summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/libANGLE
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /gfx/angle/src/libANGLE
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'gfx/angle/src/libANGLE')
-rwxr-xr-xgfx/angle/src/libANGLE/AttributeMap.cpp93
-rwxr-xr-xgfx/angle/src/libANGLE/AttributeMap.h45
-rwxr-xr-xgfx/angle/src/libANGLE/BinaryStream.h235
-rwxr-xr-xgfx/angle/src/libANGLE/BinaryStream_unittest.cpp71
-rwxr-xr-xgfx/angle/src/libANGLE/Buffer.cpp187
-rwxr-xr-xgfx/angle/src/libANGLE/Buffer.h107
-rwxr-xr-xgfx/angle/src/libANGLE/Caps.cpp891
-rwxr-xr-xgfx/angle/src/libANGLE/Caps.h678
-rwxr-xr-xgfx/angle/src/libANGLE/Compiler.cpp194
-rwxr-xr-xgfx/angle/src/libANGLE/Compiler.h50
-rwxr-xr-xgfx/angle/src/libANGLE/Config.cpp279
-rwxr-xr-xgfx/angle/src/libANGLE/Config.h92
-rwxr-xr-xgfx/angle/src/libANGLE/Config_unittest.cpp220
-rwxr-xr-xgfx/angle/src/libANGLE/Constants.h44
-rwxr-xr-xgfx/angle/src/libANGLE/Context.cpp3593
-rwxr-xr-xgfx/angle/src/libANGLE/Context.h706
-rwxr-xr-xgfx/angle/src/libANGLE/ContextState.cpp618
-rwxr-xr-xgfx/angle/src/libANGLE/ContextState.h112
-rwxr-xr-xgfx/angle/src/libANGLE/Debug.cpp303
-rwxr-xr-xgfx/angle/src/libANGLE/Debug.h120
-rwxr-xr-xgfx/angle/src/libANGLE/Device.cpp130
-rwxr-xr-xgfx/angle/src/libANGLE/Device.h58
-rwxr-xr-xgfx/angle/src/libANGLE/Display.cpp1033
-rwxr-xr-xgfx/angle/src/libANGLE/Display.h167
-rwxr-xr-xgfx/angle/src/libANGLE/Error.cpp104
-rwxr-xr-xgfx/angle/src/libANGLE/Error.h146
-rwxr-xr-xgfx/angle/src/libANGLE/Error.inl159
-rwxr-xr-xgfx/angle/src/libANGLE/Fence.cpp126
-rwxr-xr-xgfx/angle/src/libANGLE/Fence.h79
-rwxr-xr-xgfx/angle/src/libANGLE/Fence_unittest.cpp163
-rwxr-xr-xgfx/angle/src/libANGLE/Framebuffer.cpp938
-rwxr-xr-xgfx/angle/src/libANGLE/Framebuffer.h235
-rwxr-xr-xgfx/angle/src/libANGLE/FramebufferAttachment.cpp241
-rwxr-xr-xgfx/angle/src/libANGLE/FramebufferAttachment.h201
-rwxr-xr-xgfx/angle/src/libANGLE/HandleAllocator.cpp131
-rwxr-xr-xgfx/angle/src/libANGLE/HandleAllocator.h64
-rwxr-xr-xgfx/angle/src/libANGLE/HandleAllocator_unittest.cpp138
-rwxr-xr-xgfx/angle/src/libANGLE/HandleRangeAllocator.cpp225
-rwxr-xr-xgfx/angle/src/libANGLE/HandleRangeAllocator.h59
-rwxr-xr-xgfx/angle/src/libANGLE/HandleRangeAllocator_unittest.cpp275
-rwxr-xr-xgfx/angle/src/libANGLE/Image.cpp193
-rwxr-xr-xgfx/angle/src/libANGLE/Image.h92
-rwxr-xr-xgfx/angle/src/libANGLE/ImageIndex.cpp207
-rwxr-xr-xgfx/angle/src/libANGLE/ImageIndex.h83
-rwxr-xr-xgfx/angle/src/libANGLE/ImageIndexIterator_unittest.cpp122
-rwxr-xr-xgfx/angle/src/libANGLE/Image_unittest.cpp137
-rwxr-xr-xgfx/angle/src/libANGLE/IndexRangeCache.cpp113
-rwxr-xr-xgfx/angle/src/libANGLE/IndexRangeCache.h60
-rwxr-xr-xgfx/angle/src/libANGLE/Path.cpp78
-rwxr-xr-xgfx/angle/src/libANGLE/Path.h71
-rwxr-xr-xgfx/angle/src/libANGLE/Platform.cpp35
-rwxr-xr-xgfx/angle/src/libANGLE/Program.cpp2961
-rwxr-xr-xgfx/angle/src/libANGLE/Program.h504
-rwxr-xr-xgfx/angle/src/libANGLE/Program_unittest.cpp42
-rwxr-xr-xgfx/angle/src/libANGLE/Query.cpp87
-rwxr-xr-xgfx/angle/src/libANGLE/Query.h59
-rwxr-xr-xgfx/angle/src/libANGLE/RefCountObject.h139
-rwxr-xr-xgfx/angle/src/libANGLE/Renderbuffer.cpp173
-rwxr-xr-xgfx/angle/src/libANGLE/Renderbuffer.h86
-rwxr-xr-xgfx/angle/src/libANGLE/ResourceManager.cpp562
-rwxr-xr-xgfx/angle/src/libANGLE/ResourceManager.h124
-rwxr-xr-xgfx/angle/src/libANGLE/ResourceManager_unittest.cpp67
-rwxr-xr-xgfx/angle/src/libANGLE/Sampler.cpp158
-rwxr-xr-xgfx/angle/src/libANGLE/Sampler.h82
-rwxr-xr-xgfx/angle/src/libANGLE/Shader.cpp432
-rwxr-xr-xgfx/angle/src/libANGLE/Shader.h154
-rwxr-xr-xgfx/angle/src/libANGLE/State.cpp2014
-rwxr-xr-xgfx/angle/src/libANGLE/State.h497
-rwxr-xr-xgfx/angle/src/libANGLE/Stream.cpp271
-rwxr-xr-xgfx/angle/src/libANGLE/Stream.h142
-rwxr-xr-xgfx/angle/src/libANGLE/Surface.cpp336
-rwxr-xr-xgfx/angle/src/libANGLE/Surface.h183
-rwxr-xr-xgfx/angle/src/libANGLE/Surface_unittest.cpp72
-rwxr-xr-xgfx/angle/src/libANGLE/Texture.cpp1153
-rwxr-xr-xgfx/angle/src/libANGLE/Texture.h398
-rw-r--r--gfx/angle/src/libANGLE/Thread.cpp88
-rw-r--r--gfx/angle/src/libANGLE/Thread.h57
-rwxr-xr-xgfx/angle/src/libANGLE/TransformFeedback.cpp206
-rwxr-xr-xgfx/angle/src/libANGLE/TransformFeedback.h94
-rwxr-xr-xgfx/angle/src/libANGLE/TransformFeedback_unittest.cpp148
-rwxr-xr-xgfx/angle/src/libANGLE/Uniform.cpp160
-rwxr-xr-xgfx/angle/src/libANGLE/Uniform.h74
-rwxr-xr-xgfx/angle/src/libANGLE/Version.h36
-rwxr-xr-xgfx/angle/src/libANGLE/Version.inl59
-rwxr-xr-xgfx/angle/src/libANGLE/VertexArray.cpp138
-rwxr-xr-xgfx/angle/src/libANGLE/VertexArray.h130
-rwxr-xr-xgfx/angle/src/libANGLE/VertexAttribute.cpp74
-rwxr-xr-xgfx/angle/src/libANGLE/VertexAttribute.h72
-rwxr-xr-xgfx/angle/src/libANGLE/VertexAttribute.inl76
-rw-r--r--gfx/angle/src/libANGLE/Workarounds.h25
-rwxr-xr-xgfx/angle/src/libANGLE/angletypes.cpp144
-rwxr-xr-xgfx/angle/src/libANGLE/angletypes.h341
-rwxr-xr-xgfx/angle/src/libANGLE/angletypes.inl44
-rw-r--r--gfx/angle/src/libANGLE/es3_copy_conversion_formats.json44
-rw-r--r--gfx/angle/src/libANGLE/es3_copy_conversion_table_autogen.cpp171
-rw-r--r--gfx/angle/src/libANGLE/es3_format_type_combinations.json171
-rwxr-xr-xgfx/angle/src/libANGLE/features.h53
-rw-r--r--gfx/angle/src/libANGLE/format_map_autogen.cpp1530
-rw-r--r--gfx/angle/src/libANGLE/format_map_data.json130
-rwxr-xr-xgfx/angle/src/libANGLE/formatutils.cpp1656
-rwxr-xr-xgfx/angle/src/libANGLE/formatutils.h301
-rw-r--r--gfx/angle/src/libANGLE/gen_copy_conversion_table.py91
-rw-r--r--gfx/angle/src/libANGLE/gen_format_map.py187
-rwxr-xr-xgfx/angle/src/libANGLE/histogram_macros.h107
-rwxr-xr-xgfx/angle/src/libANGLE/moz.build407
-rwxr-xr-xgfx/angle/src/libANGLE/queryconversions.cpp219
-rwxr-xr-xgfx/angle/src/libANGLE/queryconversions.h70
-rw-r--r--gfx/angle/src/libANGLE/queryutils.cpp772
-rw-r--r--gfx/angle/src/libANGLE/queryutils.h79
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/BufferImpl.h54
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/BufferImpl_mock.h42
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/CompilerImpl.h34
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/ContextImpl.cpp113
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/ContextImpl.h153
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/DeviceImpl.cpp22
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/DeviceImpl.h37
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/DisplayImpl.cpp64
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/DisplayImpl.h104
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/EGLImplFactory.h71
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/FenceNVImpl.h34
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/FenceSyncImpl.h35
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/Format.h101
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/Format_ID_autogen.inl138
-rw-r--r--gfx/angle/src/libANGLE/renderer/Format_table_autogen.cpp157
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h35
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/FramebufferImpl.h83
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/FramebufferImpl_mock.h67
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/GLImplFactory.h88
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/ImageImpl.h32
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/ImageImpl_mock.h28
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/PathImpl.h36
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/ProgramImpl.h88
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/ProgramImpl_mock.h77
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/QueryImpl.h44
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/RenderbufferImpl.h38
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h35
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/SamplerImpl.h25
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/ShaderImpl.h40
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/StreamProducerImpl.h39
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/SurfaceImpl.cpp28
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/SurfaceImpl.h63
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/TextureImpl.cpp50
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/TextureImpl.h101
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/TextureImpl_mock.h61
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/TransformFeedbackImpl.h38
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h41
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/VertexArrayImpl.h31
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/angle_format.py45
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/angle_format_data.json21
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/angle_format_map.json127
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp188
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/BufferD3D.h79
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp20
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.h33
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp102
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.h39
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp371
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.h89
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp1087
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h103
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp135
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h56
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp381
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h130
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp333
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h56
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp42
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/ImageD3D.h88
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp196
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.h100
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp354
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.h93
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp23
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h38
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp2301
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.h414
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp36
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h46
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp96
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h49
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp372
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/RendererD3D.h317
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/SamplerD3D.h25
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp227
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.h84
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp61
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h54
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp402
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h121
-rw-r--r--gfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp34
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h59
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp3086
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/TextureD3D.h505
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/TextureStorage.h58
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp405
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.h175
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp280
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.h159
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp589
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.h143
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h111
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp2250
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h295
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp1556
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h156
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp672
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h98
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp270
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h128
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp118
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h37
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp237
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h59
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp441
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h88
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp643
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h92
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp167
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h49
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp651
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h120
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h39
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp299
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h89
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp400
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h67
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp473
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h114
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp444
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h131
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp4614
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h580
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp97
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h55
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp1120
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h202
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp102
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h44
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp867
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h108
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp3390
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h425
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp102
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h54
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp100
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h45
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp245
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h62
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp191
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h58
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h40
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl386
-rw-r--r--gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json118
-rw-r--r--gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp516
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json1279
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp2447
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h49
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp1023
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h71
-rw-r--r--gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_format_table.py134
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_support_tables.py281
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py360
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp2096
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h419
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl77
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl119
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl145
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl146
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl56
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl99
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h165
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h229
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h128
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h128
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h311
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h176
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h195
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h175
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h195
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h130
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h195
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h130
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h177
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h191
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h155
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h145
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h196
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h160
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h185
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h156
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h198
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h167
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h167
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h162
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h174
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h174
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h198
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h167
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h167
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h162
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h174
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h174
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h196
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h165
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h165
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h160
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h172
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h172
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h176
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h157
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h157
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h149
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h164
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h164
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h101
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h110
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h101
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h110
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h82
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h92
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h84
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h84
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h278
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h256
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h265
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h286
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h270
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h277
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h286
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h270
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h277
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/generate_shaders.bat134
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json490
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json74
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp35
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h105
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp1821
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h77
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp242
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h52
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp229
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h92
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp356
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp276
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h131
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp126
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h50
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp355
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h93
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp460
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp694
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h97
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp112
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h50
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp258
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h126
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp36
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h29
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp94
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h38
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp410
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h54
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp822
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h80
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp167
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h49
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp39
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h35
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp189
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h48
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp163
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h98
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp3032
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h487
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h108
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp47
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h35
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp945
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h209
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp442
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h71
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp617
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h134
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h29
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp165
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h50
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp255
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h65
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp659
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h94
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp659
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h95
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps33
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs43
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h84
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h66
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h94
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h61
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h66
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/generate_shaders.bat63
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h200
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h41
-rw-r--r--gfx/angle/src/libANGLE/renderer/driver_utils.cpp81
-rw-r--r--gfx/angle/src/libANGLE/renderer/driver_utils.h57
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gen_angle_format_table.py272
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gen_load_functions_table.py191
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp486
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/BlitGL.h83
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp204
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/BufferGL.h62
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/CompilerGL.cpp91
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/CompilerGL.h33
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/ContextGL.cpp370
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/ContextGL.h183
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/DisplayGL.cpp103
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/DisplayGL.h62
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/FeatureSupportGL.md107
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/FenceNVGL.cpp51
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/FenceNVGL.h36
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.cpp67
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.h36
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp553
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/FramebufferGL.h113
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp2316
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/FunctionsGL.h791
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/PathGL.cpp38
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/PathGL.h44
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/ProgramGL.cpp588
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/ProgramGL.h118
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/QueryGL.cpp222
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/QueryGL.h64
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.cpp96
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.h52
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/RendererGL.cpp561
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/RendererGL.h194
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/SamplerGL.cpp73
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/SamplerGL.h40
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/ShaderGL.cpp143
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/ShaderGL.h44
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp1742
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/StateManagerGL.h290
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/SurfaceGL.cpp36
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/SurfaceGL.h36
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/TextureGL.cpp1039
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/TextureGL.h145
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp131
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h53
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp499
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.h100
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h126
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.h77
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm275
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h65
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm143
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h100
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm332
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp116
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h43
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp340
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h91
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp74
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h42
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp39
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h36
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp132
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h55
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp40
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h37
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp385
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h78
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h131
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp945
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h211
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp98
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h52
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp553
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/formatutilsgl.h129
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/functionsgl_enums.h1375
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/functionsgl_typedefs.h758
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp981
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h151
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md204
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp398
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h96
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp143
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h64
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h26
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp244
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h73
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h52
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/glx/platform_glx.h190
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp1045
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/renderergl_utils.h61
-rw-r--r--gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp384
-rw-r--r--gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h86
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp553
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h106
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp741
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h112
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp181
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h94
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp196
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h74
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp178
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h64
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h43
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp85
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h32
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/load_functions_data.json562
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/load_functions_table.h22
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/load_functions_table_autogen.cpp2311
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/BufferNULL.cpp74
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/BufferNULL.h43
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/CompilerNULL.cpp37
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/CompilerNULL.h32
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/ContextNULL.cpp175
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/ContextNULL.h95
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/DeviceNULL.cpp48
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/DeviceNULL.h32
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/DisplayNULL.cpp168
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/DisplayNULL.h82
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/FenceNVNULL.cpp43
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/FenceNVNULL.h31
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/FenceSyncNULL.cpp49
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/FenceSyncNULL.h32
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/FramebufferNULL.cpp131
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/FramebufferNULL.h70
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/ImageNULL.cpp37
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/ImageNULL.h30
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/PathNULL.cpp40
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/PathNULL.h35
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/ProgramNULL.cpp212
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/ProgramNULL.h101
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/QueryNULL.cpp73
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/QueryNULL.h36
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/RenderbufferNULL.cpp46
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/RenderbufferNULL.h34
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/SamplerNULL.cpp25
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/SamplerNULL.h27
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/ShaderNULL.cpp44
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/ShaderNULL.h35
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/SurfaceNULL.cpp103
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/SurfaceNULL.h46
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/TextureNULL.cpp143
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/TextureNULL.h89
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.cpp57
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.h35
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/VertexArrayNULL.cpp25
-rw-r--r--gfx/angle/src/libANGLE/renderer/null/VertexArrayNULL.h27
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/renderer_utils.cpp292
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/renderer_utils.h124
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp74
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/BufferVk.h43
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/CompilerVk.cpp37
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/CompilerVk.h32
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp254
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/ContextVk.h126
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/DeviceVk.cpp48
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/DeviceVk.h32
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp168
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/DisplayVk.h85
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/FenceNVVk.cpp43
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/FenceNVVk.h31
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.cpp49
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.h32
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp131
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/FramebufferVk.h70
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp37
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/ImageVk.h30
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp212
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/ProgramVk.h100
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp73
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/QueryVk.h36
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp53
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h37
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp66
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/RendererVk.h46
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/SamplerVk.cpp25
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/SamplerVk.h27
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/ShaderVk.cpp44
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/ShaderVk.h35
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp103
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h46
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp150
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/TextureVk.h92
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp57
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h35
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp25
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h27
-rwxr-xr-xgfx/angle/src/libANGLE/signal_utils.cpp103
-rwxr-xr-xgfx/angle/src/libANGLE/signal_utils.h74
-rwxr-xr-xgfx/angle/src/libANGLE/signal_utils_unittest.cpp38
-rwxr-xr-xgfx/angle/src/libANGLE/validationEGL.cpp1616
-rwxr-xr-xgfx/angle/src/libANGLE/validationEGL.h111
-rwxr-xr-xgfx/angle/src/libANGLE/validationES.cpp5290
-rwxr-xr-xgfx/angle/src/libANGLE/validationES.h561
-rwxr-xr-xgfx/angle/src/libANGLE/validationES2.cpp3867
-rwxr-xr-xgfx/angle/src/libANGLE/validationES2.h375
-rwxr-xr-xgfx/angle/src/libANGLE/validationES3.cpp2038
-rwxr-xr-xgfx/angle/src/libANGLE/validationES3.h369
-rwxr-xr-xgfx/angle/src/libANGLE/validationES31.cpp67
-rwxr-xr-xgfx/angle/src/libANGLE/validationES31.h28
-rwxr-xr-xgfx/angle/src/libANGLE/validationES_unittest.cpp140
603 files changed, 160460 insertions, 0 deletions
diff --git a/gfx/angle/src/libANGLE/AttributeMap.cpp b/gfx/angle/src/libANGLE/AttributeMap.cpp
new file mode 100755
index 000000000..73d94924d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/AttributeMap.cpp
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 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"
+
+namespace egl
+{
+
+AttributeMap::AttributeMap()
+{
+}
+
+void AttributeMap::insert(EGLAttrib key, EGLAttrib value)
+{
+ mAttributes[key] = value;
+}
+
+bool AttributeMap::contains(EGLAttrib key) const
+{
+ return (mAttributes.find(key) != mAttributes.end());
+}
+
+EGLAttrib AttributeMap::get(EGLAttrib key, EGLAttrib defaultValue) const
+{
+ std::map<EGLAttrib, EGLAttrib>::const_iterator iter = mAttributes.find(key);
+ return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue;
+}
+
+EGLint AttributeMap::getAsInt(EGLAttrib key, EGLint defaultValue) const
+{
+ return static_cast<EGLint>(
+ get(static_cast<EGLAttrib>(key), static_cast<EGLAttrib>(defaultValue)));
+}
+
+bool AttributeMap::isEmpty() const
+{
+ return mAttributes.empty();
+}
+
+std::vector<EGLint> AttributeMap::toIntVector() const
+{
+ std::vector<EGLint> ret;
+ for (const auto &pair : mAttributes)
+ {
+ 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 mAttributes.begin();
+}
+
+AttributeMap::const_iterator AttributeMap::end() const
+{
+ return mAttributes.end();
+}
+
+// static
+AttributeMap AttributeMap::CreateFromIntArray(const EGLint *attributes)
+{
+ AttributeMap map;
+ if (attributes)
+ {
+ for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
+ {
+ map.insert(static_cast<EGLAttrib>(curAttrib[0]), static_cast<EGLAttrib>(curAttrib[1]));
+ }
+ }
+ return map;
+}
+
+// static
+AttributeMap AttributeMap::CreateFromAttribArray(const EGLAttrib *attributes)
+{
+ AttributeMap map;
+ if (attributes)
+ {
+ for (const EGLAttrib *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
+ {
+ map.insert(curAttrib[0], curAttrib[1]);
+ }
+ }
+ return map;
+}
+}
diff --git a/gfx/angle/src/libANGLE/AttributeMap.h b/gfx/angle/src/libANGLE/AttributeMap.h
new file mode 100755
index 000000000..01bba7477
--- /dev/null
+++ b/gfx/angle/src/libANGLE/AttributeMap.h
@@ -0,0 +1,45 @@
+//
+// Copyright (c) 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 <EGL/egl.h>
+
+#include <map>
+#include <vector>
+
+namespace egl
+{
+
+class AttributeMap final
+{
+ public:
+ AttributeMap();
+
+ void insert(EGLAttrib key, EGLAttrib value);
+ bool contains(EGLAttrib key) const;
+ EGLAttrib get(EGLAttrib key, EGLAttrib defaultValue) const;
+ EGLint getAsInt(EGLAttrib key, EGLint defaultValue) const;
+ bool isEmpty() const;
+ std::vector<EGLint> toIntVector() const;
+
+ typedef std::map<EGLAttrib, EGLAttrib>::const_iterator const_iterator;
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ static AttributeMap CreateFromIntArray(const EGLint *attributes);
+ static AttributeMap CreateFromAttribArray(const EGLAttrib *attributes);
+
+ private:
+ std::map<EGLAttrib, EGLAttrib> mAttributes;
+};
+
+}
+
+#endif // LIBANGLE_ATTRIBUTEMAP_H_
diff --git a/gfx/angle/src/libANGLE/BinaryStream.h b/gfx/angle/src/libANGLE/BinaryStream.h
new file mode 100755
index 000000000..3f2ae6986
--- /dev/null
+++ b/gfx/angle/src/libANGLE/BinaryStream.h
@@ -0,0 +1,235 @@
+//
+// Copyright (c) 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 <cstddef>
+#include <string>
+#include <vector>
+#include <stdint.h>
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+
+namespace gl
+{
+
+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()
+ {
+ int value = 0;
+ read(&value);
+ return static_cast<IntT>(value);
+ }
+
+ template <class IntT>
+ void readInt(IntT *outValue)
+ {
+ *outValue = readInt<IntT>();
+ }
+
+ 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();
+ }
+
+ 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;
+ }
+
+ 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()
+ {
+ }
+
+ // writeInt also handles bool types
+ template <class IntT>
+ void writeInt(IntT param)
+ {
+ ASSERT(angle::IsValueInRangeForNumericType<int>(param));
+ int intValue = static_cast<int>(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);
+ }
+ }
+
+ 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);
+ }
+
+ size_t length() const
+ {
+ return mData.size();
+ }
+
+ const void* data() const
+ {
+ return mData.size() ? &mData[0] : NULL;
+ }
+
+ private:
+ std::vector<char> mData;
+
+ 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));
+ }
+
+};
+}
+
+#endif // LIBANGLE_BINARYSTREAM_H_
diff --git a/gfx/angle/src/libANGLE/BinaryStream_unittest.cpp b/gfx/angle/src/libANGLE/BinaryStream_unittest.cpp
new file mode 100755
index 000000000..963f48911
--- /dev/null
+++ b/gfx/angle/src/libANGLE/BinaryStream_unittest.cpp
@@ -0,0 +1,71 @@
+//
+// Copyright (c) 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.
+//
+
+// BinaryStream_unittest.cpp: Unit tests of the binary stream classes.
+
+#include <gtest/gtest.h>
+
+#include "libANGLE/BinaryStream.h"
+
+namespace angle
+{
+
+// Test that errors are properly generated for overflows.
+TEST(BinaryInputStream, Overflow)
+{
+ const uint8_t goodValue = 2;
+ const uint8_t badValue = 255;
+
+ const size_t dataSize = 1024;
+ const size_t slopSize = 1024;
+
+ std::vector<uint8_t> data(dataSize + slopSize);
+ std::fill(data.begin(), data.begin() + dataSize, goodValue);
+ std::fill(data.begin() + dataSize, data.end(), badValue);
+
+ std::vector<uint8_t> outputData(dataSize);
+
+ auto checkDataIsSafe = [=](uint8_t item)
+ {
+ return item == goodValue;
+ };
+
+ {
+ // One large read
+ gl::BinaryInputStream stream(data.data(), dataSize);
+ stream.readBytes(outputData.data(), dataSize);
+ ASSERT_FALSE(stream.error());
+ ASSERT_TRUE(std::all_of(outputData.begin(), outputData.end(), checkDataIsSafe));
+ ASSERT_TRUE(stream.endOfStream());
+ }
+
+ {
+ // Two half-sized reads
+ gl::BinaryInputStream stream(data.data(), dataSize);
+ stream.readBytes(outputData.data(), dataSize / 2);
+ ASSERT_FALSE(stream.error());
+ stream.readBytes(outputData.data() + dataSize / 2, dataSize / 2);
+ ASSERT_FALSE(stream.error());
+ ASSERT_TRUE(std::all_of(outputData.begin(), outputData.end(), checkDataIsSafe));
+ ASSERT_TRUE(stream.endOfStream());
+ }
+
+ {
+ // One large read that is too big
+ gl::BinaryInputStream stream(data.data(), dataSize);
+ stream.readBytes(outputData.data(), dataSize + 1);
+ ASSERT_TRUE(stream.error());
+ }
+
+ {
+ // Two reads, one that overflows the offset
+ gl::BinaryInputStream stream(data.data(), dataSize);
+ stream.readBytes(outputData.data(), dataSize - 1);
+ ASSERT_FALSE(stream.error());
+ stream.readBytes(outputData.data(), std::numeric_limits<size_t>::max() - dataSize - 2);
+ }
+}
+}
diff --git a/gfx/angle/src/libANGLE/Buffer.cpp b/gfx/angle/src/libANGLE/Buffer.cpp
new file mode 100755
index 000000000..c69d1c671
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Buffer.cpp
@@ -0,0 +1,187 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/renderer/BufferImpl.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace gl
+{
+
+BufferState::BufferState()
+ : mLabel(),
+ mUsage(GL_STATIC_DRAW),
+ mSize(0),
+ mAccessFlags(0),
+ mAccess(GL_WRITE_ONLY_OES),
+ mMapped(GL_FALSE),
+ mMapPointer(nullptr),
+ mMapOffset(0),
+ mMapLength(0)
+{
+}
+
+BufferState::~BufferState()
+{
+}
+
+Buffer::Buffer(rx::GLImplFactory *factory, GLuint id)
+ : RefCountObject(id), mImpl(factory->createBuffer(mState))
+{
+}
+
+Buffer::~Buffer()
+{
+ SafeDelete(mImpl);
+}
+
+void Buffer::setLabel(const std::string &label)
+{
+ mState.mLabel = label;
+}
+
+const std::string &Buffer::getLabel() const
+{
+ return mState.mLabel;
+}
+
+Error Buffer::bufferData(GLenum target, const void *data, GLsizeiptr size, GLenum usage)
+{
+ ANGLE_TRY(mImpl->setData(target, data, size, usage));
+
+ mIndexRangeCache.clear();
+ mState.mUsage = usage;
+ mState.mSize = size;
+
+ return NoError();
+}
+
+Error Buffer::bufferSubData(GLenum target, const void *data, GLsizeiptr size, GLintptr offset)
+{
+ ANGLE_TRY(mImpl->setSubData(target, data, size, offset));
+
+ mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(size));
+
+ return NoError();
+}
+
+Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
+{
+ ANGLE_TRY(mImpl->copySubData(source->getImplementation(), sourceOffset, destOffset, size));
+
+ mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset), static_cast<unsigned int>(size));
+
+ return NoError();
+}
+
+Error Buffer::map(GLenum access)
+{
+ ASSERT(!mState.mMapped);
+
+ Error error = mImpl->map(access, &mState.mMapPointer);
+ if (error.isError())
+ {
+ mState.mMapPointer = nullptr;
+ return error;
+ }
+
+ 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();
+
+ return error;
+}
+
+Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access)
+{
+ ASSERT(!mState.mMapped);
+ ASSERT(offset + length <= mState.mSize);
+
+ Error error = mImpl->mapRange(offset, length, access, &mState.mMapPointer);
+ if (error.isError())
+ {
+ mState.mMapPointer = nullptr;
+ return error;
+ }
+
+ 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));
+ }
+
+ return error;
+}
+
+Error Buffer::unmap(GLboolean *result)
+{
+ ASSERT(mState.mMapped);
+
+ Error error = mImpl->unmap(result);
+ if (error.isError())
+ {
+ *result = GL_FALSE;
+ return error;
+ }
+
+ mState.mMapped = GL_FALSE;
+ mState.mMapPointer = nullptr;
+ mState.mMapOffset = 0;
+ mState.mMapLength = 0;
+ mState.mAccess = GL_WRITE_ONLY_OES;
+ mState.mAccessFlags = 0;
+
+ return error;
+}
+
+void Buffer::onTransformFeedback()
+{
+ mIndexRangeCache.clear();
+}
+
+void Buffer::onPixelUnpack()
+{
+ mIndexRangeCache.clear();
+}
+
+Error Buffer::getIndexRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ IndexRange *outRange) const
+{
+ if (mIndexRangeCache.findRange(type, offset, count, primitiveRestartEnabled, outRange))
+ {
+ return NoError();
+ }
+
+ ANGLE_TRY(mImpl->getIndexRange(type, offset, count, primitiveRestartEnabled, outRange));
+
+ mIndexRangeCache.addRange(type, offset, count, primitiveRestartEnabled, *outRange);
+
+ return NoError();
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/Buffer.h b/gfx/angle/src/libANGLE/Buffer.h
new file mode 100755
index 000000000..dba4d5adf
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Buffer.h
@@ -0,0 +1,107 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/angleutils.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/IndexRangeCache.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class BufferImpl;
+class GLImplFactory;
+};
+
+namespace gl
+{
+class Buffer;
+
+class BufferState final : angle::NonCopyable
+{
+ public:
+ BufferState();
+ ~BufferState();
+
+ const std::string &getLabel();
+
+ GLenum getUsage() const { return mUsage; }
+ GLbitfield getAccessFlags() const { return mAccessFlags; }
+ GLenum getAccess() const { return mAccess; }
+ GLboolean isMapped() const { return mMapped; }
+ GLvoid *getMapPointer() const { return mMapPointer; }
+ GLint64 getMapOffset() const { return mMapOffset; }
+ GLint64 getMapLength() const { return mMapLength; }
+ GLint64 getSize() const { return mSize; }
+
+ private:
+ friend class Buffer;
+
+ std::string mLabel;
+
+ GLenum mUsage;
+ GLint64 mSize;
+ GLbitfield mAccessFlags;
+ GLenum mAccess;
+ GLboolean mMapped;
+ GLvoid *mMapPointer;
+ GLint64 mMapOffset;
+ GLint64 mMapLength;
+};
+
+class Buffer final : public RefCountObject, public LabeledObject
+{
+ public:
+ Buffer(rx::GLImplFactory *factory, GLuint id);
+ ~Buffer() override;
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ Error bufferData(GLenum target, const void *data, GLsizeiptr size, GLenum usage);
+ Error bufferSubData(GLenum target, const void *data, GLsizeiptr size, GLintptr offset);
+ Error copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
+ Error map(GLenum access);
+ Error mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access);
+ Error unmap(GLboolean *result);
+
+ void onTransformFeedback();
+ void onPixelUnpack();
+
+ Error getIndexRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ IndexRange *outRange) const;
+
+ GLenum getUsage() const { return mState.mUsage; }
+ GLbitfield getAccessFlags() const { return mState.mAccessFlags; }
+ GLenum getAccess() const { return mState.mAccess; }
+ GLboolean isMapped() const { return mState.mMapped; }
+ GLvoid *getMapPointer() const { return mState.mMapPointer; }
+ GLint64 getMapOffset() const { return mState.mMapOffset; }
+ GLint64 getMapLength() const { return mState.mMapLength; }
+ GLint64 getSize() const { return mState.mSize; }
+
+ rx::BufferImpl *getImplementation() const { return mImpl; }
+
+ private:
+ BufferState mState;
+ rx::BufferImpl *mImpl;
+
+ mutable IndexRangeCache mIndexRangeCache;
+};
+
+}
+
+#endif // LIBANGLE_BUFFER_H_
diff --git a/gfx/angle/src/libANGLE/Caps.cpp b/gfx/angle/src/libANGLE/Caps.cpp
new file mode 100755
index 000000000..d8e486d3d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Caps.cpp
@@ -0,0 +1,891 @@
+//
+// Copyright (c) 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/debug.h"
+#include "common/angleutils.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()
+ : texturable(false),
+ filterable(false),
+ renderable(false),
+ sampleCounts()
+{
+}
+
+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;
+}
+
+void TextureCapsMap::insert(GLenum internalFormat, const TextureCaps &caps)
+{
+ mCapsMap[internalFormat] = caps;
+}
+
+void TextureCapsMap::remove(GLenum internalFormat)
+{
+ InternalFormatToCapsMap::iterator i = mCapsMap.find(internalFormat);
+ if (i != mCapsMap.end())
+ {
+ mCapsMap.erase(i);
+ }
+}
+
+void TextureCapsMap::clear()
+{
+ mCapsMap.clear();
+}
+
+const TextureCaps &TextureCapsMap::get(GLenum internalFormat) const
+{
+ static TextureCaps defaultUnsupportedTexture;
+ InternalFormatToCapsMap::const_iterator iter = mCapsMap.find(internalFormat);
+ return (iter != mCapsMap.end()) ? iter->second : defaultUnsupportedTexture;
+}
+
+TextureCapsMap::const_iterator TextureCapsMap::begin() const
+{
+ return mCapsMap.begin();
+}
+
+TextureCapsMap::const_iterator TextureCapsMap::end() const
+{
+ return mCapsMap.end();
+}
+
+size_t TextureCapsMap::size() const
+{
+ return mCapsMap.size();
+}
+
+Extensions::Extensions()
+ : elementIndexUint(false),
+ packedDepthStencil(false),
+ getProgramBinary(false),
+ rgb8rgba8(false),
+ textureFormatBGRA8888(false),
+ readFormatBGRA(false),
+ pixelBufferObject(false),
+ mapBuffer(false),
+ mapBufferRange(false),
+ colorBufferHalfFloat(false),
+ textureHalfFloat(false),
+ textureHalfFloatLinear(false),
+ textureFloat(false),
+ textureFloatLinear(false),
+ textureRG(false),
+ textureCompressionDXT1(false),
+ textureCompressionDXT3(false),
+ textureCompressionDXT5(false),
+ textureCompressionASTCHDR(false),
+ textureCompressionASTCLDR(false),
+ compressedETC1RGB8Texture(false),
+ depthTextures(false),
+ depth32(false),
+ textureStorage(false),
+ textureNPOT(false),
+ drawBuffers(false),
+ textureFilterAnisotropic(false),
+ maxTextureAnisotropy(false),
+ occlusionQueryBoolean(false),
+ fence(false),
+ timerQuery(false),
+ disjointTimerQuery(false),
+ queryCounterBitsTimeElapsed(0),
+ queryCounterBitsTimestamp(0),
+ robustness(false),
+ blendMinMax(false),
+ framebufferBlit(false),
+ framebufferMultisample(false),
+ instancedArrays(false),
+ packReverseRowOrder(false),
+ standardDerivatives(false),
+ shaderTextureLOD(false),
+ shaderFramebufferFetch(false),
+ ARMshaderFramebufferFetch(false),
+ NVshaderFramebufferFetch(false),
+ fragDepth(false),
+ textureUsage(false),
+ translatedShaderSource(false),
+ fboRenderMipmap(false),
+ discardFramebuffer(false),
+ debugMarker(false),
+ eglImage(false),
+ eglImageExternal(false),
+ eglImageExternalEssl3(false),
+ eglStreamConsumerExternal(false),
+ unpackSubimage(false),
+ packSubimage(false),
+ vertexArrayObject(false),
+ debug(false),
+ maxDebugMessageLength(0),
+ maxDebugLoggedMessages(0),
+ maxDebugGroupStackDepth(0),
+ maxLabelLength(0),
+ noError(false),
+ lossyETCDecode(false),
+ bindUniformLocation(false),
+ syncQuery(false),
+ copyTexture(false),
+ copyCompressedTexture(false),
+ webglCompatibility(false),
+ bindGeneratesResource(false),
+ robustClientMemory(false),
+ textureSRGBDecode(false),
+ sRGBWriteControl(false),
+ colorBufferFloat(false),
+ multisampleCompatibility(false),
+ framebufferMixedSamples(false),
+ textureNorm16(false),
+ pathRendering(false)
+{
+}
+
+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()
+ : noFrontFacingSupport(false),
+ noSampleAlphaToCoverageSupport(false),
+ attributeZeroRequiresZeroDivisorInEXT(false),
+ noSeparateStencilRefsAndMasks(false),
+ shadersRequireIndexedLoopValidation(false),
+ noSimultaneousConstantColorAndAlphaBlendFunc(false)
+{
+}
+
+static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vector<GLenum> &requiredFormats,
+ bool requiresTexturing, bool requiresFiltering, bool requiresRendering)
+{
+ for (size_t i = 0; i < requiredFormats.size(); i++)
+ {
+ const TextureCaps &cap = textureCaps.get(requiredFormats[i]);
+
+ if (requiresTexturing && !cap.texturable)
+ {
+ return false;
+ }
+
+ if (requiresFiltering && !cap.filterable)
+ {
+ return false;
+ }
+
+ if (requiresRendering && !cap.renderable)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Check for GL_OES_packed_depth_stencil
+static bool DeterminePackedDepthStencilSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_DEPTH24_STENCIL8);
+
+ return GetFormatSupport(textureCaps, requiredFormats, false, false, true);
+}
+
+// Checks for GL_OES_rgb8_rgba8 support
+static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_RGB8);
+ requiredFormats.push_back(GL_RGBA8);
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
+}
+
+// Checks for GL_EXT_texture_format_BGRA8888 support
+static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_BGRA8_EXT);
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
+}
+
+// Checks for GL_OES_color_buffer_half_float support
+static bool DetermineColorBufferHalfFloatSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_RGBA16F);
+ requiredFormats.push_back(GL_RGB16F);
+ requiredFormats.push_back(GL_RG16F);
+ requiredFormats.push_back(GL_R16F);
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+}
+
+// Checks for GL_OES_texture_half_float support
+static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_RGB16F);
+ requiredFormats.push_back(GL_RGBA16F);
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+}
+
+// Checks for GL_OES_texture_half_float_linear support
+static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_RGB16F);
+ requiredFormats.push_back(GL_RGBA16F);
+
+ return DetermineHalfFloatTextureSupport(textureCaps) &&
+ GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Checks for GL_OES_texture_float support
+static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_RGB32F);
+ requiredFormats.push_back(GL_RGBA32F);
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+}
+
+// Checks for GL_OES_texture_float_linear support
+static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_RGB32F);
+ requiredFormats.push_back(GL_RGBA32F);
+
+ return DetermineFloatTextureSupport(textureCaps) &&
+ GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Checks for GL_EXT_texture_rg support
+static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps, bool checkHalfFloatFormats, bool checkFloatFormats)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_R8);
+ requiredFormats.push_back(GL_RG8);
+ if (checkHalfFloatFormats)
+ {
+ requiredFormats.push_back(GL_R16F);
+ requiredFormats.push_back(GL_RG16F);
+ }
+ if (checkFloatFormats)
+ {
+ requiredFormats.push_back(GL_R32F);
+ requiredFormats.push_back(GL_RG32F);
+ }
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_EXT_texture_compression_dxt1
+static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_ANGLE_texture_compression_dxt3
+static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_ANGLE_texture_compression_dxt5
+static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_KHR_texture_compression_astc_hdr and GL_KHR_texture_compression_astc_ldr
+static bool DetermineASTCTextureSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_4x4_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_5x4_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_5x5_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_6x5_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_6x6_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_8x5_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_8x6_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_8x8_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_10x5_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_10x6_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_10x8_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_10x10_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_12x10_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_12x12_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR);
+ requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR);
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_ETC1_RGB8_OES
+static bool DetermineETC1RGB8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_ETC1_RGB8_OES);
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_ANGLE_texture_compression_dxt5
+static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFilterFormats;
+ requiredFilterFormats.push_back(GL_SRGB8);
+ requiredFilterFormats.push_back(GL_SRGB8_ALPHA8);
+
+ std::vector<GLenum> requiredRenderFormats;
+ requiredRenderFormats.push_back(GL_SRGB8_ALPHA8);
+
+ return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false) &&
+ GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true);
+}
+
+// Check for GL_ANGLE_depth_texture
+static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_DEPTH_COMPONENT16);
+ requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES);
+ requiredFormats.push_back(GL_DEPTH24_STENCIL8_OES);
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
+}
+
+// Check for GL_OES_depth32
+static bool DetermineDepth32Support(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES);
+
+ return GetFormatSupport(textureCaps, requiredFormats, false, false, true);
+}
+
+// Check for GL_EXT_color_buffer_float
+static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFormats;
+ requiredFormats.push_back(GL_R16F);
+ requiredFormats.push_back(GL_RG16F);
+ requiredFormats.push_back(GL_RGBA16F);
+ requiredFormats.push_back(GL_R32F);
+ requiredFormats.push_back(GL_RG32F);
+ requiredFormats.push_back(GL_RGBA32F);
+ requiredFormats.push_back(GL_R11F_G11F_B10F);
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+}
+
+// Check for GL_EXT_texture_norm16
+static bool DetermineTextureNorm16Support(const TextureCapsMap &textureCaps)
+{
+ std::vector<GLenum> requiredFilterFormats;
+ requiredFilterFormats.push_back(GL_R16_EXT);
+ requiredFilterFormats.push_back(GL_RG16_EXT);
+ requiredFilterFormats.push_back(GL_RGB16_EXT);
+ requiredFilterFormats.push_back(GL_RGBA16_EXT);
+ requiredFilterFormats.push_back(GL_R16_SNORM_EXT);
+ requiredFilterFormats.push_back(GL_RG16_SNORM_EXT);
+ requiredFilterFormats.push_back(GL_RGB16_SNORM_EXT);
+ requiredFilterFormats.push_back(GL_RGBA16_SNORM_EXT);
+
+ std::vector<GLenum> requiredRenderFormats;
+ requiredFilterFormats.push_back(GL_R16_EXT);
+ requiredFilterFormats.push_back(GL_RG16_EXT);
+ requiredFilterFormats.push_back(GL_RGBA16_EXT);
+
+ return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false) &&
+ GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true);
+}
+
+void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
+{
+ packedDepthStencil = DeterminePackedDepthStencilSupport(textureCaps);
+ rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps);
+ textureFormatBGRA8888 = DetermineBGRA8TextureSupport(textureCaps);
+ colorBufferHalfFloat = DetermineColorBufferHalfFloatSupport(textureCaps);
+ textureHalfFloat = DetermineHalfFloatTextureSupport(textureCaps);
+ textureHalfFloatLinear = DetermineHalfFloatTextureFilteringSupport(textureCaps);
+ textureFloat = DetermineFloatTextureSupport(textureCaps);
+ textureFloatLinear = DetermineFloatTextureFilteringSupport(textureCaps);
+ textureRG = DetermineRGTextureSupport(textureCaps, textureHalfFloat, textureFloat);
+ textureCompressionDXT1 = DetermineDXT1TextureSupport(textureCaps);
+ textureCompressionDXT3 = DetermineDXT3TextureSupport(textureCaps);
+ textureCompressionDXT5 = DetermineDXT5TextureSupport(textureCaps);
+ textureCompressionASTCHDR = DetermineASTCTextureSupport(textureCaps);
+ textureCompressionASTCLDR = textureCompressionASTCHDR;
+ compressedETC1RGB8Texture = DetermineETC1RGB8TextureSupport(textureCaps);
+ sRGB = DetermineSRGBTextureSupport(textureCaps);
+ depthTextures = DetermineDepthTextureSupport(textureCaps);
+ depth32 = DetermineDepth32Support(textureCaps);
+ colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps);
+ textureNorm16 = DetermineTextureNorm16Support(textureCaps);
+}
+
+const ExtensionInfoMap &GetExtensionInfoMap()
+{
+ auto buildExtensionInfoMap = []() {
+ auto enableableExtension = [](ExtensionInfo::ExtensionBool member) {
+ ExtensionInfo info;
+ info.Enableable = true;
+ info.ExtensionsMember = member;
+ return info;
+ };
+
+ auto esOnlyExtension = [](ExtensionInfo::ExtensionBool member) {
+ ExtensionInfo info;
+ info.ExtensionsMember = member;
+ return info;
+ };
+
+ // clang-format off
+ ExtensionInfoMap map;
+ map["GL_OES_element_index_uint"] = enableableExtension(&Extensions::elementIndexUint);
+ map["GL_OES_packed_depth_stencil"] = esOnlyExtension(&Extensions::packedDepthStencil);
+ map["GL_OES_get_program_binary"] = esOnlyExtension(&Extensions::getProgramBinary);
+ map["GL_OES_rgb8_rgba8"] = esOnlyExtension(&Extensions::rgb8rgba8);
+ map["GL_EXT_texture_format_BGRA8888"] = esOnlyExtension(&Extensions::textureFormatBGRA8888);
+ map["GL_EXT_read_format_bgra"] = esOnlyExtension(&Extensions::readFormatBGRA);
+ map["GL_NV_pixel_buffer_object"] = esOnlyExtension(&Extensions::pixelBufferObject);
+ map["GL_OES_mapbuffer"] = esOnlyExtension(&Extensions::mapBuffer);
+ map["GL_EXT_map_buffer_range"] = esOnlyExtension(&Extensions::mapBufferRange);
+ map["GL_EXT_color_buffer_half_float"] = esOnlyExtension(&Extensions::colorBufferHalfFloat);
+ map["GL_OES_texture_half_float"] = esOnlyExtension(&Extensions::textureHalfFloat);
+ map["GL_OES_texture_half_float_linear"] = esOnlyExtension(&Extensions::textureHalfFloatLinear);
+ map["GL_OES_texture_float"] = esOnlyExtension(&Extensions::textureFloat);
+ map["GL_OES_texture_float_linear"] = esOnlyExtension(&Extensions::textureFloatLinear);
+ map["GL_EXT_texture_rg"] = esOnlyExtension(&Extensions::textureRG);
+ map["GL_EXT_texture_compression_dxt1"] = esOnlyExtension(&Extensions::textureCompressionDXT1);
+ map["GL_ANGLE_texture_compression_dxt3"] = esOnlyExtension(&Extensions::textureCompressionDXT3);
+ map["GL_ANGLE_texture_compression_dxt5"] = esOnlyExtension(&Extensions::textureCompressionDXT5);
+ map["GL_KHR_texture_compression_astc_hdr"] = esOnlyExtension(&Extensions::textureCompressionASTCHDR);
+ map["GL_KHR_texture_compression_astc_ldr"] = esOnlyExtension(&Extensions::textureCompressionASTCLDR);
+ map["GL_OES_compressed_ETC1_RGB8_texture"] = esOnlyExtension(&Extensions::compressedETC1RGB8Texture);
+ map["GL_EXT_sRGB"] = esOnlyExtension(&Extensions::sRGB);
+ map["GL_ANGLE_depth_texture"] = esOnlyExtension(&Extensions::depthTextures);
+ map["GL_OES_depth32"] = esOnlyExtension(&Extensions::depth32);
+ map["GL_EXT_texture_storage"] = esOnlyExtension(&Extensions::textureStorage);
+ map["GL_OES_texture_npot"] = esOnlyExtension(&Extensions::textureNPOT);
+ map["GL_EXT_draw_buffers"] = esOnlyExtension(&Extensions::drawBuffers);
+ map["GL_EXT_texture_filter_anisotropic"] = esOnlyExtension(&Extensions::textureFilterAnisotropic);
+ map["GL_EXT_occlusion_query_boolean"] = esOnlyExtension(&Extensions::occlusionQueryBoolean);
+ map["GL_NV_fence"] = esOnlyExtension(&Extensions::fence);
+ map["GL_ANGLE_timer_query"] = esOnlyExtension(&Extensions::timerQuery);
+ map["GL_EXT_disjoint_timer_query"] = esOnlyExtension(&Extensions::disjointTimerQuery);
+ map["GL_EXT_robustness"] = esOnlyExtension(&Extensions::robustness);
+ map["GL_EXT_blend_minmax"] = esOnlyExtension(&Extensions::blendMinMax);
+ map["GL_ANGLE_framebuffer_blit"] = esOnlyExtension(&Extensions::framebufferBlit);
+ map["GL_ANGLE_framebuffer_multisample"] = esOnlyExtension(&Extensions::framebufferMultisample);
+ map["GL_ANGLE_instanced_arrays"] = esOnlyExtension(&Extensions::instancedArrays);
+ map["GL_ANGLE_pack_reverse_row_order"] = esOnlyExtension(&Extensions::packReverseRowOrder);
+ map["GL_OES_standard_derivatives"] = esOnlyExtension(&Extensions::standardDerivatives);
+ map["GL_EXT_shader_texture_lod"] = esOnlyExtension(&Extensions::shaderTextureLOD);
+ map["GL_NV_shader_framebuffer_fetch"] = esOnlyExtension(&Extensions::NVshaderFramebufferFetch);
+ map["GL_ARM_shader_framebuffer_fetch"] = esOnlyExtension(&Extensions::ARMshaderFramebufferFetch);
+ map["GL_EXT_shader_framebuffer_fetch"] = esOnlyExtension(&Extensions::shaderFramebufferFetch);
+ map["GL_EXT_frag_depth"] = esOnlyExtension(&Extensions::fragDepth);
+ map["GL_ANGLE_texture_usage"] = esOnlyExtension(&Extensions::textureUsage);
+ map["GL_ANGLE_translated_shader_source"] = esOnlyExtension(&Extensions::translatedShaderSource);
+ map["GL_OES_fbo_render_mipmap"] = esOnlyExtension(&Extensions::fboRenderMipmap);
+ map["GL_EXT_discard_framebuffer"] = esOnlyExtension(&Extensions::discardFramebuffer);
+ map["GL_EXT_debug_marker"] = esOnlyExtension(&Extensions::debugMarker);
+ map["GL_OES_EGL_image"] = esOnlyExtension(&Extensions::eglImage);
+ map["GL_OES_EGL_image_external"] = esOnlyExtension(&Extensions::eglImageExternal);
+ map["GL_OES_EGL_image_external_essl3"] = esOnlyExtension(&Extensions::eglImageExternalEssl3);
+ map["GL_NV_EGL_stream_consumer_external"] = esOnlyExtension(&Extensions::eglStreamConsumerExternal);
+ map["GL_EXT_unpack_subimage"] = esOnlyExtension(&Extensions::unpackSubimage);
+ map["GL_NV_pack_subimage"] = esOnlyExtension(&Extensions::packSubimage);
+ map["GL_EXT_color_buffer_float"] = esOnlyExtension(&Extensions::colorBufferFloat);
+ map["GL_OES_vertex_array_object"] = esOnlyExtension(&Extensions::vertexArrayObject);
+ map["GL_KHR_debug"] = esOnlyExtension(&Extensions::debug);
+ // TODO(jmadill): Enable this when complete.
+ //map["GL_KHR_no_error"] = esOnlyExtension(&Extensions::noError);
+ map["GL_ANGLE_lossy_etc_decode"] = esOnlyExtension(&Extensions::lossyETCDecode);
+ map["GL_CHROMIUM_bind_uniform_location"] = esOnlyExtension(&Extensions::bindUniformLocation);
+ map["GL_CHROMIUM_sync_query"] = esOnlyExtension(&Extensions::syncQuery);
+ map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTexture);
+ map["GL_CHROMIUM_copy_compressed_texture"] = esOnlyExtension(&Extensions::copyCompressedTexture);
+ map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility);
+ map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource);
+ map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemory);
+ map["GL_EXT_texture_sRGB_decode"] = esOnlyExtension(&Extensions::textureSRGBDecode);
+ map["GL_EXT_sRGB_write_control"] = esOnlyExtension(&Extensions::sRGBWriteControl);
+ map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility);
+ map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
+ map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
+ map["GL_CHROMIUM_path_rendering"] = esOnlyExtension(&Extensions::pathRendering);
+ // clang-format on
+
+ return map;
+ };
+
+ static const ExtensionInfoMap extensionInfo = buildExtensionInfoMap();
+ return extensionInfo;
+}
+
+TypePrecision::TypePrecision()
+{
+ range[0] = 0;
+ range[1] = 0;
+ precision = 0;
+}
+
+void TypePrecision::setIEEEFloat()
+{
+ range[0] = 127;
+ range[1] = 127;
+ precision = 23;
+}
+
+void TypePrecision::setTwosComplementInt(unsigned int bits)
+{
+ range[0] = GLint(bits) - 1;
+ range[1] = GLint(bits) - 2;
+ precision = 0;
+}
+
+void TypePrecision::setSimulatedInt(unsigned int r)
+{
+ range[0] = GLint(r);
+ range[1] = GLint(r);
+ precision = 0;
+}
+
+void TypePrecision::get(GLint *returnRange, GLint *returnPrecision) const
+{
+ returnRange[0] = range[0];
+ returnRange[1] = range[1];
+ *returnPrecision = precision;
+}
+
+Caps::Caps()
+ : maxElementIndex(0),
+ max3DTextureSize(0),
+ max2DTextureSize(0),
+ maxArrayTextureLayers(0),
+ maxLODBias(0),
+ maxCubeMapTextureSize(0),
+ maxRenderbufferSize(0),
+ minAliasedPointSize(0),
+ maxAliasedPointSize(0),
+ minAliasedLineWidth(0),
+ maxAliasedLineWidth(0),
+
+ // Table 20.40
+ maxDrawBuffers(0),
+ maxFramebufferWidth(0),
+ maxFramebufferHeight(0),
+ maxFramebufferSamples(0),
+ maxColorAttachments(0),
+ maxViewportWidth(0),
+ maxViewportHeight(0),
+ maxSampleMaskWords(0),
+ maxColorTextureSamples(0),
+ maxDepthTextureSamples(0),
+ maxIntegerSamples(0),
+ maxServerWaitTimeout(0),
+
+ // Table 20.41
+ maxVertexAttribRelativeOffset(0),
+ maxVertexAttribBindings(0),
+ maxVertexAttribStride(0),
+ maxElementsIndices(0),
+ maxElementsVertices(0),
+
+ // Table 20.43
+ maxVertexAttributes(0),
+ maxVertexUniformComponents(0),
+ maxVertexUniformVectors(0),
+ maxVertexUniformBlocks(0),
+ maxVertexOutputComponents(0),
+ maxVertexTextureImageUnits(0),
+ maxVertexAtomicCounterBuffers(0),
+ maxVertexAtomicCounters(0),
+ maxVertexImageUniforms(0),
+ maxVertexShaderStorageBlocks(0),
+
+ // Table 20.44
+ maxFragmentUniformComponents(0),
+ maxFragmentUniformVectors(0),
+ maxFragmentUniformBlocks(0),
+ maxFragmentInputComponents(0),
+ maxTextureImageUnits(0),
+ maxFragmentAtomicCounterBuffers(0),
+ maxFragmentAtomicCounters(0),
+ maxFragmentImageUniforms(0),
+ maxFragmentShaderStorageBlocks(0),
+ minProgramTextureGatherOffset(0),
+ maxProgramTextureGatherOffset(0),
+ minProgramTexelOffset(0),
+ maxProgramTexelOffset(0),
+
+ // Table 20.45
+ maxComputeWorkGroupInvocations(0),
+ maxComputeUniformBlocks(0),
+ maxComputeTextureImageUnits(0),
+ maxComputeSharedMemorySize(0),
+ maxComputeUniformComponents(0),
+ maxComputeAtomicCounterBuffers(0),
+ maxComputeAtomicCounters(0),
+ maxComputeImageUniforms(0),
+ maxCombinedComputeUniformComponents(0),
+ maxComputeShaderStorageBlocks(0),
+
+ // Table 20.46
+ maxUniformBufferBindings(0),
+ maxUniformBlockSize(0),
+ uniformBufferOffsetAlignment(0),
+ maxCombinedUniformBlocks(0),
+ maxCombinedVertexUniformComponents(0),
+ maxCombinedFragmentUniformComponents(0),
+ maxVaryingComponents(0),
+ maxVaryingVectors(0),
+ maxCombinedTextureImageUnits(0),
+ maxCombinedShaderOutputResources(0),
+
+ // Table 20.47
+ maxUniformLocations(0),
+ maxAtomicCounterBufferBindings(0),
+ maxAtomicCounterBufferSize(0),
+ maxCombinedAtomicCounterBuffers(0),
+ maxCombinedAtomicCounters(0),
+ maxImageUnits(0),
+ maxCombinedImageUniforms(0),
+ maxShaderStorageBufferBindings(0),
+ maxShaderStorageBlockSize(0),
+ maxCombinedShaderStorageBlocks(0),
+ shaderStorageBufferOffsetAlignment(0),
+
+ // Table 20.48
+ maxTransformFeedbackInterleavedComponents(0),
+ maxTransformFeedbackSeparateAttributes(0),
+ maxTransformFeedbackSeparateComponents(0),
+
+ // Table 20.49
+ maxSamples(0)
+
+{
+ for (size_t i = 0; i < 3; ++i)
+ {
+ maxComputeWorkGroupCount[i] = 0;
+ maxComputeWorkGroupSize[i] = 0;
+ }
+}
+
+}
+
+namespace egl
+{
+
+Caps::Caps()
+ : textureNPOT(false)
+{
+}
+
+DisplayExtensions::DisplayExtensions()
+ : createContextRobustness(false),
+ d3dShareHandleClientBuffer(false),
+ d3dTextureClientBuffer(false),
+ surfaceD3DTexture2DShareHandle(false),
+ querySurfacePointer(false),
+ windowFixedSize(false),
+ keyedMutex(false),
+ surfaceOrientation(false),
+ postSubBuffer(false),
+ createContext(false),
+ deviceQuery(false),
+ image(false),
+ imageBase(false),
+ imagePixmap(false),
+ glTexture2DImage(false),
+ glTextureCubemapImage(false),
+ glTexture3DImage(false),
+ glRenderbufferImage(false),
+ getAllProcAddresses(false),
+ flexibleSurfaceCompatibility(false),
+ directComposition(false),
+ createContextNoError(false),
+ stream(false),
+ streamConsumerGLTexture(false),
+ streamConsumerGLTextureYUV(false),
+ streamProducerD3DTextureNV12(false),
+ createContextWebGLCompatibility(false),
+ createContextBindGeneratesResource(false),
+ swapBuffersWithDamage(false)
+{
+}
+
+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_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
+ InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
+ InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings);
+ InsertExtensionString("EGL_KHR_image", image, &extensionStrings);
+ InsertExtensionString("EGL_KHR_image_base", imageBase, &extensionStrings);
+ InsertExtensionString("EGL_KHR_image_pixmap", imagePixmap, &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_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_stream_producer_d3d_texture_nv12", streamProducerD3DTextureNV12, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_create_context_webgl_compatibility", createContextWebGLCompatibility, &extensionStrings);
+ InsertExtensionString("EGL_CHROMIUM_create_context_bind_generates_resource", createContextBindGeneratesResource, &extensionStrings);
+ InsertExtensionString("EGL_EXT_swap_buffers_with_damage", swapBuffersWithDamage, &extensionStrings);
+ // TODO(jmadill): Enable this when complete.
+ //InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
+ // clang-format on
+
+ return extensionStrings;
+}
+
+DeviceExtensions::DeviceExtensions()
+ : deviceD3D(false)
+{
+}
+
+std::vector<std::string> DeviceExtensions::getStrings() const
+{
+ std::vector<std::string> extensionStrings;
+
+ // | Extension name | Supported flag | Output vector |
+ InsertExtensionString("EGL_ANGLE_device_d3d", deviceD3D, &extensionStrings);
+
+ return extensionStrings;
+}
+
+ClientExtensions::ClientExtensions()
+ : clientExtensions(false),
+ platformBase(false),
+ platformDevice(false),
+ platformANGLE(false),
+ platformANGLED3D(false),
+ platformANGLEOpenGL(false),
+ deviceCreation(false),
+ deviceCreationD3D11(false),
+ x11Visual(false),
+ experimentalPresentPath(false),
+ clientGetAllProcAddresses(false)
+{
+}
+
+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_platform_base", platformBase, &extensionStrings);
+ InsertExtensionString("EGL_EXT_platform_device", platformDevice, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_null", platformANGLENULL, &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);
+ // clang-format on
+
+ return extensionStrings;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/Caps.h b/gfx/angle/src/libANGLE/Caps.h
new file mode 100755
index 000000000..277b4a490
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Caps.h
@@ -0,0 +1,678 @@
+//
+// Copyright (c) 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/angletypes.h"
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+#include <array>
+
+namespace gl
+{
+
+typedef std::set<GLuint> SupportedSampleSet;
+
+struct TextureCaps
+{
+ TextureCaps();
+
+ // Supports for basic texturing: glTexImage, glTexSubImage, etc
+ bool texturable;
+
+ // Support for linear or anisotropic filtering
+ bool filterable;
+
+ // Support for being used as a framebuffer attachment or renderbuffer format
+ bool renderable;
+
+ // 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;
+};
+
+class TextureCapsMap
+{
+ public:
+ typedef std::map<GLenum, TextureCaps>::const_iterator const_iterator;
+
+ void insert(GLenum internalFormat, const TextureCaps &caps);
+ void remove(GLenum internalFormat);
+ void clear();
+
+ const TextureCaps &get(GLenum internalFormat) const;
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ size_t size() const;
+
+ private:
+ typedef std::map<GLenum, TextureCaps> InternalFormatToCapsMap;
+ InternalFormatToCapsMap mCapsMap;
+};
+
+struct Extensions
+{
+ Extensions();
+
+ // 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_compression_dxt1, GL_ANGLE_texture_compression_dxt3,
+ // GL_ANGLE_texture_compression_dxt5
+ // GL_KHR_texture_compression_astc_hdr, GL_KHR_texture_compression_astc_ldr
+ // 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
+ void setTextureExtensionSupport(const TextureCapsMap &textureCaps);
+
+ // ES2 Extension support
+
+ // GL_OES_element_index_uint
+ bool elementIndexUint;
+
+ // GL_OES_packed_depth_stencil
+ bool packedDepthStencil;
+
+ // GL_OES_get_program_binary
+ bool getProgramBinary;
+
+ // GL_OES_rgb8_rgba8
+ // Implies that TextureCaps for GL_RGB8 and GL_RGBA8 exist
+ bool rgb8rgba8;
+
+ // GL_EXT_texture_format_BGRA8888
+ // Implies that TextureCaps for GL_BGRA8 exist
+ bool textureFormatBGRA8888;
+
+ // GL_EXT_read_format_bgra
+ bool readFormatBGRA;
+
+ // GL_NV_pixel_buffer_object
+ bool pixelBufferObject;
+
+ // GL_OES_mapbuffer and GL_EXT_map_buffer_range
+ bool mapBuffer;
+ bool mapBufferRange;
+
+ // GL_EXT_color_buffer_half_float
+ // Together with GL_OES_texture_half_float in a GLES 2.0 context, implies that half-float
+ // textures are renderable.
+ bool colorBufferHalfFloat;
+
+ // GL_OES_texture_half_float and GL_OES_texture_half_float_linear
+ // Implies that TextureCaps for GL_RGB16F, GL_RGBA16F, GL_ALPHA32F_EXT, GL_LUMINANCE32F_EXT and
+ // GL_LUMINANCE_ALPHA32F_EXT exist
+ bool textureHalfFloat;
+ bool textureHalfFloatLinear;
+
+ // GL_OES_texture_float and GL_OES_texture_float_linear
+ // Implies that TextureCaps for GL_RGB32F, GL_RGBA32F, GL_ALPHA16F_EXT, GL_LUMINANCE16F_EXT and
+ // GL_LUMINANCE_ALPHA16F_EXT exist
+ bool textureFloat;
+ bool textureFloatLinear;
+
+ // GL_EXT_texture_rg
+ // Implies that TextureCaps for GL_R8, GL_RG8 (and floating point R/RG texture formats if floating point extensions
+ // are also present) exist
+ bool textureRG;
+
+ // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3 and GL_ANGLE_texture_compression_dxt5
+ // Implies that TextureCaps for GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
+ // GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE and GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE
+ bool textureCompressionDXT1;
+ bool textureCompressionDXT3;
+ bool textureCompressionDXT5;
+
+ // GL_KHR_texture_compression_astc_hdr
+ bool textureCompressionASTCHDR;
+
+ // GL_KHR_texture_compression_astc_ldr
+ bool textureCompressionASTCLDR;
+
+ // GL_OES_compressed_ETC1_RGB8_texture
+ // Implies that TextureCaps for GL_ETC1_RGB8_OES exist
+ bool compressedETC1RGB8Texture;
+
+ // GL_EXT_sRGB
+ // Implies that TextureCaps for GL_SRGB8_ALPHA8 and GL_SRGB8 exist
+ // TODO: Don't advertise this extension in ES3
+ bool sRGB;
+
+ // GL_ANGLE_depth_texture
+ bool depthTextures;
+
+ // GL_OES_depth32
+ // Allows DEPTH_COMPONENT32_OES as a valid Renderbuffer format.
+ bool depth32;
+
+ // GL_EXT_texture_storage
+ bool textureStorage;
+
+ // GL_OES_texture_npot
+ bool textureNPOT;
+
+ // GL_EXT_draw_buffers
+ bool drawBuffers;
+
+ // GL_EXT_texture_filter_anisotropic
+ bool textureFilterAnisotropic;
+ GLfloat maxTextureAnisotropy;
+
+ // GL_EXT_occlusion_query_boolean
+ bool occlusionQueryBoolean;
+
+ // GL_NV_fence
+ bool fence;
+
+ // GL_ANGLE_timer_query
+ bool timerQuery;
+
+ // GL_EXT_disjoint_timer_query
+ bool disjointTimerQuery;
+ GLuint queryCounterBitsTimeElapsed;
+ GLuint queryCounterBitsTimestamp;
+
+ // GL_EXT_robustness
+ bool robustness;
+
+ // GL_EXT_blend_minmax
+ bool blendMinMax;
+
+ // GL_ANGLE_framebuffer_blit
+ bool framebufferBlit;
+
+ // GL_ANGLE_framebuffer_multisample
+ bool framebufferMultisample;
+
+ // GL_ANGLE_instanced_arrays
+ bool instancedArrays;
+
+ // GL_ANGLE_pack_reverse_row_order
+ bool packReverseRowOrder;
+
+ // GL_OES_standard_derivatives
+ bool standardDerivatives;
+
+ // GL_EXT_shader_texture_lod
+ bool shaderTextureLOD;
+
+ // GL_EXT_shader_framebuffer_fetch
+ bool shaderFramebufferFetch;
+
+ // GL_ARM_shader_framebuffer_fetch
+ bool ARMshaderFramebufferFetch;
+
+ // GL_NV_shader_framebuffer_fetch
+ bool NVshaderFramebufferFetch;
+
+ // GL_EXT_frag_depth
+ bool fragDepth;
+
+ // GL_ANGLE_texture_usage
+ bool textureUsage;
+
+ // GL_ANGLE_translated_shader_source
+ bool translatedShaderSource;
+
+ // GL_OES_fbo_render_mipmap
+ bool fboRenderMipmap;
+
+ // GL_EXT_discard_framebuffer
+ bool discardFramebuffer;
+
+ // EXT_debug_marker
+ bool debugMarker;
+
+ // GL_OES_EGL_image
+ bool eglImage;
+
+ // GL_OES_EGL_image_external
+ bool eglImageExternal;
+
+ // GL_OES_EGL_image_external_essl3
+ bool eglImageExternalEssl3;
+
+ // NV_EGL_stream_consumer_external
+ bool eglStreamConsumerExternal;
+
+ // EXT_unpack_subimage
+ bool unpackSubimage;
+
+ // NV_pack_subimage
+ bool packSubimage;
+
+ // GL_OES_vertex_array_object
+ bool vertexArrayObject;
+
+ // GL_KHR_debug
+ bool debug;
+ GLuint maxDebugMessageLength;
+ GLuint maxDebugLoggedMessages;
+ GLuint maxDebugGroupStackDepth;
+ GLuint maxLabelLength;
+
+ // KHR_no_error
+ bool noError;
+
+ // GL_ANGLE_lossy_etc_decode
+ bool lossyETCDecode;
+
+ // GL_CHROMIUM_bind_uniform_location
+ bool bindUniformLocation;
+
+ // GL_CHROMIUM_sync_query
+ bool syncQuery;
+
+ // GL_CHROMIUM_copy_texture
+ bool copyTexture;
+
+ // GL_CHROMIUM_copy_compressed_texture
+ bool copyCompressedTexture;
+
+ // GL_ANGLE_webgl_compatibility
+ bool webglCompatibility;
+
+ // GL_CHROMIUM_bind_generates_resource
+ bool bindGeneratesResource;
+
+ // GL_ANGLE_robust_client_memory
+ bool robustClientMemory;
+
+ // GL_EXT_texture_sRGB_decode
+ bool textureSRGBDecode;
+
+ // GL_EXT_sRGB_write_control
+ bool sRGBWriteControl;
+
+ // ES3 Extension support
+
+ // GL_EXT_color_buffer_float
+ bool colorBufferFloat;
+
+ // GL_EXT_multisample_compatibility.
+ // written against ES 3.1 but can apply to earlier versions.
+ bool multisampleCompatibility;
+
+ // GL_CHROMIUM_framebuffer_mixed_samples
+ bool framebufferMixedSamples;
+
+ // GL_EXT_texture_norm16
+ // written against ES 3.1 but can apply to ES 3.0 as well.
+ bool textureNorm16;
+
+ // GL_CHROMIUM_path_rendering
+ bool pathRendering;
+};
+
+struct ExtensionInfo
+{
+ // If this extension can be enabled with glEnableExtension (GL_ANGLE_webgl_compatibility)
+ bool Enableable = false;
+
+ // Pointer to a boolean member of the Extensions struct
+ typedef bool(Extensions::*ExtensionBool);
+ ExtensionBool ExtensionsMember = nullptr;
+};
+
+using ExtensionInfoMap = std::map<std::string, ExtensionInfo>;
+const ExtensionInfoMap &GetExtensionInfoMap();
+
+struct Limitations
+{
+ Limitations();
+
+ // Renderer doesn't support gl_FrontFacing in fragment shaders
+ bool noFrontFacingSupport;
+
+ // Renderer doesn't support GL_SAMPLE_ALPHA_TO_COVERAGE
+ bool noSampleAlphaToCoverageSupport;
+
+ // In glVertexAttribDivisorANGLE, attribute zero must have a zero divisor
+ bool attributeZeroRequiresZeroDivisorInEXT;
+
+ // Unable to support different values for front and back faces for stencil refs and masks
+ bool noSeparateStencilRefsAndMasks;
+
+ // Renderer doesn't support non-constant indexing loops in fragment shader
+ bool shadersRequireIndexedLoopValidation;
+
+ // 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;
+};
+
+struct TypePrecision
+{
+ TypePrecision();
+
+ void setIEEEFloat();
+ void setTwosComplementInt(unsigned int bits);
+ void setSimulatedInt(unsigned int range);
+
+ void get(GLint *returnRange, GLint *returnPrecision) const;
+
+ GLint range[2];
+ GLint precision;
+};
+
+struct Caps
+{
+ Caps();
+
+ // ES 3.1 (April 29, 2015) 20.39: implementation dependent values
+ GLuint64 maxElementIndex;
+ GLuint max3DTextureSize;
+ GLuint max2DTextureSize;
+ GLuint maxArrayTextureLayers;
+ GLfloat maxLODBias;
+ GLuint maxCubeMapTextureSize;
+ GLuint maxRenderbufferSize;
+ GLfloat minAliasedPointSize;
+ GLfloat maxAliasedPointSize;
+ GLfloat minAliasedLineWidth;
+ GLfloat maxAliasedLineWidth;
+
+ // ES 3.1 (April 29, 2015) 20.40: implementation dependent values (cont.)
+ GLuint maxDrawBuffers;
+ GLuint maxFramebufferWidth;
+ GLuint maxFramebufferHeight;
+ GLuint maxFramebufferSamples;
+ GLuint maxColorAttachments;
+ GLuint maxViewportWidth;
+ GLuint maxViewportHeight;
+ GLuint maxSampleMaskWords;
+ GLuint maxColorTextureSamples;
+ GLuint maxDepthTextureSamples;
+ GLuint maxIntegerSamples;
+ GLuint64 maxServerWaitTimeout;
+
+ // ES 3.1 (April 29, 2015) Table 20.41: Implementation dependent values (cont.)
+ GLint maxVertexAttribRelativeOffset;
+ GLint maxVertexAttribBindings;
+ GLint maxVertexAttribStride;
+ GLuint maxElementsIndices;
+ GLuint maxElementsVertices;
+ 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;
+
+ // ES 3.1 (April 29, 2015) Table 20.43: Implementation dependent Vertex shader limits
+ GLuint maxVertexAttributes;
+ GLuint maxVertexUniformComponents;
+ GLuint maxVertexUniformVectors;
+ GLuint maxVertexUniformBlocks;
+ GLuint maxVertexOutputComponents;
+ GLuint maxVertexTextureImageUnits;
+ GLuint maxVertexAtomicCounterBuffers;
+ GLuint maxVertexAtomicCounters;
+ GLuint maxVertexImageUniforms;
+ GLuint maxVertexShaderStorageBlocks;
+
+ // ES 3.1 (April 29, 2015) Table 20.44: Implementation dependent Fragment shader limits
+ GLuint maxFragmentUniformComponents;
+ GLuint maxFragmentUniformVectors;
+ GLuint maxFragmentUniformBlocks;
+ GLuint maxFragmentInputComponents;
+ GLuint maxTextureImageUnits;
+ GLuint maxFragmentAtomicCounterBuffers;
+ GLuint maxFragmentAtomicCounters;
+ GLuint maxFragmentImageUniforms;
+ GLuint maxFragmentShaderStorageBlocks;
+ GLint minProgramTextureGatherOffset;
+ GLuint maxProgramTextureGatherOffset;
+ GLint minProgramTexelOffset;
+ GLint maxProgramTexelOffset;
+
+ // ES 3.1 (April 29, 2015) Table 20.45: implementation dependent compute shader limits
+ std::array<GLuint, 3> maxComputeWorkGroupCount;
+ std::array<GLuint, 3> maxComputeWorkGroupSize;
+ GLuint maxComputeWorkGroupInvocations;
+ GLuint maxComputeUniformBlocks;
+ GLuint maxComputeTextureImageUnits;
+ GLuint maxComputeSharedMemorySize;
+ GLuint maxComputeUniformComponents;
+ GLuint maxComputeAtomicCounterBuffers;
+ GLuint maxComputeAtomicCounters;
+ GLuint maxComputeImageUniforms;
+ GLuint maxCombinedComputeUniformComponents;
+ GLuint maxComputeShaderStorageBlocks;
+
+ // ES 3.1 (April 29, 2015) Table 20.46: implementation dependent aggregate shader limits
+ GLuint maxUniformBufferBindings;
+ GLuint64 maxUniformBlockSize;
+ GLuint uniformBufferOffsetAlignment;
+ GLuint maxCombinedUniformBlocks;
+ GLuint64 maxCombinedVertexUniformComponents;
+ GLuint64 maxCombinedFragmentUniformComponents;
+ GLuint maxVaryingComponents;
+ GLuint maxVaryingVectors;
+ GLuint maxCombinedTextureImageUnits;
+ GLuint maxCombinedShaderOutputResources;
+
+ // ES 3.1 (April 29, 2015) Table 20.47: implementation dependent aggregate shader limits (cont.)
+ GLuint maxUniformLocations;
+ GLuint maxAtomicCounterBufferBindings;
+ GLuint maxAtomicCounterBufferSize;
+ GLuint maxCombinedAtomicCounterBuffers;
+ GLuint maxCombinedAtomicCounters;
+ GLuint maxImageUnits;
+ GLuint maxCombinedImageUniforms;
+ GLuint maxShaderStorageBufferBindings;
+ GLuint64 maxShaderStorageBlockSize;
+ GLuint maxCombinedShaderStorageBlocks;
+ GLuint shaderStorageBufferOffsetAlignment;
+
+ // ES 3.1 (April 29, 2015) Table 20.48: implementation dependent transform feedback limits
+ GLuint maxTransformFeedbackInterleavedComponents;
+ GLuint maxTransformFeedbackSeparateAttributes;
+ GLuint maxTransformFeedbackSeparateComponents;
+
+ // ES 3.1 (April 29, 2015) Table 20.49: Framebuffer Dependent Values
+ GLuint maxSamples;
+};
+
+}
+
+namespace egl
+{
+
+struct Caps
+{
+ Caps();
+
+ // Support for NPOT surfaces
+ bool textureNPOT;
+};
+
+struct DisplayExtensions
+{
+ DisplayExtensions();
+
+ // Generate a vector of supported extension strings
+ std::vector<std::string> getStrings() const;
+
+ // EGL_EXT_create_context_robustness
+ bool createContextRobustness;
+
+ // EGL_ANGLE_d3d_share_handle_client_buffer
+ bool d3dShareHandleClientBuffer;
+
+ // EGL_ANGLE_d3d_texture_client_buffer
+ bool d3dTextureClientBuffer;
+
+ // EGL_ANGLE_surface_d3d_texture_2d_share_handle
+ bool surfaceD3DTexture2DShareHandle;
+
+ // EGL_ANGLE_query_surface_pointer
+ bool querySurfacePointer;
+
+ // EGL_ANGLE_window_fixed_size
+ bool windowFixedSize;
+
+ // EGL_ANGLE_keyed_mutex
+ bool keyedMutex;
+
+ // EGL_ANGLE_surface_orientation
+ bool surfaceOrientation;
+
+ // EGL_NV_post_sub_buffer
+ bool postSubBuffer;
+
+ // EGL_KHR_create_context
+ bool createContext;
+
+ // EGL_EXT_device_query
+ bool deviceQuery;
+
+ // EGL_KHR_image
+ bool image;
+
+ // EGL_KHR_image_base
+ bool imageBase;
+
+ // EGL_KHR_image_pixmap
+ bool imagePixmap;
+
+ // EGL_KHR_gl_texture_2D_image
+ bool glTexture2DImage;
+
+ // EGL_KHR_gl_texture_cubemap_image
+ bool glTextureCubemapImage;
+
+ // EGL_KHR_gl_texture_3D_image
+ bool glTexture3DImage;
+
+ // EGL_KHR_gl_renderbuffer_image
+ bool glRenderbufferImage;
+
+ // EGL_KHR_get_all_proc_addresses
+ bool getAllProcAddresses;
+
+ // EGL_ANGLE_flexible_surface_compatibility
+ bool flexibleSurfaceCompatibility;
+
+ // EGL_ANGLE_direct_composition
+ bool directComposition;
+
+ // KHR_create_context_no_error
+ bool createContextNoError;
+
+ // EGL_KHR_stream
+ bool stream;
+
+ // EGL_KHR_stream_consumer_gltexture
+ bool streamConsumerGLTexture;
+
+ // EGL_NV_stream_consumer_gltexture_yuv
+ bool streamConsumerGLTextureYUV;
+
+ // EGL_ANGLE_stream_producer_d3d_texture_nv12
+ bool streamProducerD3DTextureNV12;
+
+ // EGL_ANGLE_create_context_webgl_compatibility
+ bool createContextWebGLCompatibility;
+
+ // EGL_CHROMIUM_create_context_bind_generates_resource
+ bool createContextBindGeneratesResource;
+
+ // EGL_EXT_swap_buffers_with_damage
+ bool swapBuffersWithDamage;
+};
+
+struct DeviceExtensions
+{
+ DeviceExtensions();
+
+ // Generate a vector of supported extension strings
+ std::vector<std::string> getStrings() const;
+
+ // EGL_ANGLE_device_d3d
+ bool deviceD3D;
+};
+
+struct ClientExtensions
+{
+ ClientExtensions();
+
+ // Generate a vector of supported extension strings
+ std::vector<std::string> getStrings() const;
+
+ // EGL_EXT_client_extensions
+ bool clientExtensions;
+
+ // EGL_EXT_platform_base
+ bool platformBase;
+
+ // EGL_EXT_platform_device
+ bool platformDevice;
+
+ // EGL_ANGLE_platform_angle
+ bool platformANGLE;
+
+ // EGL_ANGLE_platform_angle_d3d
+ bool platformANGLED3D;
+
+ // EGL_ANGLE_platform_angle_opengl
+ bool platformANGLEOpenGL;
+
+ // EGL_ANGLE_platform_angle_null
+ bool platformANGLENULL;
+
+ // EGL_ANGLE_device_creation
+ bool deviceCreation;
+
+ // EGL_ANGLE_device_creation_d3d11
+ bool deviceCreationD3D11;
+
+ // EGL_ANGLE_x11_visual
+ bool x11Visual;
+
+ // EGL_ANGLE_experimental_present_path
+ bool experimentalPresentPath;
+
+ // EGL_KHR_client_get_all_proc_addresses
+ bool clientGetAllProcAddresses;
+};
+
+}
+
+#endif // LIBANGLE_CAPS_H_
diff --git a/gfx/angle/src/libANGLE/Compiler.cpp b/gfx/angle/src/libANGLE/Compiler.cpp
new file mode 100755
index 000000000..078491284
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Compiler.cpp
@@ -0,0 +1,194 @@
+//
+// Copyright (c) 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/ContextState.h"
+#include "libANGLE/renderer/CompilerImpl.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace gl
+{
+
+namespace
+{
+
+// Global count of active shader compiler handles. Needed to know when to call sh::Initialize and
+// sh::Finalize.
+size_t activeCompilerHandles = 0;
+
+ShShaderSpec SelectShaderSpec(GLint majorVersion, GLint minorVersion, bool isWebGL)
+{
+ if (majorVersion >= 3)
+ {
+ if (minorVersion == 1)
+ {
+ return isWebGL ? SH_WEBGL3_SPEC : SH_GLES3_1_SPEC;
+ }
+ else
+ {
+ return isWebGL ? SH_WEBGL2_SPEC : SH_GLES3_SPEC;
+ }
+ }
+ return isWebGL ? SH_WEBGL_SPEC : SH_GLES2_SPEC;
+}
+
+} // anonymous namespace
+
+Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state)
+ : mImplementation(implFactory->createCompiler()),
+ mSpec(SelectShaderSpec(state.getClientMajorVersion(),
+ state.getClientMinorVersion(),
+ state.getExtensions().webglCompatibility)),
+ mOutputType(mImplementation->getTranslatorOutputType()),
+ mResources(),
+ mFragmentCompiler(nullptr),
+ mVertexCompiler(nullptr),
+ mComputeCompiler(nullptr)
+{
+ ASSERT(state.getClientMajorVersion() == 2 || state.getClientMajorVersion() == 3);
+
+ const gl::Caps &caps = state.getCaps();
+ const gl::Extensions &extensions = state.getExtensions();
+
+ sh::InitBuiltInResources(&mResources);
+ mResources.MaxVertexAttribs = caps.maxVertexAttributes;
+ mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors;
+ mResources.MaxVaryingVectors = caps.maxVaryingVectors;
+ mResources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits;
+ mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
+ mResources.MaxTextureImageUnits = caps.maxTextureImageUnits;
+ mResources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors;
+ mResources.MaxDrawBuffers = caps.maxDrawBuffers;
+ mResources.OES_standard_derivatives = extensions.standardDerivatives;
+ mResources.EXT_draw_buffers = extensions.drawBuffers;
+ mResources.EXT_shader_texture_lod = extensions.shaderTextureLOD;
+ mResources.OES_EGL_image_external = extensions.eglImageExternal;
+ mResources.OES_EGL_image_external_essl3 = extensions.eglImageExternalEssl3;
+ mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternal;
+ // TODO: use shader precision caps to determine if high precision is supported?
+ mResources.FragmentPrecisionHigh = 1;
+ mResources.EXT_frag_depth = extensions.fragDepth;
+
+ // GLSL ES 3.0 constants
+ mResources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4;
+ mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
+ mResources.MinProgramTexelOffset = caps.minProgramTexelOffset;
+ mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset;
+
+ // GLSL ES 3.1 compute shader constants
+ mResources.MaxImageUnits = caps.maxImageUnits;
+ mResources.MaxVertexImageUniforms = caps.maxVertexImageUniforms;
+ mResources.MaxFragmentImageUniforms = caps.maxFragmentImageUniforms;
+ mResources.MaxComputeImageUniforms = caps.maxComputeImageUniforms;
+ mResources.MaxCombinedImageUniforms = caps.maxCombinedImageUniforms;
+ mResources.MaxCombinedShaderOutputResources = caps.maxCombinedShaderOutputResources;
+
+ for (size_t index = 0u; index < 3u; ++index)
+ {
+ mResources.MaxComputeWorkGroupCount[index] = caps.maxComputeWorkGroupCount[index];
+ mResources.MaxComputeWorkGroupSize[index] = caps.maxComputeWorkGroupSize[index];
+ }
+
+ mResources.MaxComputeUniformComponents = caps.maxComputeUniformComponents;
+ mResources.MaxComputeTextureImageUnits = caps.maxComputeTextureImageUnits;
+
+ mResources.MaxComputeAtomicCounters = caps.maxComputeAtomicCounters;
+ mResources.MaxComputeAtomicCounterBuffers = caps.maxComputeAtomicCounterBuffers;
+
+ mResources.MaxVertexAtomicCounters = caps.maxVertexAtomicCounters;
+ mResources.MaxFragmentAtomicCounters = caps.maxFragmentAtomicCounters;
+ mResources.MaxCombinedAtomicCounters = caps.maxCombinedAtomicCounters;
+ mResources.MaxAtomicCounterBindings = caps.maxAtomicCounterBufferBindings;
+ mResources.MaxVertexAtomicCounterBuffers = caps.maxVertexAtomicCounterBuffers;
+ mResources.MaxFragmentAtomicCounterBuffers = caps.maxFragmentAtomicCounterBuffers;
+ mResources.MaxCombinedAtomicCounterBuffers = caps.maxCombinedAtomicCounterBuffers;
+ mResources.MaxAtomicCounterBufferSize = caps.maxAtomicCounterBufferSize;
+}
+
+Compiler::~Compiler()
+{
+ release();
+ SafeDelete(mImplementation);
+}
+
+Error Compiler::release()
+{
+ if (mFragmentCompiler)
+ {
+ sh::Destruct(mFragmentCompiler);
+ mFragmentCompiler = nullptr;
+
+ ASSERT(activeCompilerHandles > 0);
+ activeCompilerHandles--;
+ }
+
+ if (mVertexCompiler)
+ {
+ sh::Destruct(mVertexCompiler);
+ mVertexCompiler = nullptr;
+
+ ASSERT(activeCompilerHandles > 0);
+ activeCompilerHandles--;
+ }
+
+ if (mComputeCompiler)
+ {
+ sh::Destruct(mComputeCompiler);
+ mComputeCompiler = nullptr;
+
+ ASSERT(activeCompilerHandles > 0);
+ activeCompilerHandles--;
+ }
+
+ if (activeCompilerHandles == 0)
+ {
+ sh::Finalize();
+ }
+
+ mImplementation->release();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+ShHandle Compiler::getCompilerHandle(GLenum type)
+{
+ ShHandle *compiler = nullptr;
+ switch (type)
+ {
+ case GL_VERTEX_SHADER:
+ compiler = &mVertexCompiler;
+ break;
+
+ case GL_FRAGMENT_SHADER:
+ compiler = &mFragmentCompiler;
+ break;
+ case GL_COMPUTE_SHADER:
+ compiler = &mComputeCompiler;
+ break;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+
+ if (!(*compiler))
+ {
+ if (activeCompilerHandles == 0)
+ {
+ sh::Initialize();
+ }
+
+ *compiler = sh::ConstructCompiler(type, mSpec, mOutputType, &mResources);
+ activeCompilerHandles++;
+ }
+
+ return *compiler;
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/Compiler.h b/gfx/angle/src/libANGLE/Compiler.h
new file mode 100755
index 000000000..14226630e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Compiler.h
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 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 "libANGLE/Error.h"
+#include "GLSLANG/ShaderLang.h"
+
+namespace rx
+{
+class CompilerImpl;
+class GLImplFactory;
+}
+
+namespace gl
+{
+class ContextState;
+
+class Compiler final : angle::NonCopyable
+{
+ public:
+ Compiler(rx::GLImplFactory *implFactory, const ContextState &data);
+ ~Compiler();
+
+ Error release();
+
+ ShHandle getCompilerHandle(GLenum type);
+ ShShaderOutput getShaderOutputType() const { return mOutputType; }
+
+ private:
+ rx::CompilerImpl *mImplementation;
+ ShShaderSpec mSpec;
+ ShShaderOutput mOutputType;
+ ShBuiltInResources mResources;
+
+ ShHandle mFragmentCompiler;
+ ShHandle mVertexCompiler;
+ ShHandle mComputeCompiler;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_COMPILER_H_
diff --git a/gfx/angle/src/libANGLE/Config.cpp b/gfx/angle/src/libANGLE/Config.cpp
new file mode 100755
index 000000000..822518ef6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Config.cpp
@@ -0,0 +1,279 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 "angle_gl.h"
+#include <EGL/eglext.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),
+ colorBufferType(EGL_NONE),
+ 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)
+{
+}
+
+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) \
+ if (x.attribute != y.attribute) \
+ { \
+ return x.attribute < y.attribute; \
+ }
+
+ static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "Unexpected EGL enum value.");
+ SORT(configCaveat);
+
+ 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:
+ void scanForWantedComponents(const AttributeMap &attributeMap)
+ {
+ // [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.
+ for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
+ {
+ EGLAttrib attributeKey = attribIter->first;
+ EGLAttrib attributeValue = attribIter->second;
+ if (attributeKey != 0 && attributeValue != EGL_DONT_CARE)
+ {
+ switch (attributeKey)
+ {
+ case EGL_RED_SIZE: mWantRed = true; break;
+ case EGL_GREEN_SIZE: mWantGreen = true; break;
+ case EGL_BLUE_SIZE: mWantBlue = true; break;
+ case EGL_ALPHA_SIZE: mWantAlpha = true; break;
+ case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
+ }
+ }
+ }
+ }
+
+ 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;
+
+ 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 == (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 == (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 == (EGLenum)attributeValue; break;
+ case EGL_TRANSPARENT_BLUE_VALUE: match = config.transparentBlueValue == attributeValue; break;
+ case EGL_TRANSPARENT_GREEN_VALUE: match = config.transparentGreenValue == attributeValue; break;
+ case EGL_TRANSPARENT_RED_VALUE: match = config.transparentRedValue == attributeValue; break;
+ case EGL_BIND_TO_TEXTURE_RGB: match = config.bindToTextureRGB == (EGLBoolean)attributeValue; break;
+ case EGL_BIND_TO_TEXTURE_RGBA: match = config.bindToTextureRGBA == (EGLBoolean)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 == (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;
+ default: UNREACHABLE();
+ }
+
+ if (!match)
+ {
+ break;
+ }
+ }
+
+ if (match)
+ {
+ result.push_back(&config);
+ }
+ }
+
+ // Sort the result
+ std::sort(result.begin(), result.end(), ConfigSorter(attributeMap));
+
+ return result;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/Config.h b/gfx/angle/src/libANGLE/Config.h
new file mode 100755
index 000000000..00f5673b5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Config.h
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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();
+
+ 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 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
+};
+
+class ConfigSet
+{
+ public:
+ 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;
+
+ private:
+ typedef std::map<EGLint, const Config> ConfigMap;
+ ConfigMap mConfigs;
+};
+
+}
+
+#endif // INCLUDE_CONFIG_H_
diff --git a/gfx/angle/src/libANGLE/Config_unittest.cpp b/gfx/angle/src/libANGLE/Config_unittest.cpp
new file mode 100755
index 000000000..4c49df600
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Config_unittest.cpp
@@ -0,0 +1,220 @@
+//
+// Copyright (c) 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 "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Config.h"
+
+// Create a generic, valid EGL config that can be modified to test sorting and
+// filtering routines
+static egl::Config GenerateGenericConfig()
+{
+ egl::Config config;
+
+ config.bufferSize = 24;
+ config.redSize = 8;
+ config.greenSize = 8;
+ config.blueSize = 8;
+ config.luminanceSize = 0;
+ config.alphaSize = 8;
+ config.alphaMaskSize = 0;
+ config.bindToTextureRGB = EGL_TRUE;
+ config.bindToTextureRGBA = EGL_TRUE;
+ config.colorBufferType = EGL_RGB_BUFFER;
+ config.configCaveat = EGL_NONE;
+ config.configID = 0;
+ config.conformant = EGL_OPENGL_ES2_BIT;
+ config.depthSize = 24;
+ config.level = 0;
+ config.matchNativePixmap = EGL_NONE;
+ config.maxPBufferWidth = 1024;
+ config.maxPBufferHeight = 1024;
+ config.maxPBufferPixels = config.maxPBufferWidth * config.maxPBufferWidth;
+ config.maxSwapInterval = 0;
+ config.minSwapInterval = 4;
+ config.nativeRenderable = EGL_OPENGL_ES2_BIT;
+ config.nativeVisualID = 0;
+ config.nativeVisualType = 0;
+ config.renderableType = EGL_FALSE;
+ config.sampleBuffers = 0;
+ config.samples = 0;
+ config.stencilSize = 8;
+ 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;
+
+ return config;
+}
+
+static std::vector<egl::Config> GenerateUniqueConfigs(size_t count)
+{
+ std::vector<egl::Config> configs;
+
+ for (size_t i = 0; i < count; i++)
+ {
+ egl::Config config = GenerateGenericConfig();
+ config.samples = static_cast<EGLint>(i);
+ configs.push_back(config);
+ }
+
+ return configs;
+}
+
+// Add unique configs to a ConfigSet and expect that the size of the
+// set is equal to the number of configs added.
+TEST(ConfigSetTest, Size)
+{
+ egl::ConfigSet set;
+
+ std::vector<egl::Config> uniqueConfigs = GenerateUniqueConfigs(16);
+ for (size_t i = 0; i < uniqueConfigs.size(); i++)
+ {
+ set.add(uniqueConfigs[i]);
+ EXPECT_EQ(set.size(), i + 1);
+ }
+}
+
+// [EGL 1.5] section 3.4:
+// EGL_CONFIG_ID is a unique integer identifying different EGLConfigs. Configuration IDs
+// must be small positive integers starting at 1 and ID assignment should be compact;
+// that is, if there are N EGLConfigs defined by the EGL implementation, their
+// configuration IDs should be in the range [1, N].
+TEST(ConfigSetTest, IDs)
+{
+ egl::ConfigSet set;
+
+ std::set<EGLint> ids;
+
+ std::vector<egl::Config> uniqueConfigs = GenerateUniqueConfigs(16);
+ for (size_t i = 0; i < uniqueConfigs.size(); i++)
+ {
+ EGLint id = set.add(uniqueConfigs[i]);
+
+ // Check that the config that was inserted has the ID that was returned
+ // by ConfigSet::add
+ EXPECT_EQ(id, set.get(id).configID);
+
+ ids.insert(id);
+ }
+
+ // Verify configCount unique IDs
+ EXPECT_EQ(ids.size(), set.size());
+
+ // Check that there are no gaps and the IDs are in the range [1, N].
+ EXPECT_EQ(*std::min_element(ids.begin(), ids.end()), 1);
+ EXPECT_EQ(*std::max_element(ids.begin(), ids.end()), static_cast<EGLint>(set.size()));
+}
+
+TEST(ConfigSetTest, Filtering_BitSizes)
+{
+ egl::ConfigSet set;
+
+ struct VariableConfigBitSize
+ {
+ EGLint Name;
+ EGLint(egl::Config::*ConfigMember);
+ };
+
+ VariableConfigBitSize testMembers[] =
+ {
+ { EGL_RED_SIZE, &egl::Config::redSize },
+ { EGL_GREEN_SIZE, &egl::Config::greenSize },
+ { EGL_BLUE_SIZE, &egl::Config::blueSize },
+ { EGL_ALPHA_SIZE, &egl::Config::alphaSize },
+ { EGL_DEPTH_SIZE, &egl::Config::depthSize },
+ { EGL_STENCIL_SIZE, &egl::Config::stencilSize },
+ };
+
+ // Generate configsPerType configs with varying bit sizes of each type
+ size_t configsPerType = 4;
+ for (size_t i = 0; i < ArraySize(testMembers); i++)
+ {
+ for (size_t j = 0; j < configsPerType; j++)
+ {
+ egl::Config config = GenerateGenericConfig();
+
+ // Set all the other tested members of this config to 0
+ for (size_t k = 0; k < ArraySize(testMembers); k++)
+ {
+ config.*(testMembers[k].ConfigMember) = 0;
+ }
+
+ // Set the tested member of this config to i so it ranges from
+ // [1, configsPerType]
+ config.*(testMembers[i].ConfigMember) = static_cast<EGLint>(j) + 1;
+
+ set.add(config);
+ }
+ }
+
+ // for each tested member, filter by it's type and verify that the correct number
+ // of results are returned
+ for (size_t i = 0; i < ArraySize(testMembers); i++)
+ {
+ // Start with a filter of 1 to not grab the other members
+ for (EGLint j = 0; j < static_cast<EGLint>(configsPerType); j++)
+ {
+ egl::AttributeMap filter;
+ filter.insert(testMembers[i].Name, j + 1);
+
+ std::vector<const egl::Config *> filteredConfigs = set.filter(filter);
+
+ EXPECT_EQ(filteredConfigs.size(), configsPerType - j);
+ }
+ }
+}
+
+// Verify the sorting, [EGL 1.5] section 3.4.1.2 pg 30:
+// [configs are sorted] by larger total number of color bits (for an RGB
+// color buffer this is the sum of EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE,
+// and EGL_ALPHA_SIZE; for a luminance color buffer, the sum of EGL_LUMINANCE_SIZE
+// and EGL_ALPHA_SIZE).If the requested number of bits in attrib list for a
+// particular color component is 0 or EGL_DONT_CARE, then the number of bits
+// for that component is not considered.
+TEST(ConfigSetTest, Sorting_BitSizes)
+{
+ egl::ConfigSet set;
+ size_t testConfigCount = 64;
+ for (size_t i = 0; i < testConfigCount; i++)
+ {
+ egl::Config config = GenerateGenericConfig();
+
+ // Give random-ish bit sizes to the config
+ config.redSize = (i * 2) % 3;
+ config.greenSize = (i + 5) % 7;
+ config.blueSize = (i + 7) % 11;
+ config.alphaSize = (i + 13) % 17;
+
+ set.add(config);
+ }
+
+ egl::AttributeMap greaterThan1BitFilter;
+ greaterThan1BitFilter.insert(EGL_RED_SIZE, 1);
+ greaterThan1BitFilter.insert(EGL_GREEN_SIZE, 1);
+ greaterThan1BitFilter.insert(EGL_BLUE_SIZE, 1);
+ greaterThan1BitFilter.insert(EGL_ALPHA_SIZE, 1);
+
+ std::vector<const egl::Config *> filteredConfigs = set.filter(greaterThan1BitFilter);
+ for (size_t i = 1; i < filteredConfigs.size(); i++)
+ {
+ const egl::Config &prevConfig = *filteredConfigs[i - 1];
+ size_t prevBitCount = prevConfig.redSize +
+ prevConfig.greenSize +
+ prevConfig.blueSize +
+ prevConfig.alphaSize;
+
+ const egl::Config &curConfig = *filteredConfigs[i];
+ size_t curBitCount = curConfig.redSize +
+ curConfig.greenSize +
+ curConfig.blueSize +
+ curConfig.alphaSize;
+
+ EXPECT_GE(prevBitCount, curBitCount);
+ }
+}
diff --git a/gfx/angle/src/libANGLE/Constants.h b/gfx/angle/src/libANGLE/Constants.h
new file mode 100755
index 000000000..dc8f9555b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Constants.h
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 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_
+
+namespace gl
+{
+
+enum
+{
+ MAX_VERTEX_ATTRIBS = 16,
+
+ // Implementation upper limits, real maximums depend on the hardware
+ 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
+
+ IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS = 16,
+ IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS = 16,
+ IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS = IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS +
+ IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS,
+
+ IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS = 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 = 16384,
+ IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384,
+ IMPLEMENTATION_MAX_3D_TEXTURE_SIZE = 2048,
+ IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS = 2048,
+
+ IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE
+};
+
+}
+
+#endif // LIBANGLE_CONSTANTS_H_
diff --git a/gfx/angle/src/libANGLE/Context.cpp b/gfx/angle/src/libANGLE/Context.cpp
new file mode 100755
index 000000000..d74f33057
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Context.cpp
@@ -0,0 +1,3593 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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.h"
+
+#include <iterator>
+#include <sstream>
+#include <string.h>
+#include <vector>
+
+#include "common/matrix_utils.h"
+#include "common/platform.h"
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Path.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/Workarounds.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
+
+namespace
+{
+
+template <typename T>
+std::vector<gl::Path *> GatherPaths(gl::ResourceManager &resourceManager,
+ GLsizei numPaths,
+ const void *paths,
+ GLuint pathBase)
+{
+ std::vector<gl::Path *> ret;
+ ret.reserve(numPaths);
+
+ const auto *nameArray = static_cast<const T *>(paths);
+
+ for (GLsizei i = 0; i < numPaths; ++i)
+ {
+ const GLuint pathName = nameArray[i] + pathBase;
+
+ ret.push_back(resourceManager.getPath(pathName));
+ }
+
+ return ret;
+}
+
+std::vector<gl::Path *> GatherPaths(gl::ResourceManager &resourceManager,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase)
+{
+ switch (pathNameType)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GatherPaths<GLubyte>(resourceManager, numPaths, paths, pathBase);
+
+ case GL_BYTE:
+ return GatherPaths<GLbyte>(resourceManager, numPaths, paths, pathBase);
+
+ case GL_UNSIGNED_SHORT:
+ return GatherPaths<GLushort>(resourceManager, numPaths, paths, pathBase);
+
+ case GL_SHORT:
+ return GatherPaths<GLshort>(resourceManager, numPaths, paths, pathBase);
+
+ case GL_UNSIGNED_INT:
+ return GatherPaths<GLuint>(resourceManager, numPaths, paths, pathBase);
+
+ case GL_INT:
+ return GatherPaths<GLint>(resourceManager, numPaths, paths, pathBase);
+ }
+
+ UNREACHABLE();
+ return std::vector<gl::Path *>();
+}
+
+template <typename T>
+gl::Error GetQueryObjectParameter(gl::Query *query, GLenum pname, T *params)
+{
+ ASSERT(query != nullptr);
+
+ switch (pname)
+ {
+ case GL_QUERY_RESULT_EXT:
+ return query->getResult(params);
+ case GL_QUERY_RESULT_AVAILABLE_EXT:
+ {
+ bool available;
+ gl::Error error = query->isResultAvailable(&available);
+ if (!error.isError())
+ {
+ *params = gl::ConvertFromGLboolean<T>(available);
+ }
+ return error;
+ }
+ default:
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION, "Unreachable Error");
+ }
+}
+
+void MarkTransformFeedbackBufferUsage(gl::TransformFeedback *transformFeedback)
+{
+ if (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
+ {
+ for (size_t tfBufferIndex = 0; tfBufferIndex < transformFeedback->getIndexedBufferCount();
+ tfBufferIndex++)
+ {
+ const OffsetBindingPointer<gl::Buffer> &buffer =
+ transformFeedback->getIndexedBuffer(tfBufferIndex);
+ if (buffer.get() != nullptr)
+ {
+ buffer->onTransformFeedback();
+ }
+ }
+ }
+}
+
+// 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));
+}
+
+gl::Version GetClientVersion(const egl::AttributeMap &attribs)
+{
+ return gl::Version(GetClientMajorVersion(attribs), GetClientMinorVersion(attribs));
+}
+
+GLenum GetResetStrategy(const egl::AttributeMap &attribs)
+{
+ EGLAttrib attrib = attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
+ EGL_NO_RESET_NOTIFICATION_EXT);
+ switch (attrib)
+ {
+ 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)
+{
+ return (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE) ||
+ ((attribs.get(EGL_CONTEXT_FLAGS_KHR, 0) & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) !=
+ 0);
+}
+
+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 GetWebGLContext(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) == EGL_TRUE);
+}
+
+bool GetBindGeneratesResource(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE) == EGL_TRUE);
+}
+
+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);
+ }
+}
+
+} // anonymous namespace
+
+namespace gl
+{
+
+Context::Context(rx::EGLImplFactory *implFactory,
+ const egl::Config *config,
+ const Context *shareContext,
+ const egl::AttributeMap &attribs)
+
+ : ValidationContext(GetClientVersion(attribs),
+ &mGLState,
+ mCaps,
+ mTextureCaps,
+ mExtensions,
+ nullptr,
+ mLimitations,
+ mFramebufferMap,
+ GetNoError(attribs)),
+ mImplementation(implFactory->createContext(mState)),
+ mCompiler(nullptr),
+ mConfig(config),
+ mClientType(EGL_OPENGL_ES_API),
+ mHasBeenCurrent(false),
+ mContextLost(false),
+ mResetStatus(GL_NO_ERROR),
+ mContextLostForced(false),
+ mResetStrategy(GetResetStrategy(attribs)),
+ mRobustAccess(GetRobustAccess(attribs)),
+ mCurrentSurface(nullptr),
+ mResourceManager(nullptr)
+{
+ if (mRobustAccess)
+ {
+ UNIMPLEMENTED();
+ }
+
+ initCaps(GetWebGLContext(attribs));
+ initWorkarounds();
+
+ mGLState.initialize(mCaps, mExtensions, getClientVersion(), GetDebug(attribs),
+ GetBindGeneratesResource(attribs));
+
+ mFenceNVHandleAllocator.setBaseHandle(0);
+
+ if (shareContext != nullptr)
+ {
+ mResourceManager = shareContext->mResourceManager;
+ mResourceManager->addRef();
+ }
+ else
+ {
+ mResourceManager = new ResourceManager();
+ }
+
+ mState.mResourceManager = mResourceManager;
+
+ // [OpenGL ES 2.0.24] section 3.7 page 83:
+ // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
+ // 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, GL_TEXTURE_2D);
+ mZeroTextures[GL_TEXTURE_2D].set(zeroTexture2D);
+
+ Texture *zeroTextureCube = new Texture(mImplementation.get(), 0, GL_TEXTURE_CUBE_MAP);
+ mZeroTextures[GL_TEXTURE_CUBE_MAP].set(zeroTextureCube);
+
+ if (getClientVersion() >= Version(3, 0))
+ {
+ // TODO: These could also be enabled via extension
+ Texture *zeroTexture3D = new Texture(mImplementation.get(), 0, GL_TEXTURE_3D);
+ mZeroTextures[GL_TEXTURE_3D].set(zeroTexture3D);
+
+ Texture *zeroTexture2DArray = new Texture(mImplementation.get(), 0, GL_TEXTURE_2D_ARRAY);
+ mZeroTextures[GL_TEXTURE_2D_ARRAY].set(zeroTexture2DArray);
+ }
+
+ if (mExtensions.eglImageExternal || mExtensions.eglStreamConsumerExternal)
+ {
+ Texture *zeroTextureExternal =
+ new Texture(mImplementation.get(), 0, GL_TEXTURE_EXTERNAL_OES);
+ mZeroTextures[GL_TEXTURE_EXTERNAL_OES].set(zeroTextureExternal);
+ }
+
+ mGLState.initializeZeroTextures(mZeroTextures);
+
+ bindVertexArray(0);
+ bindArrayBuffer(0);
+ bindElementArrayBuffer(0);
+
+ bindRenderbuffer(GL_RENDERBUFFER, 0);
+
+ bindGenericUniformBuffer(0);
+ for (unsigned int i = 0; i < mCaps.maxCombinedUniformBlocks; i++)
+ {
+ bindIndexedUniformBuffer(0, i, 0, -1);
+ }
+
+ bindCopyReadBuffer(0);
+ bindCopyWriteBuffer(0);
+ bindPixelPackBuffer(0);
+ bindPixelUnpackBuffer(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(0);
+ }
+
+ mCompiler = new Compiler(mImplementation.get(), mState);
+
+ // Initialize dirty bit masks
+ // TODO(jmadill): additional ES3 state
+ mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_ALIGNMENT);
+ mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_ROW_LENGTH);
+ mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
+ mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_SKIP_IMAGES);
+ mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_SKIP_ROWS);
+ mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_SKIP_PIXELS);
+ mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_BUFFER_BINDING);
+ // No dirty objects.
+
+ // Readpixels uses the pack state and read FBO
+ mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_ALIGNMENT);
+ mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_REVERSE_ROW_ORDER);
+ mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_ROW_LENGTH);
+ mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_SKIP_ROWS);
+ mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_SKIP_PIXELS);
+ mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_BUFFER_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);
+ mClearDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+
+ mBlitDirtyBits.set(State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
+ mBlitDirtyBits.set(State::DIRTY_BIT_SCISSOR);
+ mBlitDirtyBits.set(State::DIRTY_BIT_FRAMEBUFFER_SRGB);
+ mBlitDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER);
+ mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+
+ handleError(mImplementation->initialize());
+}
+
+Context::~Context()
+{
+ mGLState.reset();
+
+ for (auto framebuffer : mFramebufferMap)
+ {
+ // Default framebuffer are owned by their respective Surface
+ if (framebuffer.second != nullptr && framebuffer.second->id() != 0)
+ {
+ SafeDelete(framebuffer.second);
+ }
+ }
+
+ for (auto fence : mFenceNVMap)
+ {
+ SafeDelete(fence.second);
+ }
+
+ for (auto query : mQueryMap)
+ {
+ if (query.second != nullptr)
+ {
+ query.second->release();
+ }
+ }
+
+ for (auto vertexArray : mVertexArrayMap)
+ {
+ SafeDelete(vertexArray.second);
+ }
+
+ for (auto transformFeedback : mTransformFeedbackMap)
+ {
+ if (transformFeedback.second != nullptr)
+ {
+ transformFeedback.second->release();
+ }
+ }
+
+ for (auto &zeroTexture : mZeroTextures)
+ {
+ zeroTexture.second.set(NULL);
+ }
+ mZeroTextures.clear();
+
+ if (mCurrentSurface != nullptr)
+ {
+ releaseSurface();
+ }
+
+ if (mResourceManager)
+ {
+ mResourceManager->release();
+ }
+
+ SafeDelete(mCompiler);
+}
+
+void Context::makeCurrent(egl::Surface *surface)
+{
+ ASSERT(surface != nullptr);
+
+ if (!mHasBeenCurrent)
+ {
+ initRendererString();
+ initExtensionStrings();
+
+ mGLState.setViewportParams(0, 0, surface->getWidth(), surface->getHeight());
+ mGLState.setScissorParams(0, 0, surface->getWidth(), surface->getHeight());
+
+ mHasBeenCurrent = true;
+ }
+
+ // TODO(jmadill): Rework this when we support ContextImpl
+ mGLState.setAllDirtyBits();
+
+ if (mCurrentSurface)
+ {
+ releaseSurface();
+ }
+ surface->setIsCurrent(true);
+ mCurrentSurface = surface;
+
+ // Update default framebuffer, the binding of the previous default
+ // framebuffer (or lack of) will have a nullptr.
+ {
+ Framebuffer *newDefault = surface->getDefaultFramebuffer();
+ if (mGLState.getReadFramebuffer() == nullptr)
+ {
+ mGLState.setReadFramebufferBinding(newDefault);
+ }
+ if (mGLState.getDrawFramebuffer() == nullptr)
+ {
+ mGLState.setDrawFramebufferBinding(newDefault);
+ }
+ mFramebufferMap[0] = newDefault;
+ }
+
+ // Notify the renderer of a context switch
+ mImplementation->onMakeCurrent(mState);
+}
+
+void Context::releaseSurface()
+{
+ ASSERT(mCurrentSurface != nullptr);
+
+ // Remove the default framebuffer
+ {
+ Framebuffer *currentDefault = mCurrentSurface->getDefaultFramebuffer();
+ if (mGLState.getReadFramebuffer() == currentDefault)
+ {
+ mGLState.setReadFramebufferBinding(nullptr);
+ }
+ if (mGLState.getDrawFramebuffer() == currentDefault)
+ {
+ mGLState.setDrawFramebufferBinding(nullptr);
+ }
+ mFramebufferMap.erase(0);
+ }
+
+ mCurrentSurface->setIsCurrent(false);
+ mCurrentSurface = nullptr;
+}
+
+GLuint Context::createBuffer()
+{
+ return mResourceManager->createBuffer();
+}
+
+GLuint Context::createProgram()
+{
+ return mResourceManager->createProgram(mImplementation.get());
+}
+
+GLuint Context::createShader(GLenum type)
+{
+ return mResourceManager->createShader(mImplementation.get(),
+ mImplementation->getNativeLimitations(), type);
+}
+
+GLuint Context::createTexture()
+{
+ return mResourceManager->createTexture();
+}
+
+GLuint Context::createRenderbuffer()
+{
+ return mResourceManager->createRenderbuffer();
+}
+
+GLsync Context::createFenceSync()
+{
+ GLuint handle = mResourceManager->createFenceSync(mImplementation.get());
+
+ return reinterpret_cast<GLsync>(static_cast<uintptr_t>(handle));
+}
+
+GLuint Context::createPaths(GLsizei range)
+{
+ auto resultOrError = mResourceManager->createPaths(mImplementation.get(), range);
+ if (resultOrError.isError())
+ {
+ handleError(resultOrError.getError());
+ return 0;
+ }
+ return resultOrError.getResult();
+}
+
+GLuint Context::createVertexArray()
+{
+ GLuint vertexArray = mVertexArrayHandleAllocator.allocate();
+ mVertexArrayMap[vertexArray] = nullptr;
+ return vertexArray;
+}
+
+GLuint Context::createSampler()
+{
+ return mResourceManager->createSampler();
+}
+
+GLuint Context::createTransformFeedback()
+{
+ GLuint transformFeedback = mTransformFeedbackAllocator.allocate();
+ mTransformFeedbackMap[transformFeedback] = nullptr;
+ return transformFeedback;
+}
+
+// Returns an unused framebuffer name
+GLuint Context::createFramebuffer()
+{
+ GLuint handle = mFramebufferHandleAllocator.allocate();
+
+ mFramebufferMap[handle] = NULL;
+
+ return handle;
+}
+
+GLuint Context::createFenceNV()
+{
+ GLuint handle = mFenceNVHandleAllocator.allocate();
+
+ mFenceNVMap[handle] = new FenceNV(mImplementation->createFenceNV());
+
+ return handle;
+}
+
+// Returns an unused query name
+GLuint Context::createQuery()
+{
+ GLuint handle = mQueryHandleAllocator.allocate();
+
+ mQueryMap[handle] = NULL;
+
+ return handle;
+}
+
+void Context::deleteBuffer(GLuint buffer)
+{
+ if (mResourceManager->getBuffer(buffer))
+ {
+ detachBuffer(buffer);
+ }
+
+ mResourceManager->deleteBuffer(buffer);
+}
+
+void Context::deleteShader(GLuint shader)
+{
+ mResourceManager->deleteShader(shader);
+}
+
+void Context::deleteProgram(GLuint program)
+{
+ mResourceManager->deleteProgram(program);
+}
+
+void Context::deleteTexture(GLuint texture)
+{
+ if (mResourceManager->getTexture(texture))
+ {
+ detachTexture(texture);
+ }
+
+ mResourceManager->deleteTexture(texture);
+}
+
+void Context::deleteRenderbuffer(GLuint renderbuffer)
+{
+ if (mResourceManager->getRenderbuffer(renderbuffer))
+ {
+ detachRenderbuffer(renderbuffer);
+ }
+
+ mResourceManager->deleteRenderbuffer(renderbuffer);
+}
+
+void Context::deleteFenceSync(GLsync fenceSync)
+{
+ // 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.
+ mResourceManager->deleteFenceSync(static_cast<GLuint>(reinterpret_cast<uintptr_t>(fenceSync)));
+}
+
+void Context::deletePaths(GLuint first, GLsizei range)
+{
+ mResourceManager->deletePaths(first, range);
+}
+
+bool Context::hasPathData(GLuint path) const
+{
+ const auto *pathObj = mResourceManager->getPath(path);
+ if (pathObj == nullptr)
+ return false;
+
+ return pathObj->hasPathData();
+}
+
+bool Context::hasPath(GLuint path) const
+{
+ return mResourceManager->hasPath(path);
+}
+
+void Context::setPathCommands(GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords)
+{
+ auto *pathObject = mResourceManager->getPath(path);
+
+ handleError(pathObject->setCommands(numCommands, commands, numCoords, coordType, coords));
+}
+
+void Context::setPathParameterf(GLuint path, GLenum pname, GLfloat value)
+{
+ auto *pathObj = mResourceManager->getPath(path);
+
+ switch (pname)
+ {
+ case GL_PATH_STROKE_WIDTH_CHROMIUM:
+ pathObj->setStrokeWidth(value);
+ break;
+ case GL_PATH_END_CAPS_CHROMIUM:
+ pathObj->setEndCaps(static_cast<GLenum>(value));
+ break;
+ case GL_PATH_JOIN_STYLE_CHROMIUM:
+ pathObj->setJoinStyle(static_cast<GLenum>(value));
+ break;
+ case GL_PATH_MITER_LIMIT_CHROMIUM:
+ pathObj->setMiterLimit(value);
+ break;
+ case GL_PATH_STROKE_BOUND_CHROMIUM:
+ pathObj->setStrokeBound(value);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void Context::getPathParameterfv(GLuint path, GLenum pname, GLfloat *value) const
+{
+ const auto *pathObj = mResourceManager->getPath(path);
+
+ switch (pname)
+ {
+ case GL_PATH_STROKE_WIDTH_CHROMIUM:
+ *value = pathObj->getStrokeWidth();
+ break;
+ case GL_PATH_END_CAPS_CHROMIUM:
+ *value = static_cast<GLfloat>(pathObj->getEndCaps());
+ break;
+ case GL_PATH_JOIN_STYLE_CHROMIUM:
+ *value = static_cast<GLfloat>(pathObj->getJoinStyle());
+ break;
+ case GL_PATH_MITER_LIMIT_CHROMIUM:
+ *value = pathObj->getMiterLimit();
+ break;
+ case GL_PATH_STROKE_BOUND_CHROMIUM:
+ *value = pathObj->getStrokeBound();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void Context::setPathStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ mGLState.setPathStencilFunc(func, ref, mask);
+}
+
+void Context::deleteVertexArray(GLuint vertexArray)
+{
+ auto iter = mVertexArrayMap.find(vertexArray);
+ if (iter != mVertexArrayMap.end())
+ {
+ VertexArray *vertexArrayObject = iter->second;
+ if (vertexArrayObject != nullptr)
+ {
+ detachVertexArray(vertexArray);
+ delete vertexArrayObject;
+ }
+
+ mVertexArrayMap.erase(iter);
+ mVertexArrayHandleAllocator.release(vertexArray);
+ }
+}
+
+void Context::deleteSampler(GLuint sampler)
+{
+ if (mResourceManager->getSampler(sampler))
+ {
+ detachSampler(sampler);
+ }
+
+ mResourceManager->deleteSampler(sampler);
+}
+
+void Context::deleteTransformFeedback(GLuint transformFeedback)
+{
+ auto iter = mTransformFeedbackMap.find(transformFeedback);
+ if (iter != mTransformFeedbackMap.end())
+ {
+ TransformFeedback *transformFeedbackObject = iter->second;
+ if (transformFeedbackObject != nullptr)
+ {
+ detachTransformFeedback(transformFeedback);
+ transformFeedbackObject->release();
+ }
+
+ mTransformFeedbackMap.erase(iter);
+ mTransformFeedbackAllocator.release(transformFeedback);
+ }
+}
+
+void Context::deleteFramebuffer(GLuint framebuffer)
+{
+ auto framebufferObject = mFramebufferMap.find(framebuffer);
+
+ if (framebufferObject != mFramebufferMap.end())
+ {
+ detachFramebuffer(framebuffer);
+
+ mFramebufferHandleAllocator.release(framebufferObject->first);
+ delete framebufferObject->second;
+ mFramebufferMap.erase(framebufferObject);
+ }
+}
+
+void Context::deleteFenceNV(GLuint fence)
+{
+ auto fenceObject = mFenceNVMap.find(fence);
+
+ if (fenceObject != mFenceNVMap.end())
+ {
+ mFenceNVHandleAllocator.release(fenceObject->first);
+ delete fenceObject->second;
+ mFenceNVMap.erase(fenceObject);
+ }
+}
+
+void Context::deleteQuery(GLuint query)
+{
+ auto queryObject = mQueryMap.find(query);
+ if (queryObject != mQueryMap.end())
+ {
+ mQueryHandleAllocator.release(queryObject->first);
+ if (queryObject->second)
+ {
+ queryObject->second->release();
+ }
+ mQueryMap.erase(queryObject);
+ }
+}
+
+Buffer *Context::getBuffer(GLuint handle) const
+{
+ return mResourceManager->getBuffer(handle);
+}
+
+Texture *Context::getTexture(GLuint handle) const
+{
+ return mResourceManager->getTexture(handle);
+}
+
+Renderbuffer *Context::getRenderbuffer(GLuint handle) const
+{
+ return mResourceManager->getRenderbuffer(handle);
+}
+
+FenceSync *Context::getFenceSync(GLsync handle) const
+{
+ return mResourceManager->getFenceSync(static_cast<GLuint>(reinterpret_cast<uintptr_t>(handle)));
+}
+
+VertexArray *Context::getVertexArray(GLuint handle) const
+{
+ auto vertexArray = mVertexArrayMap.find(handle);
+ return (vertexArray != mVertexArrayMap.end()) ? vertexArray->second : nullptr;
+}
+
+Sampler *Context::getSampler(GLuint handle) const
+{
+ return mResourceManager->getSampler(handle);
+}
+
+TransformFeedback *Context::getTransformFeedback(GLuint handle) const
+{
+ auto iter = mTransformFeedbackMap.find(handle);
+ return (iter != mTransformFeedbackMap.end()) ? iter->second : nullptr;
+}
+
+LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const
+{
+ switch (identifier)
+ {
+ case GL_BUFFER:
+ return getBuffer(name);
+ case GL_SHADER:
+ return getShader(name);
+ case GL_PROGRAM:
+ return getProgram(name);
+ case GL_VERTEX_ARRAY:
+ return getVertexArray(name);
+ case GL_QUERY:
+ 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);
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+LabeledObject *Context::getLabeledObjectFromPtr(const void *ptr) const
+{
+ return getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr)));
+}
+
+void Context::objectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label)
+{
+ LabeledObject *object = getLabeledObject(identifier, name);
+ ASSERT(object != nullptr);
+
+ std::string labelName = GetObjectLabelFromPointer(length, label);
+ object->setLabel(labelName);
+}
+
+void Context::objectPtrLabel(const void *ptr, GLsizei length, const GLchar *label)
+{
+ LabeledObject *object = getLabeledObjectFromPtr(ptr);
+ ASSERT(object != nullptr);
+
+ std::string labelName = GetObjectLabelFromPointer(length, label);
+ object->setLabel(labelName);
+}
+
+void Context::getObjectLabel(GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label) const
+{
+ 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) const
+{
+ LabeledObject *object = getLabeledObjectFromPtr(ptr);
+ ASSERT(object != nullptr);
+
+ const std::string &objectLabel = object->getLabel();
+ GetObjectLabelBase(objectLabel, bufSize, length, label);
+}
+
+bool Context::isSampler(GLuint samplerName) const
+{
+ return mResourceManager->isSampler(samplerName);
+}
+
+void Context::bindArrayBuffer(GLuint bufferHandle)
+{
+ Buffer *buffer = mResourceManager->checkBufferAllocation(mImplementation.get(), bufferHandle);
+ mGLState.setArrayBufferBinding(buffer);
+}
+
+void Context::bindElementArrayBuffer(GLuint bufferHandle)
+{
+ Buffer *buffer = mResourceManager->checkBufferAllocation(mImplementation.get(), bufferHandle);
+ mGLState.getVertexArray()->setElementArrayBuffer(buffer);
+}
+
+void Context::bindTexture(GLenum target, GLuint handle)
+{
+ Texture *texture = nullptr;
+
+ if (handle == 0)
+ {
+ texture = mZeroTextures[target].get();
+ }
+ else
+ {
+ texture = mResourceManager->checkTextureAllocation(mImplementation.get(), handle, target);
+ }
+
+ ASSERT(texture);
+ mGLState.setSamplerTexture(target, texture);
+}
+
+void Context::bindReadFramebuffer(GLuint framebufferHandle)
+{
+ Framebuffer *framebuffer = checkFramebufferAllocation(framebufferHandle);
+ mGLState.setReadFramebufferBinding(framebuffer);
+}
+
+void Context::bindDrawFramebuffer(GLuint framebufferHandle)
+{
+ Framebuffer *framebuffer = checkFramebufferAllocation(framebufferHandle);
+ mGLState.setDrawFramebufferBinding(framebuffer);
+}
+
+void Context::bindVertexArray(GLuint vertexArrayHandle)
+{
+ VertexArray *vertexArray = checkVertexArrayAllocation(vertexArrayHandle);
+ mGLState.setVertexArrayBinding(vertexArray);
+}
+
+void Context::bindSampler(GLuint textureUnit, GLuint samplerHandle)
+{
+ ASSERT(textureUnit < mCaps.maxCombinedTextureImageUnits);
+ Sampler *sampler =
+ mResourceManager->checkSamplerAllocation(mImplementation.get(), samplerHandle);
+ mGLState.setSamplerBinding(textureUnit, sampler);
+}
+
+void Context::bindGenericUniformBuffer(GLuint bufferHandle)
+{
+ Buffer *buffer = mResourceManager->checkBufferAllocation(mImplementation.get(), bufferHandle);
+ mGLState.setGenericUniformBufferBinding(buffer);
+}
+
+void Context::bindIndexedUniformBuffer(GLuint bufferHandle,
+ GLuint index,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ Buffer *buffer = mResourceManager->checkBufferAllocation(mImplementation.get(), bufferHandle);
+ mGLState.setIndexedUniformBufferBinding(index, buffer, offset, size);
+}
+
+void Context::bindGenericTransformFeedbackBuffer(GLuint bufferHandle)
+{
+ Buffer *buffer = mResourceManager->checkBufferAllocation(mImplementation.get(), bufferHandle);
+ mGLState.getCurrentTransformFeedback()->bindGenericBuffer(buffer);
+}
+
+void Context::bindIndexedTransformFeedbackBuffer(GLuint bufferHandle,
+ GLuint index,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ Buffer *buffer = mResourceManager->checkBufferAllocation(mImplementation.get(), bufferHandle);
+ mGLState.getCurrentTransformFeedback()->bindIndexedBuffer(index, buffer, offset, size);
+}
+
+void Context::bindCopyReadBuffer(GLuint bufferHandle)
+{
+ Buffer *buffer = mResourceManager->checkBufferAllocation(mImplementation.get(), bufferHandle);
+ mGLState.setCopyReadBufferBinding(buffer);
+}
+
+void Context::bindCopyWriteBuffer(GLuint bufferHandle)
+{
+ Buffer *buffer = mResourceManager->checkBufferAllocation(mImplementation.get(), bufferHandle);
+ mGLState.setCopyWriteBufferBinding(buffer);
+}
+
+void Context::bindPixelPackBuffer(GLuint bufferHandle)
+{
+ Buffer *buffer = mResourceManager->checkBufferAllocation(mImplementation.get(), bufferHandle);
+ mGLState.setPixelPackBufferBinding(buffer);
+}
+
+void Context::bindPixelUnpackBuffer(GLuint bufferHandle)
+{
+ Buffer *buffer = mResourceManager->checkBufferAllocation(mImplementation.get(), bufferHandle);
+ mGLState.setPixelUnpackBufferBinding(buffer);
+}
+
+void Context::useProgram(GLuint program)
+{
+ mGLState.setProgram(getProgram(program));
+}
+
+void Context::bindTransformFeedback(GLuint transformFeedbackHandle)
+{
+ TransformFeedback *transformFeedback =
+ checkTransformFeedbackAllocation(transformFeedbackHandle);
+ mGLState.setTransformFeedbackBinding(transformFeedback);
+}
+
+Error Context::beginQuery(GLenum target, GLuint query)
+{
+ Query *queryObject = getQuery(query, true, target);
+ ASSERT(queryObject);
+
+ // begin query
+ Error error = queryObject->begin();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // set query as active for specified target only if begin succeeded
+ mGLState.setActiveQuery(target, queryObject);
+
+ return Error(GL_NO_ERROR);
+}
+
+Error Context::endQuery(GLenum target)
+{
+ Query *queryObject = mGLState.getActiveQuery(target);
+ ASSERT(queryObject);
+
+ gl::Error error = queryObject->end();
+
+ // Always unbind the query, even if there was an error. This may delete the query object.
+ mGLState.setActiveQuery(target, NULL);
+
+ return error;
+}
+
+Error Context::queryCounter(GLuint id, GLenum target)
+{
+ ASSERT(target == GL_TIMESTAMP_EXT);
+
+ Query *queryObject = getQuery(id, true, target);
+ ASSERT(queryObject);
+
+ return queryObject->queryCounter();
+}
+
+void Context::getQueryiv(GLenum target, GLenum pname, GLint *params)
+{
+ switch (pname)
+ {
+ case GL_CURRENT_QUERY_EXT:
+ params[0] = mGLState.getActiveQueryId(target);
+ break;
+ case GL_QUERY_COUNTER_BITS_EXT:
+ switch (target)
+ {
+ case GL_TIME_ELAPSED_EXT:
+ params[0] = getExtensions().queryCounterBitsTimeElapsed;
+ break;
+ case GL_TIMESTAMP_EXT:
+ params[0] = getExtensions().queryCounterBitsTimestamp;
+ break;
+ default:
+ UNREACHABLE();
+ params[0] = 0;
+ break;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+void Context::getQueryObjectiv(GLuint id, GLenum pname, GLint *params)
+{
+ handleError(GetQueryObjectParameter(getQuery(id), pname, params));
+}
+
+void Context::getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
+{
+ handleError(GetQueryObjectParameter(getQuery(id), pname, params));
+}
+
+void Context::getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params)
+{
+ handleError(GetQueryObjectParameter(getQuery(id), pname, params));
+}
+
+void Context::getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params)
+{
+ handleError(GetQueryObjectParameter(getQuery(id), pname, params));
+}
+
+Framebuffer *Context::getFramebuffer(unsigned int handle) const
+{
+ auto framebufferIt = mFramebufferMap.find(handle);
+ return ((framebufferIt == mFramebufferMap.end()) ? nullptr : framebufferIt->second);
+}
+
+FenceNV *Context::getFenceNV(unsigned int handle)
+{
+ auto fence = mFenceNVMap.find(handle);
+
+ if (fence == mFenceNVMap.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ return fence->second;
+ }
+}
+
+Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
+{
+ auto query = mQueryMap.find(handle);
+
+ if (query == mQueryMap.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ if (!query->second && create)
+ {
+ query->second = new Query(mImplementation->createQuery(type), handle);
+ query->second->addRef();
+ }
+ return query->second;
+ }
+}
+
+Query *Context::getQuery(GLuint handle) const
+{
+ auto iter = mQueryMap.find(handle);
+ return (iter != mQueryMap.end()) ? iter->second : nullptr;
+}
+
+Texture *Context::getTargetTexture(GLenum target) const
+{
+ ASSERT(ValidTextureTarget(this, target) || ValidTextureExternalTarget(this, target));
+ return mGLState.getTargetTexture(target);
+}
+
+Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const
+{
+ return mGLState.getSamplerTexture(sampler, type);
+}
+
+Compiler *Context::getCompiler() const
+{
+ return mCompiler;
+}
+
+void Context::getBooleanv(GLenum pname, GLboolean *params)
+{
+ switch (pname)
+ {
+ case GL_SHADER_COMPILER: *params = GL_TRUE; break;
+ case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break;
+ default:
+ mGLState.getBooleanv(pname, params);
+ break;
+ }
+}
+
+void Context::getFloatv(GLenum pname, GLfloat *params)
+{
+ // 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] = mCaps.minAliasedLineWidth;
+ params[1] = mCaps.maxAliasedLineWidth;
+ break;
+ case GL_ALIASED_POINT_SIZE_RANGE:
+ params[0] = mCaps.minAliasedPointSize;
+ params[1] = mCaps.maxAliasedPointSize;
+ break;
+ case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+ ASSERT(mExtensions.textureFilterAnisotropic);
+ *params = mExtensions.maxTextureAnisotropy;
+ break;
+ case GL_MAX_TEXTURE_LOD_BIAS:
+ *params = mCaps.maxLODBias;
+ break;
+
+ case GL_PATH_MODELVIEW_MATRIX_CHROMIUM:
+ case GL_PATH_PROJECTION_MATRIX_CHROMIUM:
+ {
+ ASSERT(mExtensions.pathRendering);
+ const GLfloat *m = mGLState.getPathRenderingMatrix(pname);
+ memcpy(params, m, 16 * sizeof(GLfloat));
+ }
+ break;
+
+ default:
+ mGLState.getFloatv(pname, params);
+ break;
+ }
+}
+
+void Context::getIntegerv(GLenum pname, GLint *params)
+{
+ // 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 = mCaps.maxVertexAttributes; break;
+ case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mCaps.maxVertexUniformVectors; break;
+ case GL_MAX_VERTEX_UNIFORM_COMPONENTS: *params = mCaps.maxVertexUniformComponents; break;
+ case GL_MAX_VARYING_VECTORS: *params = mCaps.maxVaryingVectors; break;
+ case GL_MAX_VARYING_COMPONENTS: *params = mCaps.maxVertexOutputComponents; break;
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mCaps.maxCombinedTextureImageUnits; break;
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxVertexTextureImageUnits; break;
+ case GL_MAX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxTextureImageUnits; break;
+ case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mCaps.maxFragmentUniformVectors; break;
+ case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: *params = mCaps.maxFragmentUniformComponents; break;
+ case GL_MAX_RENDERBUFFER_SIZE: *params = mCaps.maxRenderbufferSize; break;
+ case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mCaps.maxColorAttachments; break;
+ case GL_MAX_DRAW_BUFFERS_EXT: *params = mCaps.maxDrawBuffers; break;
+ //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
+ case GL_SUBPIXEL_BITS: *params = 4; break;
+ case GL_MAX_TEXTURE_SIZE: *params = mCaps.max2DTextureSize; break;
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = mCaps.maxCubeMapTextureSize; break;
+ case GL_MAX_3D_TEXTURE_SIZE: *params = mCaps.max3DTextureSize; break;
+ case GL_MAX_ARRAY_TEXTURE_LAYERS: *params = mCaps.maxArrayTextureLayers; break;
+ case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: *params = mCaps.uniformBufferOffsetAlignment; break;
+ case GL_MAX_UNIFORM_BUFFER_BINDINGS: *params = mCaps.maxUniformBufferBindings; break;
+ case GL_MAX_VERTEX_UNIFORM_BLOCKS: *params = mCaps.maxVertexUniformBlocks; break;
+ case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: *params = mCaps.maxFragmentUniformBlocks; break;
+ case GL_MAX_COMBINED_UNIFORM_BLOCKS: *params = mCaps.maxCombinedTextureImageUnits; break;
+ case GL_MAX_VERTEX_OUTPUT_COMPONENTS: *params = mCaps.maxVertexOutputComponents; break;
+ case GL_MAX_FRAGMENT_INPUT_COMPONENTS: *params = mCaps.maxFragmentInputComponents; break;
+ case GL_MIN_PROGRAM_TEXEL_OFFSET: *params = mCaps.minProgramTexelOffset; break;
+ case GL_MAX_PROGRAM_TEXEL_OFFSET: *params = 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 = mCaps.maxElementsIndices; break;
+ case GL_MAX_ELEMENTS_VERTICES: *params = mCaps.maxElementsVertices; break;
+ case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: *params = mCaps.maxTransformFeedbackInterleavedComponents; break;
+ case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: *params = mCaps.maxTransformFeedbackSeparateAttributes; break;
+ case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: *params = mCaps.maxTransformFeedbackSeparateComponents; break;
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+ *params = static_cast<GLint>(mCaps.compressedTextureFormats.size());
+ break;
+ case GL_MAX_SAMPLES_ANGLE: *params = mCaps.maxSamples; break;
+ case GL_MAX_VIEWPORT_DIMS:
+ {
+ params[0] = mCaps.maxViewportWidth;
+ params[1] = mCaps.maxViewportHeight;
+ }
+ break;
+ case GL_COMPRESSED_TEXTURE_FORMATS:
+ std::copy(mCaps.compressedTextureFormats.begin(), mCaps.compressedTextureFormats.end(), params);
+ break;
+ case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+ *params = mResetStrategy;
+ break;
+ case GL_NUM_SHADER_BINARY_FORMATS:
+ *params = static_cast<GLint>(mCaps.shaderBinaryFormats.size());
+ break;
+ case GL_SHADER_BINARY_FORMATS:
+ std::copy(mCaps.shaderBinaryFormats.begin(), mCaps.shaderBinaryFormats.end(), params);
+ break;
+ case GL_NUM_PROGRAM_BINARY_FORMATS:
+ *params = static_cast<GLint>(mCaps.programBinaryFormats.size());
+ break;
+ case GL_PROGRAM_BINARY_FORMATS:
+ std::copy(mCaps.programBinaryFormats.begin(), mCaps.programBinaryFormats.end(), params);
+ break;
+ case GL_NUM_EXTENSIONS:
+ *params = static_cast<GLint>(mExtensionStrings.size());
+ break;
+
+ // GL_KHR_debug
+ case GL_MAX_DEBUG_MESSAGE_LENGTH:
+ *params = mExtensions.maxDebugMessageLength;
+ break;
+ case GL_MAX_DEBUG_LOGGED_MESSAGES:
+ *params = mExtensions.maxDebugLoggedMessages;
+ break;
+ case GL_MAX_DEBUG_GROUP_STACK_DEPTH:
+ *params = mExtensions.maxDebugGroupStackDepth;
+ break;
+ case GL_MAX_LABEL_LENGTH:
+ *params = mExtensions.maxLabelLength;
+ break;
+
+ // GL_EXT_disjoint_timer_query
+ case GL_GPU_DISJOINT_EXT:
+ *params = mImplementation->getGPUDisjoint();
+ break;
+ case GL_MAX_FRAMEBUFFER_WIDTH:
+ *params = mCaps.maxFramebufferWidth;
+ break;
+ case GL_MAX_FRAMEBUFFER_HEIGHT:
+ *params = mCaps.maxFramebufferHeight;
+ break;
+ case GL_MAX_FRAMEBUFFER_SAMPLES:
+ *params = mCaps.maxFramebufferSamples;
+ break;
+ case GL_MAX_SAMPLE_MASK_WORDS:
+ *params = mCaps.maxSampleMaskWords;
+ break;
+ case GL_MAX_COLOR_TEXTURE_SAMPLES:
+ *params = mCaps.maxColorTextureSamples;
+ break;
+ case GL_MAX_DEPTH_TEXTURE_SAMPLES:
+ *params = mCaps.maxDepthTextureSamples;
+ break;
+ case GL_MAX_INTEGER_SAMPLES:
+ *params = mCaps.maxIntegerSamples;
+ break;
+ case GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET:
+ *params = mCaps.maxVertexAttribRelativeOffset;
+ break;
+ case GL_MAX_VERTEX_ATTRIB_BINDINGS:
+ *params = mCaps.maxVertexAttribBindings;
+ break;
+ case GL_MAX_VERTEX_ATTRIB_STRIDE:
+ *params = mCaps.maxVertexAttribStride;
+ break;
+ case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
+ *params = mCaps.maxVertexAtomicCounterBuffers;
+ break;
+ case GL_MAX_VERTEX_ATOMIC_COUNTERS:
+ *params = mCaps.maxVertexAtomicCounters;
+ break;
+ case GL_MAX_VERTEX_IMAGE_UNIFORMS:
+ *params = mCaps.maxVertexImageUniforms;
+ break;
+ case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
+ *params = mCaps.maxVertexShaderStorageBlocks;
+ break;
+ case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
+ *params = mCaps.maxFragmentAtomicCounterBuffers;
+ break;
+ case GL_MAX_FRAGMENT_ATOMIC_COUNTERS:
+ *params = mCaps.maxFragmentAtomicCounters;
+ break;
+ case GL_MAX_FRAGMENT_IMAGE_UNIFORMS:
+ *params = mCaps.maxFragmentImageUniforms;
+ break;
+ case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
+ *params = mCaps.maxFragmentShaderStorageBlocks;
+ break;
+ case GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET:
+ *params = mCaps.minProgramTextureGatherOffset;
+ break;
+ case GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET:
+ *params = mCaps.maxProgramTextureGatherOffset;
+ break;
+ case GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS:
+ *params = mCaps.maxComputeWorkGroupInvocations;
+ break;
+ case GL_MAX_COMPUTE_UNIFORM_BLOCKS:
+ *params = mCaps.maxComputeUniformBlocks;
+ break;
+ case GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS:
+ *params = mCaps.maxComputeTextureImageUnits;
+ break;
+ case GL_MAX_COMPUTE_SHARED_MEMORY_SIZE:
+ *params = mCaps.maxComputeSharedMemorySize;
+ break;
+ case GL_MAX_COMPUTE_UNIFORM_COMPONENTS:
+ *params = mCaps.maxComputeUniformComponents;
+ break;
+ case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
+ *params = mCaps.maxComputeAtomicCounterBuffers;
+ break;
+ case GL_MAX_COMPUTE_ATOMIC_COUNTERS:
+ *params = mCaps.maxComputeAtomicCounters;
+ break;
+ case GL_MAX_COMPUTE_IMAGE_UNIFORMS:
+ *params = mCaps.maxComputeImageUniforms;
+ break;
+ case GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS:
+ *params = mCaps.maxCombinedComputeUniformComponents;
+ break;
+ case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
+ *params = mCaps.maxComputeShaderStorageBlocks;
+ break;
+ case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
+ *params = mCaps.maxCombinedShaderOutputResources;
+ break;
+ case GL_MAX_UNIFORM_LOCATIONS:
+ *params = mCaps.maxUniformLocations;
+ break;
+ case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
+ *params = mCaps.maxAtomicCounterBufferBindings;
+ break;
+ case GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE:
+ *params = mCaps.maxAtomicCounterBufferSize;
+ break;
+ case GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS:
+ *params = mCaps.maxCombinedAtomicCounterBuffers;
+ break;
+ case GL_MAX_COMBINED_ATOMIC_COUNTERS:
+ *params = mCaps.maxCombinedAtomicCounters;
+ break;
+ case GL_MAX_IMAGE_UNITS:
+ *params = mCaps.maxImageUnits;
+ break;
+ case GL_MAX_COMBINED_IMAGE_UNIFORMS:
+ *params = mCaps.maxCombinedImageUniforms;
+ break;
+ case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
+ *params = mCaps.maxShaderStorageBufferBindings;
+ break;
+ case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
+ *params = mCaps.maxCombinedShaderStorageBlocks;
+ break;
+ case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
+ *params = mCaps.shaderStorageBufferOffsetAlignment;
+ break;
+ default:
+ mGLState.getIntegerv(mState, pname, params);
+ break;
+ }
+}
+
+void Context::getInteger64v(GLenum pname, GLint64 *params)
+{
+ // 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 = mCaps.maxElementIndex;
+ break;
+ case GL_MAX_UNIFORM_BLOCK_SIZE:
+ *params = mCaps.maxUniformBlockSize;
+ break;
+ case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
+ *params = mCaps.maxCombinedVertexUniformComponents;
+ break;
+ case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
+ *params = mCaps.maxCombinedFragmentUniformComponents;
+ break;
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ *params = mCaps.maxServerWaitTimeout;
+ break;
+
+ // GL_EXT_disjoint_timer_query
+ case GL_TIMESTAMP_EXT:
+ *params = mImplementation->getTimestamp();
+ break;
+
+ case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
+ *params = mCaps.maxShaderStorageBlockSize;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void Context::getPointerv(GLenum pname, void **params) const
+{
+ mGLState.getPointerv(pname, params);
+}
+
+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 = mCaps.maxComputeWorkGroupCount[index];
+ break;
+ case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
+ ASSERT(index < 3u);
+ *data = mCaps.maxComputeWorkGroupSize[index];
+ break;
+ default:
+ mGLState.getIntegeri_v(target, index, data);
+ }
+ }
+ else
+ {
+ CastIndexedStateValues(this, nativeType, target, index, numParams, 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)
+ {
+ mGLState.getInteger64i_v(target, index, data);
+ }
+ else
+ {
+ CastIndexedStateValues(this, nativeType, target, index, numParams, 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)
+ {
+ mGLState.getBooleani_v(target, index, data);
+ }
+ else
+ {
+ CastIndexedStateValues(this, nativeType, target, index, numParams, data);
+ }
+}
+
+Error Context::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ syncRendererState();
+ ANGLE_TRY(mImplementation->drawArrays(mode, first, count));
+ MarkTransformFeedbackBufferUsage(mGLState.getCurrentTransformFeedback());
+
+ return NoError();
+}
+
+Error Context::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
+{
+ syncRendererState();
+ ANGLE_TRY(mImplementation->drawArraysInstanced(mode, first, count, instanceCount));
+ MarkTransformFeedbackBufferUsage(mGLState.getCurrentTransformFeedback());
+
+ return NoError();
+}
+
+Error Context::drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const IndexRange &indexRange)
+{
+ syncRendererState();
+ return mImplementation->drawElements(mode, count, type, indices, indexRange);
+}
+
+Error Context::drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const IndexRange &indexRange)
+{
+ syncRendererState();
+ return mImplementation->drawElementsInstanced(mode, count, type, indices, instances,
+ indexRange);
+}
+
+Error Context::drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const IndexRange &indexRange)
+{
+ syncRendererState();
+ return mImplementation->drawRangeElements(mode, start, end, count, type, indices, indexRange);
+}
+
+Error Context::flush()
+{
+ return mImplementation->flush();
+}
+
+Error Context::finish()
+{
+ return mImplementation->finish();
+}
+
+void Context::insertEventMarker(GLsizei length, const char *marker)
+{
+ ASSERT(mImplementation);
+ mImplementation->insertEventMarker(length, marker);
+}
+
+void Context::pushGroupMarker(GLsizei length, const char *marker)
+{
+ ASSERT(mImplementation);
+ mImplementation->pushGroupMarker(length, marker);
+}
+
+void Context::popGroupMarker()
+{
+ ASSERT(mImplementation);
+ mImplementation->popGroupMarker();
+}
+
+void Context::bindUniformLocation(GLuint program, GLint location, const GLchar *name)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+
+ programObject->bindUniformLocation(location, name);
+}
+
+void Context::setCoverageModulation(GLenum components)
+{
+ mGLState.setCoverageModulation(components);
+}
+
+void Context::loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix)
+{
+ mGLState.loadPathRenderingMatrix(matrixMode, matrix);
+}
+
+void Context::loadPathRenderingIdentityMatrix(GLenum matrixMode)
+{
+ GLfloat I[16];
+ angle::Matrix<GLfloat>::setToIdentity(I);
+
+ mGLState.loadPathRenderingMatrix(matrixMode, I);
+}
+
+void Context::stencilFillPath(GLuint path, GLenum fillMode, GLuint mask)
+{
+ const auto *pathObj = mResourceManager->getPath(path);
+ if (!pathObj)
+ return;
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->stencilFillPath(pathObj, fillMode, mask);
+}
+
+void Context::stencilStrokePath(GLuint path, GLint reference, GLuint mask)
+{
+ const auto *pathObj = mResourceManager->getPath(path);
+ if (!pathObj)
+ return;
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->stencilStrokePath(pathObj, reference, mask);
+}
+
+void Context::coverFillPath(GLuint path, GLenum coverMode)
+{
+ const auto *pathObj = mResourceManager->getPath(path);
+ if (!pathObj)
+ return;
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->coverFillPath(pathObj, coverMode);
+}
+
+void Context::coverStrokePath(GLuint path, GLenum coverMode)
+{
+ const auto *pathObj = mResourceManager->getPath(path);
+ if (!pathObj)
+ return;
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->coverStrokePath(pathObj, coverMode);
+}
+
+void Context::stencilThenCoverFillPath(GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode)
+{
+ const auto *pathObj = mResourceManager->getPath(path);
+ if (!pathObj)
+ return;
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->stencilThenCoverFillPath(pathObj, fillMode, mask, coverMode);
+}
+
+void Context::stencilThenCoverStrokePath(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode)
+{
+ const auto *pathObj = mResourceManager->getPath(path);
+ if (!pathObj)
+ return;
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->stencilThenCoverStrokePath(pathObj, reference, mask, coverMode);
+}
+
+void Context::coverFillPathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjects =
+ GatherPaths(*mResourceManager, numPaths, pathNameType, paths, pathBase);
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->coverFillPathInstanced(pathObjects, coverMode, transformType, transformValues);
+}
+
+void Context::coverStrokePathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjects =
+ GatherPaths(*mResourceManager, numPaths, pathNameType, paths, pathBase);
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->coverStrokePathInstanced(pathObjects, coverMode, transformType,
+ transformValues);
+}
+
+void Context::stencilFillPathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjects =
+ GatherPaths(*mResourceManager, numPaths, pathNameType, paths, pathBase);
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->stencilFillPathInstanced(pathObjects, fillMode, mask, transformType,
+ transformValues);
+}
+
+void Context::stencilStrokePathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjects =
+ GatherPaths(*mResourceManager, numPaths, pathNameType, paths, pathBase);
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->stencilStrokePathInstanced(pathObjects, reference, mask, transformType,
+ transformValues);
+}
+
+void Context::stencilThenCoverFillPathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjects =
+ GatherPaths(*mResourceManager, numPaths, pathNameType, paths, pathBase);
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->stencilThenCoverFillPathInstanced(pathObjects, coverMode, fillMode, mask,
+ transformType, transformValues);
+}
+
+void Context::stencilThenCoverStrokePathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjects =
+ GatherPaths(*mResourceManager, numPaths, pathNameType, paths, pathBase);
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->stencilThenCoverStrokePathInstanced(pathObjects, coverMode, reference, mask,
+ transformType, transformValues);
+}
+
+void Context::bindFragmentInputLocation(GLuint program, GLint location, const GLchar *name)
+{
+ auto *programObject = getProgram(program);
+
+ programObject->bindFragmentInputLocation(location, name);
+}
+
+void Context::programPathFragmentInputGen(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ auto *programObject = getProgram(program);
+
+ programObject->pathFragmentInputGen(location, genMode, components, coeffs);
+}
+
+void Context::handleError(const Error &error)
+{
+ if (error.isError())
+ {
+ GLenum code = error.getCode();
+ mErrors.insert(code);
+ if (code == GL_OUT_OF_MEMORY && getWorkarounds().loseContextOnOutOfMemory)
+ {
+ markContextLost();
+ }
+
+ if (!error.getMessage().empty())
+ {
+ auto *debug = &mGLState.getDebug();
+ debug->insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, error.getID(),
+ GL_DEBUG_SEVERITY_HIGH, error.getMessage());
+ }
+ }
+}
+
+// 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
+ {
+ GLenum error = *mErrors.begin();
+ mErrors.erase(mErrors.begin());
+ return error;
+ }
+}
+
+// NOTE: this function should not assume that this context is current!
+void Context::markContextLost()
+{
+ if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
+ {
+ mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT;
+ mContextLostForced = true;
+ }
+ mContextLost = true;
+}
+
+bool Context::isContextLost()
+{
+ return mContextLost;
+}
+
+GLenum Context::getResetStatus()
+{
+ // 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 (!mContextLost && mImplementation->getResetStatus() != GL_NO_ERROR)
+ {
+ mContextLost = true;
+ }
+
+ // 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 (!mContextLost)
+ {
+ ASSERT(mResetStatus == GL_NO_ERROR);
+ mResetStatus = mImplementation->getResetStatus();
+
+ if (mResetStatus != GL_NO_ERROR)
+ {
+ mContextLost = true;
+ }
+ }
+ else if (!mContextLostForced && mResetStatus != GL_NO_ERROR)
+ {
+ // 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 mResetStatus;
+}
+
+bool Context::isResetNotificationEnabled()
+{
+ return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
+}
+
+const egl::Config *Context::getConfig() const
+{
+ return mConfig;
+}
+
+EGLenum Context::getClientType() const
+{
+ return mClientType;
+}
+
+EGLenum Context::getRenderBuffer() const
+{
+ auto framebufferIt = mFramebufferMap.find(0);
+ if (framebufferIt != mFramebufferMap.end())
+ {
+ const Framebuffer *framebuffer = framebufferIt->second;
+ const FramebufferAttachment *backAttachment = framebuffer->getAttachment(GL_BACK);
+
+ ASSERT(backAttachment != nullptr);
+ return backAttachment->getSurface()->getRenderBuffer();
+ }
+ else
+ {
+ return EGL_NONE;
+ }
+}
+
+VertexArray *Context::checkVertexArrayAllocation(GLuint vertexArrayHandle)
+{
+ // Only called after a prior call to Gen.
+ VertexArray *vertexArray = getVertexArray(vertexArrayHandle);
+ if (!vertexArray)
+ {
+ vertexArray = new VertexArray(mImplementation.get(), vertexArrayHandle, MAX_VERTEX_ATTRIBS);
+
+ mVertexArrayMap[vertexArrayHandle] = vertexArray;
+ }
+
+ return vertexArray;
+}
+
+TransformFeedback *Context::checkTransformFeedbackAllocation(GLuint transformFeedbackHandle)
+{
+ // Only called after a prior call to Gen.
+ TransformFeedback *transformFeedback = getTransformFeedback(transformFeedbackHandle);
+ if (!transformFeedback)
+ {
+ transformFeedback =
+ new TransformFeedback(mImplementation.get(), transformFeedbackHandle, mCaps);
+ transformFeedback->addRef();
+ mTransformFeedbackMap[transformFeedbackHandle] = transformFeedback;
+ }
+
+ return transformFeedback;
+}
+
+Framebuffer *Context::checkFramebufferAllocation(GLuint framebuffer)
+{
+ // Can be called from Bind without a prior call to Gen.
+ auto framebufferIt = mFramebufferMap.find(framebuffer);
+ bool neverCreated = framebufferIt == mFramebufferMap.end();
+ if (neverCreated || framebufferIt->second == nullptr)
+ {
+ Framebuffer *newFBO = new Framebuffer(mCaps, mImplementation.get(), framebuffer);
+ if (neverCreated)
+ {
+ mFramebufferHandleAllocator.reserve(framebuffer);
+ mFramebufferMap[framebuffer] = newFBO;
+ return newFBO;
+ }
+
+ framebufferIt->second = newFBO;
+ }
+
+ return framebufferIt->second;
+}
+
+bool Context::isVertexArrayGenerated(GLuint vertexArray)
+{
+ ASSERT(mVertexArrayMap.find(0) != mVertexArrayMap.end());
+ return mVertexArrayMap.find(vertexArray) != mVertexArrayMap.end();
+}
+
+bool Context::isTransformFeedbackGenerated(GLuint transformFeedback)
+{
+ ASSERT(mTransformFeedbackMap.find(0) != mTransformFeedbackMap.end());
+ return mTransformFeedbackMap.find(transformFeedback) != mTransformFeedbackMap.end();
+}
+
+void Context::detachTexture(GLuint texture)
+{
+ // 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.
+ mGLState.detachTexture(mZeroTextures, texture);
+}
+
+void Context::detachBuffer(GLuint 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
+ mGLState.detachBuffer(buffer);
+}
+
+void Context::detachFramebuffer(GLuint 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 (mGLState.removeReadFramebufferBinding(framebuffer) && framebuffer != 0)
+ {
+ bindReadFramebuffer(0);
+ }
+
+ if (mGLState.removeDrawFramebufferBinding(framebuffer) && framebuffer != 0)
+ {
+ bindDrawFramebuffer(0);
+ }
+}
+
+void Context::detachRenderbuffer(GLuint renderbuffer)
+{
+ mGLState.detachRenderbuffer(renderbuffer);
+}
+
+void Context::detachVertexArray(GLuint 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 (mGLState.removeVertexArrayBinding(vertexArray))
+ {
+ bindVertexArray(0);
+ }
+}
+
+void Context::detachTransformFeedback(GLuint 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 (mGLState.removeTransformFeedbackBinding(transformFeedback))
+ {
+ bindTransformFeedback(0);
+ }
+}
+
+void Context::detachSampler(GLuint sampler)
+{
+ mGLState.detachSampler(sampler);
+}
+
+void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
+{
+ mGLState.setVertexAttribDivisor(index, divisor);
+}
+
+void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param)
+{
+ Sampler *samplerObject =
+ mResourceManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameteri(samplerObject, pname, param);
+}
+
+void Context::samplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)
+{
+ Sampler *samplerObject =
+ mResourceManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameteriv(samplerObject, pname, param);
+}
+
+void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
+{
+ Sampler *samplerObject =
+ mResourceManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameterf(samplerObject, pname, param);
+}
+
+void Context::samplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)
+{
+ Sampler *samplerObject =
+ mResourceManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameterfv(samplerObject, pname, param);
+}
+
+void Context::getSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
+{
+ const Sampler *samplerObject =
+ mResourceManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ QuerySamplerParameteriv(samplerObject, pname, params);
+}
+
+void Context::getSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
+{
+ const Sampler *samplerObject =
+ mResourceManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ QuerySamplerParameterfv(samplerObject, pname, params);
+}
+
+void Context::programParameteri(GLuint program, GLenum pname, GLint value)
+{
+ gl::Program *programObject = getProgram(program);
+ ASSERT(programObject != nullptr);
+
+ ASSERT(pname == GL_PROGRAM_BINARY_RETRIEVABLE_HINT);
+ programObject->setBinaryRetrievableHint(value != GL_FALSE);
+}
+
+void Context::initRendererString()
+{
+ std::ostringstream rendererString;
+ rendererString << "ANGLE (";
+ rendererString << mImplementation->getRendererDescription();
+ rendererString << ")";
+
+ mRendererString = MakeStaticString(rendererString.str());
+}
+
+const char *Context::getRendererString() const
+{
+ return mRendererString;
+}
+
+void Context::initExtensionStrings()
+{
+ for (const auto &extensionString : mExtensions.getStrings())
+ {
+ mExtensionStrings.push_back(MakeStaticString(extensionString));
+ }
+
+ std::ostringstream combinedStringStream;
+ std::copy(mExtensionStrings.begin(), mExtensionStrings.end(),
+ std::ostream_iterator<const char *>(combinedStringStream, " "));
+ mExtensionString = MakeStaticString(combinedStringStream.str());
+}
+
+const char *Context::getExtensionString() const
+{
+ return mExtensionString;
+}
+
+const char *Context::getExtensionString(size_t idx) const
+{
+ return mExtensionStrings[idx];
+}
+
+size_t Context::getExtensionStringCount() const
+{
+ return mExtensionStrings.size();
+}
+
+void Context::beginTransformFeedback(GLenum primitiveMode)
+{
+ TransformFeedback *transformFeedback = mGLState.getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+ ASSERT(!transformFeedback->isPaused());
+
+ transformFeedback->begin(primitiveMode, mGLState.getProgram());
+}
+
+bool Context::hasActiveTransformFeedback(GLuint program) const
+{
+ for (auto pair : mTransformFeedbackMap)
+ {
+ if (pair.second != nullptr && pair.second->hasBoundProgram(program))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void Context::initCaps(bool webGLContext)
+{
+ mCaps = mImplementation->getNativeCaps();
+
+ mExtensions = mImplementation->getNativeExtensions();
+
+ mLimitations = mImplementation->getNativeLimitations();
+
+ if (getClientVersion() < Version(3, 0))
+ {
+ // Disable ES3+ extensions
+ mExtensions.colorBufferFloat = false;
+ mExtensions.eglImageExternalEssl3 = false;
+ mExtensions.textureNorm16 = false;
+ }
+
+ if (getClientVersion() > Version(2, 0))
+ {
+ // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts
+ //mExtensions.sRGB = false;
+ }
+
+ // Some extensions are always available because they are implemented in the GL layer.
+ mExtensions.bindUniformLocation = true;
+ mExtensions.vertexArrayObject = true;
+ mExtensions.bindGeneratesResource = true;
+
+ // Enable the no error extension if the context was created with the flag.
+ mExtensions.noError = mSkipValidation;
+
+ // Explicitly enable GL_KHR_debug
+ mExtensions.debug = true;
+ mExtensions.maxDebugMessageLength = 1024;
+ mExtensions.maxDebugLoggedMessages = 1024;
+ mExtensions.maxDebugGroupStackDepth = 1024;
+ mExtensions.maxLabelLength = 1024;
+
+ // Explicitly enable GL_ANGLE_robust_client_memory
+ mExtensions.robustClientMemory = true;
+
+ // Apply implementation limits
+ mCaps.maxVertexAttributes = std::min<GLuint>(mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS);
+ mCaps.maxVertexUniformBlocks = std::min<GLuint>(mCaps.maxVertexUniformBlocks, IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS);
+ mCaps.maxVertexOutputComponents = std::min<GLuint>(mCaps.maxVertexOutputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
+
+ mCaps.maxFragmentInputComponents = std::min<GLuint>(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
+
+ // WebGL compatibility
+ mExtensions.webglCompatibility = webGLContext;
+ for (const auto &extensionInfo : GetExtensionInfoMap())
+ {
+ // If this context is for WebGL, disable all enableable extensions
+ if (webGLContext && extensionInfo.second.Enableable)
+ {
+ mExtensions.*(extensionInfo.second.ExtensionsMember) = false;
+ }
+ }
+
+ // Generate texture caps
+ updateCaps();
+}
+
+void Context::updateCaps()
+{
+ mCaps.compressedTextureFormats.clear();
+ mTextureCaps.clear();
+
+ const TextureCapsMap &rendererFormats = mImplementation->getNativeTextureCaps();
+ for (TextureCapsMap::const_iterator i = rendererFormats.begin(); i != rendererFormats.end(); i++)
+ {
+ GLenum format = i->first;
+ TextureCaps formatCaps = i->second;
+
+ const InternalFormat &formatInfo = GetInternalFormatInfo(format);
+
+ // 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(), mExtensions);
+ formatCaps.renderable =
+ formatCaps.renderable && formatInfo.renderSupport(getClientVersion(), mExtensions);
+ formatCaps.filterable =
+ formatCaps.filterable && formatInfo.filterSupport(getClientVersion(), mExtensions);
+
+ // OpenGL ES does not support multisampling with integer formats
+ if (!formatInfo.renderSupport || formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT)
+ {
+ formatCaps.sampleCounts.clear();
+ }
+
+ if (formatCaps.texturable && formatInfo.compressed)
+ {
+ mCaps.compressedTextureFormats.push_back(format);
+ }
+
+ mTextureCaps.insert(format, formatCaps);
+ }
+}
+
+void Context::initWorkarounds()
+{
+ // Lose the context upon out of memory error if the application is
+ // expecting to watch for those events.
+ mWorkarounds.loseContextOnOutOfMemory = (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
+}
+
+void Context::syncRendererState()
+{
+ const State::DirtyBits &dirtyBits = mGLState.getDirtyBits();
+ mImplementation->syncState(mGLState, dirtyBits);
+ mGLState.clearDirtyBits();
+ mGLState.syncDirtyObjects();
+}
+
+void Context::syncRendererState(const State::DirtyBits &bitMask,
+ const State::DirtyObjects &objectMask)
+{
+ const State::DirtyBits &dirtyBits = (mGLState.getDirtyBits() & bitMask);
+ mImplementation->syncState(mGLState, dirtyBits);
+ mGLState.clearDirtyBits(dirtyBits);
+
+ mGLState.syncDirtyObjects(objectMask);
+}
+
+void Context::blitFramebuffer(GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
+{
+ Framebuffer *drawFramebuffer = mGLState.getDrawFramebuffer();
+ ASSERT(drawFramebuffer);
+
+ Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
+ Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
+
+ syncStateForBlit();
+
+ handleError(drawFramebuffer->blit(mImplementation.get(), srcArea, dstArea, mask, filter));
+}
+
+void Context::clear(GLbitfield mask)
+{
+ syncStateForClear();
+ handleError(mGLState.getDrawFramebuffer()->clear(mImplementation.get(), mask));
+}
+
+void Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values)
+{
+ syncStateForClear();
+ handleError(mGLState.getDrawFramebuffer()->clearBufferfv(mImplementation.get(), buffer,
+ drawbuffer, values));
+}
+
+void Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values)
+{
+ syncStateForClear();
+ handleError(mGLState.getDrawFramebuffer()->clearBufferuiv(mImplementation.get(), buffer,
+ drawbuffer, values));
+}
+
+void Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values)
+{
+ syncStateForClear();
+ handleError(mGLState.getDrawFramebuffer()->clearBufferiv(mImplementation.get(), buffer,
+ drawbuffer, values));
+}
+
+void Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+{
+ Framebuffer *framebufferObject = mGLState.getDrawFramebuffer();
+ ASSERT(framebufferObject);
+
+ // If a buffer is not present, the clear has no effect
+ if (framebufferObject->getDepthbuffer() == nullptr &&
+ framebufferObject->getStencilbuffer() == nullptr)
+ {
+ return;
+ }
+
+ syncStateForClear();
+ handleError(framebufferObject->clearBufferfi(mImplementation.get(), buffer, drawbuffer, depth,
+ stencil));
+}
+
+void Context::readPixels(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels)
+{
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ syncStateForReadPixels();
+
+ Framebuffer *framebufferObject = mGLState.getReadFramebuffer();
+ ASSERT(framebufferObject);
+
+ Rectangle area(x, y, width, height);
+ handleError(framebufferObject->readPixels(mImplementation.get(), area, format, type, pixels));
+}
+
+void Context::copyTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ // Only sync the read FBO
+ mGLState.syncDirtyObject(GL_READ_FRAMEBUFFER);
+
+ Rectangle sourceArea(x, y, width, height);
+
+ const Framebuffer *framebuffer = mGLState.getReadFramebuffer();
+ Texture *texture =
+ getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ handleError(texture->copyImage(target, level, sourceArea, internalformat, framebuffer));
+}
+
+void Context::copyTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ // Only sync the read FBO
+ mGLState.syncDirtyObject(GL_READ_FRAMEBUFFER);
+
+ Offset destOffset(xoffset, yoffset, 0);
+ Rectangle sourceArea(x, y, width, height);
+
+ const Framebuffer *framebuffer = mGLState.getReadFramebuffer();
+ Texture *texture =
+ getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ handleError(texture->copySubImage(target, level, destOffset, sourceArea, framebuffer));
+}
+
+void Context::copyTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ // Only sync the read FBO
+ mGLState.syncDirtyObject(GL_READ_FRAMEBUFFER);
+
+ Offset destOffset(xoffset, yoffset, zoffset);
+ Rectangle sourceArea(x, y, width, height);
+
+ const Framebuffer *framebuffer = mGLState.getReadFramebuffer();
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->copySubImage(target, level, destOffset, sourceArea, framebuffer));
+}
+
+void Context::framebufferTexture2D(GLenum target,
+ GLenum attachment,
+ GLenum textarget,
+ GLuint texture,
+ GLint level)
+{
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (texture != 0)
+ {
+ Texture *textureObj = getTexture(texture);
+
+ ImageIndex index = ImageIndex::MakeInvalid();
+
+ if (textarget == GL_TEXTURE_2D)
+ {
+ index = ImageIndex::Make2D(level);
+ }
+ else
+ {
+ ASSERT(IsCubeMapTextureTarget(textarget));
+ index = ImageIndex::MakeCube(textarget, level);
+ }
+
+ framebuffer->setAttachment(GL_TEXTURE, attachment, index, textureObj);
+ }
+ else
+ {
+ framebuffer->resetAttachment(attachment);
+ }
+
+ mGLState.setObjectDirty(target);
+}
+
+void Context::framebufferRenderbuffer(GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer)
+{
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (renderbuffer != 0)
+ {
+ Renderbuffer *renderbufferObject = getRenderbuffer(renderbuffer);
+ framebuffer->setAttachment(GL_RENDERBUFFER, attachment, gl::ImageIndex::MakeInvalid(),
+ renderbufferObject);
+ }
+ else
+ {
+ framebuffer->resetAttachment(attachment);
+ }
+
+ mGLState.setObjectDirty(target);
+}
+
+void Context::framebufferTextureLayer(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLint layer)
+{
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (texture != 0)
+ {
+ Texture *textureObject = getTexture(texture);
+
+ ImageIndex index = ImageIndex::MakeInvalid();
+
+ if (textureObject->getTarget() == GL_TEXTURE_3D)
+ {
+ index = ImageIndex::Make3D(level, layer);
+ }
+ else
+ {
+ ASSERT(textureObject->getTarget() == GL_TEXTURE_2D_ARRAY);
+ index = ImageIndex::Make2DArray(level, layer);
+ }
+
+ framebuffer->setAttachment(GL_TEXTURE, attachment, index, textureObject);
+ }
+ else
+ {
+ framebuffer->resetAttachment(attachment);
+ }
+
+ mGLState.setObjectDirty(target);
+}
+
+void Context::drawBuffers(GLsizei n, const GLenum *bufs)
+{
+ Framebuffer *framebuffer = mGLState.getDrawFramebuffer();
+ ASSERT(framebuffer);
+ framebuffer->setDrawBuffers(n, bufs);
+ mGLState.setObjectDirty(GL_DRAW_FRAMEBUFFER);
+}
+
+void Context::readBuffer(GLenum mode)
+{
+ Framebuffer *readFBO = mGLState.getReadFramebuffer();
+ readFBO->setReadBuffer(mode);
+ mGLState.setObjectDirty(GL_READ_FRAMEBUFFER);
+}
+
+void Context::discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)
+{
+ // Only sync the FBO
+ mGLState.syncDirtyObject(target);
+
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ // The specification isn't clear what should be done when the framebuffer isn't complete.
+ // We leave it up to the framebuffer implementation to decide what to do.
+ handleError(framebuffer->discard(numAttachments, attachments));
+}
+
+void Context::invalidateFramebuffer(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ // Only sync the FBO
+ mGLState.syncDirtyObject(target);
+
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (framebuffer->checkStatus(mState) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ return;
+ }
+
+ handleError(framebuffer->invalidate(numAttachments, attachments));
+}
+
+void Context::invalidateSubFramebuffer(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ // Only sync the FBO
+ mGLState.syncDirtyObject(target);
+
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (framebuffer->checkStatus(mState) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ return;
+ }
+
+ Rectangle area(x, y, width, height);
+ handleError(framebuffer->invalidateSub(numAttachments, attachments, area));
+}
+
+void Context::texImage2D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels)
+{
+ syncStateForTexImage();
+
+ Extents size(width, height, 1);
+ Texture *texture =
+ getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ handleError(texture->setImage(mGLState.getUnpackState(), target, level, internalformat, size,
+ format, type, reinterpret_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texImage3D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels)
+{
+ syncStateForTexImage();
+
+ Extents size(width, height, depth);
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->setImage(mGLState.getUnpackState(), target, level, internalformat, size,
+ format, type, reinterpret_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels)
+{
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ syncStateForTexImage();
+
+ Box area(xoffset, yoffset, 0, width, height, 1);
+ Texture *texture =
+ getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ handleError(texture->setSubImage(mGLState.getUnpackState(), target, level, area, format, type,
+ reinterpret_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels)
+{
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0 || depth == 0)
+ {
+ return;
+ }
+
+ syncStateForTexImage();
+
+ Box area(xoffset, yoffset, zoffset, width, height, depth);
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->setSubImage(mGLState.getUnpackState(), target, level, area, format, type,
+ reinterpret_cast<const uint8_t *>(pixels)));
+}
+
+void Context::compressedTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const GLvoid *data)
+{
+ syncStateForTexImage();
+
+ Extents size(width, height, 1);
+ Texture *texture =
+ getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ handleError(texture->setCompressedImage(mGLState.getUnpackState(), target, level,
+ internalformat, size, imageSize,
+ reinterpret_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexImage3D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const GLvoid *data)
+{
+ syncStateForTexImage();
+
+ Extents size(width, height, depth);
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->setCompressedImage(mGLState.getUnpackState(), target, level,
+ internalformat, size, imageSize,
+ reinterpret_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const GLvoid *data)
+{
+ syncStateForTexImage();
+
+ Box area(xoffset, yoffset, 0, width, height, 1);
+ Texture *texture =
+ getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ handleError(texture->setCompressedSubImage(mGLState.getUnpackState(), target, level, area,
+ format, imageSize,
+ reinterpret_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const GLvoid *data)
+{
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ syncStateForTexImage();
+
+ Box area(xoffset, yoffset, zoffset, width, height, depth);
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->setCompressedSubImage(mGLState.getUnpackState(), target, level, area,
+ format, imageSize,
+ reinterpret_cast<const uint8_t *>(data)));
+}
+
+void Context::generateMipmap(GLenum target)
+{
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->generateMipmap());
+}
+
+GLboolean Context::enableExtension(const char *name)
+{
+ const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
+ ASSERT(extensionInfos.find(name) != extensionInfos.end());
+ const auto &extension = extensionInfos.at(name);
+ ASSERT(extension.Enableable);
+
+ if (mExtensions.*(extension.ExtensionsMember))
+ {
+ // Extension already enabled
+ return GL_TRUE;
+ }
+
+ const auto &nativeExtensions = mImplementation->getNativeExtensions();
+ if (!(nativeExtensions.*(extension.ExtensionsMember)))
+ {
+ // Underlying implementation does not support this valid extension
+ return GL_FALSE;
+ }
+
+ mExtensions.*(extension.ExtensionsMember) = true;
+ updateCaps();
+ initExtensionStrings();
+ return GL_TRUE;
+}
+
+void Context::copyTextureCHROMIUM(GLuint sourceId,
+ GLuint destId,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ syncStateForTexImage();
+
+ gl::Texture *sourceTexture = getTexture(sourceId);
+ gl::Texture *destTexture = getTexture(destId);
+ handleError(destTexture->copyTexture(internalFormat, destType, unpackFlipY == GL_TRUE,
+ unpackPremultiplyAlpha == GL_TRUE,
+ unpackUnmultiplyAlpha == GL_TRUE, sourceTexture));
+}
+
+void Context::copySubTextureCHROMIUM(GLuint sourceId,
+ GLuint destId,
+ 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;
+ }
+
+ syncStateForTexImage();
+
+ gl::Texture *sourceTexture = getTexture(sourceId);
+ gl::Texture *destTexture = getTexture(destId);
+ Offset offset(xoffset, yoffset, 0);
+ Rectangle area(x, y, width, height);
+ handleError(destTexture->copySubTexture(offset, area, unpackFlipY == GL_TRUE,
+ unpackPremultiplyAlpha == GL_TRUE,
+ unpackUnmultiplyAlpha == GL_TRUE, sourceTexture));
+}
+
+void Context::compressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId)
+{
+ syncStateForTexImage();
+
+ gl::Texture *sourceTexture = getTexture(sourceId);
+ gl::Texture *destTexture = getTexture(destId);
+ handleError(destTexture->copyCompressedTexture(sourceTexture));
+}
+
+void Context::getBufferPointerv(GLenum target, GLenum pname, void **params)
+{
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ QueryBufferPointerv(buffer, pname, params);
+}
+
+GLvoid *Context::mapBuffer(GLenum target, GLenum access)
+{
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ Error error = buffer->map(access);
+ if (error.isError())
+ {
+ handleError(error);
+ return nullptr;
+ }
+
+ return buffer->getMapPointer();
+}
+
+GLboolean Context::unmapBuffer(GLenum target)
+{
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ GLboolean result;
+ Error error = buffer->unmap(&result);
+ if (error.isError())
+ {
+ handleError(error);
+ return GL_FALSE;
+ }
+
+ return result;
+}
+
+GLvoid *Context::mapBufferRange(GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ Error error = buffer->mapRange(offset, length, access);
+ if (error.isError())
+ {
+ handleError(error);
+ return nullptr;
+ }
+
+ return buffer->getMapPointer();
+}
+
+void Context::flushMappedBufferRange(GLenum /*target*/, GLintptr /*offset*/, GLsizeiptr /*length*/)
+{
+ // We do not currently support a non-trivial implementation of FlushMappedBufferRange
+}
+
+void Context::syncStateForReadPixels()
+{
+ syncRendererState(mReadPixelsDirtyBits, mReadPixelsDirtyObjects);
+}
+
+void Context::syncStateForTexImage()
+{
+ syncRendererState(mTexImageDirtyBits, mTexImageDirtyObjects);
+}
+
+void Context::syncStateForClear()
+{
+ syncRendererState(mClearDirtyBits, mClearDirtyObjects);
+}
+
+void Context::syncStateForBlit()
+{
+ syncRendererState(mBlitDirtyBits, mBlitDirtyObjects);
+}
+
+void Context::activeTexture(GLenum texture)
+{
+ mGLState.setActiveSampler(texture - GL_TEXTURE0);
+}
+
+void Context::blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ mGLState.setBlendColor(clamp01(red), clamp01(green), clamp01(blue), clamp01(alpha));
+}
+
+void Context::blendEquation(GLenum mode)
+{
+ mGLState.setBlendEquation(mode, mode);
+}
+
+void Context::blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+ mGLState.setBlendEquation(modeRGB, modeAlpha);
+}
+
+void Context::blendFunc(GLenum sfactor, GLenum dfactor)
+{
+ mGLState.setBlendFactors(sfactor, dfactor, sfactor, dfactor);
+}
+
+void Context::blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+ mGLState.setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void Context::clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ mGLState.setColorClearValue(red, green, blue, alpha);
+}
+
+void Context::clearDepthf(GLclampf depth)
+{
+ mGLState.setDepthClearValue(depth);
+}
+
+void Context::clearStencil(GLint s)
+{
+ mGLState.setStencilClearValue(s);
+}
+
+void Context::colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+ mGLState.setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
+}
+
+void Context::cullFace(GLenum mode)
+{
+ mGLState.setCullMode(mode);
+}
+
+void Context::depthFunc(GLenum func)
+{
+ mGLState.setDepthFunc(func);
+}
+
+void Context::depthMask(GLboolean flag)
+{
+ mGLState.setDepthMask(flag != GL_FALSE);
+}
+
+void Context::depthRangef(GLclampf zNear, GLclampf zFar)
+{
+ mGLState.setDepthRange(zNear, zFar);
+}
+
+void Context::disable(GLenum cap)
+{
+ mGLState.setEnableFeature(cap, false);
+}
+
+void Context::disableVertexAttribArray(GLuint index)
+{
+ mGLState.setEnableVertexAttribArray(index, false);
+}
+
+void Context::enable(GLenum cap)
+{
+ mGLState.setEnableFeature(cap, true);
+}
+
+void Context::enableVertexAttribArray(GLuint index)
+{
+ mGLState.setEnableVertexAttribArray(index, true);
+}
+
+void Context::frontFace(GLenum mode)
+{
+ mGLState.setFrontFace(mode);
+}
+
+void Context::hint(GLenum target, GLenum mode)
+{
+ switch (target)
+ {
+ case GL_GENERATE_MIPMAP_HINT:
+ mGLState.setGenerateMipmapHint(mode);
+ break;
+
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+ mGLState.setFragmentShaderDerivativeHint(mode);
+ break;
+
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+void Context::lineWidth(GLfloat width)
+{
+ mGLState.setLineWidth(width);
+}
+
+void Context::pixelStorei(GLenum pname, GLint param)
+{
+ switch (pname)
+ {
+ case GL_UNPACK_ALIGNMENT:
+ mGLState.setUnpackAlignment(param);
+ break;
+
+ case GL_PACK_ALIGNMENT:
+ mGLState.setPackAlignment(param);
+ break;
+
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ mGLState.setPackReverseRowOrder(param != 0);
+ break;
+
+ case GL_UNPACK_ROW_LENGTH:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().unpackSubimage);
+ mGLState.setUnpackRowLength(param);
+ break;
+
+ case GL_UNPACK_IMAGE_HEIGHT:
+ ASSERT(getClientMajorVersion() >= 3);
+ mGLState.setUnpackImageHeight(param);
+ break;
+
+ case GL_UNPACK_SKIP_IMAGES:
+ ASSERT(getClientMajorVersion() >= 3);
+ mGLState.setUnpackSkipImages(param);
+ break;
+
+ case GL_UNPACK_SKIP_ROWS:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().unpackSubimage);
+ mGLState.setUnpackSkipRows(param);
+ break;
+
+ case GL_UNPACK_SKIP_PIXELS:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().unpackSubimage);
+ mGLState.setUnpackSkipPixels(param);
+ break;
+
+ case GL_PACK_ROW_LENGTH:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().packSubimage);
+ mGLState.setPackRowLength(param);
+ break;
+
+ case GL_PACK_SKIP_ROWS:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().packSubimage);
+ mGLState.setPackSkipRows(param);
+ break;
+
+ case GL_PACK_SKIP_PIXELS:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().packSubimage);
+ mGLState.setPackSkipPixels(param);
+ break;
+
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+void Context::polygonOffset(GLfloat factor, GLfloat units)
+{
+ mGLState.setPolygonOffsetParams(factor, units);
+}
+
+void Context::sampleCoverage(GLclampf value, GLboolean invert)
+{
+ mGLState.setSampleCoverageParams(clamp01(value), invert == GL_TRUE);
+}
+
+void Context::scissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ mGLState.setScissorParams(x, y, width, height);
+}
+
+void Context::stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ mGLState.setStencilParams(func, ref, mask);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ mGLState.setStencilBackParams(func, ref, mask);
+ }
+}
+
+void Context::stencilMaskSeparate(GLenum face, GLuint mask)
+{
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ mGLState.setStencilWritemask(mask);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ mGLState.setStencilBackWritemask(mask);
+ }
+}
+
+void Context::stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ mGLState.setStencilOperations(fail, zfail, zpass);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ mGLState.setStencilBackOperations(fail, zfail, zpass);
+ }
+}
+
+void Context::vertexAttrib1f(GLuint index, GLfloat x)
+{
+ GLfloat vals[4] = {x, 0, 0, 1};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib1fv(GLuint index, const GLfloat *values)
+{
+ GLfloat vals[4] = {values[0], 0, 0, 1};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+{
+ GLfloat vals[4] = {x, y, 0, 1};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib2fv(GLuint index, const GLfloat *values)
+{
+ GLfloat vals[4] = {values[0], values[1], 0, 1};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat vals[4] = {x, y, z, 1};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib3fv(GLuint index, const GLfloat *values)
+{
+ GLfloat vals[4] = {values[0], values[1], values[2], 1};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GLfloat vals[4] = {x, y, z, w};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib4fv(GLuint index, const GLfloat *values)
+{
+ mGLState.setVertexAttribf(index, values);
+}
+
+void Context::vertexAttribPointer(GLuint index,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const GLvoid *ptr)
+{
+ mGLState.setVertexAttribState(index, mGLState.getTargetBuffer(GL_ARRAY_BUFFER), size, type,
+ normalized == GL_TRUE, false, stride, ptr);
+}
+
+void Context::viewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ mGLState.setViewportParams(x, y, width, height);
+}
+
+void Context::vertexAttribIPointer(GLuint index,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const GLvoid *pointer)
+{
+ mGLState.setVertexAttribState(index, mGLState.getTargetBuffer(GL_ARRAY_BUFFER), size, type,
+ false, true, stride, pointer);
+}
+
+void Context::vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
+{
+ GLint vals[4] = {x, y, z, w};
+ mGLState.setVertexAttribi(index, vals);
+}
+
+void Context::vertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
+{
+ GLuint vals[4] = {x, y, z, w};
+ mGLState.setVertexAttribu(index, vals);
+}
+
+void Context::vertexAttribI4iv(GLuint index, const GLint *v)
+{
+ mGLState.setVertexAttribi(index, v);
+}
+
+void Context::vertexAttribI4uiv(GLuint index, const GLuint *v)
+{
+ mGLState.setVertexAttribu(index, v);
+}
+
+void Context::debugMessageControl(GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled)
+{
+ std::vector<GLuint> idVector(ids, ids + count);
+ mGLState.getDebug().setMessageControl(source, type, severity, std::move(idVector),
+ (enabled != GL_FALSE));
+}
+
+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));
+ mGLState.getDebug().insertMessage(source, type, id, severity, std::move(msg));
+}
+
+void Context::debugMessageCallback(GLDEBUGPROCKHR callback, const void *userParam)
+{
+ mGLState.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>(mGLState.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));
+ mGLState.getDebug().pushGroup(source, id, std::move(msg));
+}
+
+void Context::popDebugGroup()
+{
+ mGLState.getDebug().popGroup();
+}
+
+void Context::bufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
+{
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ ASSERT(buffer);
+ handleError(buffer->bufferData(target, data, size, usage));
+}
+
+void Context::bufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
+{
+ if (data == nullptr)
+ {
+ return;
+ }
+
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ ASSERT(buffer);
+ handleError(buffer->bufferSubData(target, data, size, offset));
+}
+
+void Context::attachShader(GLuint program, GLuint shader)
+{
+ auto programObject = mResourceManager->getProgram(program);
+ auto shaderObject = mResourceManager->getShader(shader);
+ ASSERT(programObject && shaderObject);
+ programObject->attachShader(shaderObject);
+}
+
+const Workarounds &Context::getWorkarounds() const
+{
+ return mWorkarounds;
+}
+
+void Context::copyBufferSubData(GLenum readTarget,
+ GLenum 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 = mGLState.getTargetBuffer(readTarget);
+ Buffer *writeBuffer = mGLState.getTargetBuffer(writeTarget);
+
+ handleError(writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size));
+}
+
+void Context::bindAttribLocation(GLuint program, GLuint index, const GLchar *name)
+{
+ Program *programObject = getProgram(program);
+ // TODO(jmadill): Re-use this from the validation if possible.
+ ASSERT(programObject);
+ programObject->bindAttributeLocation(index, name);
+}
+
+void Context::bindBuffer(GLenum target, GLuint buffer)
+{
+ switch (target)
+ {
+ case GL_ARRAY_BUFFER:
+ bindArrayBuffer(buffer);
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ bindElementArrayBuffer(buffer);
+ break;
+ case GL_COPY_READ_BUFFER:
+ bindCopyReadBuffer(buffer);
+ break;
+ case GL_COPY_WRITE_BUFFER:
+ bindCopyWriteBuffer(buffer);
+ break;
+ case GL_PIXEL_PACK_BUFFER:
+ bindPixelPackBuffer(buffer);
+ break;
+ case GL_PIXEL_UNPACK_BUFFER:
+ bindPixelUnpackBuffer(buffer);
+ break;
+ case GL_UNIFORM_BUFFER:
+ bindGenericUniformBuffer(buffer);
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ bindGenericTransformFeedbackBuffer(buffer);
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void Context::bindFramebuffer(GLenum target, GLuint 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, GLuint renderbuffer)
+{
+ ASSERT(target == GL_RENDERBUFFER);
+ Renderbuffer *object =
+ mResourceManager->checkRenderbufferAllocation(mImplementation.get(), renderbuffer);
+ mGLState.setRenderbufferBinding(object);
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/Context.h b/gfx/angle/src/libANGLE/Context.h
new file mode 100755
index 000000000..26c5d98e2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Context.h
@@ -0,0 +1,706 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 <set>
+#include <string>
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/HandleAllocator.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/Workarounds.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+class ContextImpl;
+class EGLImplFactory;
+}
+
+namespace egl
+{
+class AttributeMap;
+class Surface;
+struct Config;
+}
+
+namespace gl
+{
+class Compiler;
+class Shader;
+class Program;
+class Texture;
+class Framebuffer;
+class Renderbuffer;
+class FenceNV;
+class FenceSync;
+class Query;
+class ResourceManager;
+class Buffer;
+struct VertexAttribute;
+class VertexArray;
+class Sampler;
+class TransformFeedback;
+
+class Context final : public ValidationContext
+{
+ public:
+ Context(rx::EGLImplFactory *implFactory,
+ const egl::Config *config,
+ const Context *shareContext,
+ const egl::AttributeMap &attribs);
+
+ virtual ~Context();
+
+ void makeCurrent(egl::Surface *surface);
+ void releaseSurface();
+
+ // These create and destroy methods are merely pass-throughs to
+ // ResourceManager, which owns these object types
+ GLuint createBuffer();
+ GLuint createShader(GLenum type);
+ GLuint createProgram();
+ GLuint createTexture();
+ GLuint createRenderbuffer();
+ GLuint createSampler();
+ GLuint createTransformFeedback();
+ GLsync createFenceSync();
+ GLuint createPaths(GLsizei range);
+
+ void deleteBuffer(GLuint buffer);
+ void deleteShader(GLuint shader);
+ void deleteProgram(GLuint program);
+ void deleteTexture(GLuint texture);
+ void deleteRenderbuffer(GLuint renderbuffer);
+ void deleteSampler(GLuint sampler);
+ void deleteTransformFeedback(GLuint transformFeedback);
+ void deleteFenceSync(GLsync fenceSync);
+ void deletePaths(GLuint first, GLsizei range);
+
+ // CHROMIUM_path_rendering
+ bool hasPathData(GLuint path) const;
+ bool hasPath(GLuint path) const;
+ void setPathCommands(GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords);
+ void setPathParameterf(GLuint path, GLenum pname, GLfloat value);
+ void getPathParameterfv(GLuint path, GLenum pname, GLfloat *value) const;
+ void setPathStencilFunc(GLenum func, GLint ref, GLuint mask);
+
+ // Framebuffers are owned by the Context, so these methods do not pass through
+ GLuint createFramebuffer();
+ void deleteFramebuffer(GLuint framebuffer);
+
+ // NV Fences are owned by the Context.
+ GLuint createFenceNV();
+ void deleteFenceNV(GLuint fence);
+
+ // Queries are owned by the Context;
+ GLuint createQuery();
+ void deleteQuery(GLuint query);
+
+ // Vertex arrays are owned by the Context
+ GLuint createVertexArray();
+ void deleteVertexArray(GLuint vertexArray);
+
+ void bindArrayBuffer(GLuint bufferHandle);
+ void bindElementArrayBuffer(GLuint bufferHandle);
+ void bindTexture(GLenum target, GLuint handle);
+ void bindReadFramebuffer(GLuint framebufferHandle);
+ void bindDrawFramebuffer(GLuint framebufferHandle);
+ void bindVertexArray(GLuint vertexArrayHandle);
+ void bindSampler(GLuint textureUnit, GLuint samplerHandle);
+ void bindGenericUniformBuffer(GLuint bufferHandle);
+ void bindIndexedUniformBuffer(GLuint bufferHandle,
+ GLuint index,
+ GLintptr offset,
+ GLsizeiptr size);
+ void bindGenericTransformFeedbackBuffer(GLuint bufferHandle);
+ void bindIndexedTransformFeedbackBuffer(GLuint bufferHandle,
+ GLuint index,
+ GLintptr offset,
+ GLsizeiptr size);
+ void bindCopyReadBuffer(GLuint bufferHandle);
+ void bindCopyWriteBuffer(GLuint bufferHandle);
+ void bindPixelPackBuffer(GLuint bufferHandle);
+ void bindPixelUnpackBuffer(GLuint bufferHandle);
+ void useProgram(GLuint program);
+ void bindTransformFeedback(GLuint transformFeedbackHandle);
+
+ Error beginQuery(GLenum target, GLuint query);
+ Error endQuery(GLenum target);
+ Error queryCounter(GLuint id, GLenum target);
+ void getQueryiv(GLenum target, GLenum pname, GLint *params);
+ void getQueryObjectiv(GLuint id, GLenum pname, GLint *params);
+ void getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params);
+ void getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params);
+ void getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params);
+
+ void setVertexAttribDivisor(GLuint index, GLuint divisor);
+
+ void samplerParameteri(GLuint sampler, GLenum pname, GLint param);
+ void samplerParameteriv(GLuint sampler, GLenum pname, const GLint *param);
+ void samplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
+ void samplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param);
+
+ void getSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params);
+ void getSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params);
+
+ void programParameteri(GLuint program, GLenum pname, GLint value);
+
+ Buffer *getBuffer(GLuint handle) const;
+ FenceNV *getFenceNV(GLuint handle);
+ FenceSync *getFenceSync(GLsync handle) const;
+ Texture *getTexture(GLuint handle) const;
+ Framebuffer *getFramebuffer(GLuint handle) const;
+ Renderbuffer *getRenderbuffer(GLuint handle) const;
+ VertexArray *getVertexArray(GLuint handle) const;
+ Sampler *getSampler(GLuint handle) const;
+ Query *getQuery(GLuint handle, bool create, GLenum type);
+ Query *getQuery(GLuint handle) const;
+ TransformFeedback *getTransformFeedback(GLuint handle) const;
+ void objectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+ void objectPtrLabel(const void *ptr, GLsizei length, const GLchar *label);
+ void getObjectLabel(GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label) const;
+ void getObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label) const;
+
+ Texture *getTargetTexture(GLenum target) const;
+ Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
+
+ Compiler *getCompiler() const;
+
+ bool isSampler(GLuint samplerName) const;
+
+ bool isVertexArrayGenerated(GLuint vertexArray);
+ bool isTransformFeedbackGenerated(GLuint vertexArray);
+
+ void getBooleanv(GLenum pname, GLboolean *params);
+ void getFloatv(GLenum pname, GLfloat *params);
+ void getIntegerv(GLenum pname, GLint *params);
+ void getInteger64v(GLenum pname, GLint64 *params);
+ void getPointerv(GLenum pname, void **params) const;
+ void getBooleani_v(GLenum target, GLuint index, GLboolean *data);
+ void getIntegeri_v(GLenum target, GLuint index, GLint *data);
+ void getInteger64i_v(GLenum target, GLuint index, GLint64 *data);
+
+ void activeTexture(GLenum texture);
+ void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ void blendEquation(GLenum mode);
+ void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
+ void blendFunc(GLenum sfactor, GLenum dfactor);
+ void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+ void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ void clearDepthf(GLclampf depth);
+ void clearStencil(GLint s);
+ void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+ void cullFace(GLenum mode);
+ void depthFunc(GLenum func);
+ void depthMask(GLboolean flag);
+ void depthRangef(GLclampf zNear, GLclampf zFar);
+ void disable(GLenum cap);
+ void disableVertexAttribArray(GLuint index);
+ void enable(GLenum cap);
+ void enableVertexAttribArray(GLuint index);
+ void frontFace(GLenum mode);
+ void hint(GLenum target, GLenum mode);
+ void lineWidth(GLfloat width);
+ void pixelStorei(GLenum pname, GLint param);
+ void polygonOffset(GLfloat factor, GLfloat units);
+ void sampleCoverage(GLclampf value, GLboolean invert);
+ void scissor(GLint x, GLint y, GLsizei width, GLsizei height);
+ void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
+ void stencilMaskSeparate(GLenum face, GLuint mask);
+ void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+ void vertexAttrib1f(GLuint index, GLfloat x);
+ void vertexAttrib1fv(GLuint index, const GLfloat *values);
+ void vertexAttrib2f(GLuint index, GLfloat x, GLfloat y);
+ void vertexAttrib2fv(GLuint index, const GLfloat *values);
+ void vertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+ void vertexAttrib3fv(GLuint index, const GLfloat *values);
+ void vertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void vertexAttrib4fv(GLuint index, const GLfloat *values);
+ void vertexAttribPointer(GLuint index,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const GLvoid *ptr);
+ void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
+
+ void vertexAttribIPointer(GLuint index,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const GLvoid *pointer);
+ void vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
+ void vertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+ void vertexAttribI4iv(GLuint index, const GLint *v);
+ void vertexAttribI4uiv(GLuint index, const GLuint *v);
+
+ 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 debugMessageCallback(GLDEBUGPROCKHR callback, const void *userParam);
+ GLuint getDebugMessageLog(GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog);
+ void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message);
+ void popDebugGroup();
+
+ void clear(GLbitfield mask);
+ void clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values);
+ void clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values);
+ void clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values);
+ void clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+
+ Error drawArrays(GLenum mode, GLint first, GLsizei count);
+ Error drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
+
+ Error drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const IndexRange &indexRange);
+ Error drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const IndexRange &indexRange);
+ Error drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const IndexRange &indexRange);
+
+ void blitFramebuffer(GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+
+ void readPixels(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels);
+
+ void copyTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border);
+
+ void copyTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+
+ void copyTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+
+ void framebufferTexture2D(GLenum target,
+ GLenum attachment,
+ GLenum textarget,
+ GLuint texture,
+ GLint level);
+
+ void framebufferRenderbuffer(GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer);
+
+ void framebufferTextureLayer(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLint layer);
+
+ void drawBuffers(GLsizei n, const GLenum *bufs);
+ void readBuffer(GLenum mode);
+
+ void discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments);
+ 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);
+
+ void texImage2D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels);
+ void texImage3D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels);
+ void texSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels);
+ void texSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels);
+ void compressedTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const GLvoid *data);
+ void compressedTexImage3D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const GLvoid *data);
+ void compressedTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const GLvoid *data);
+ void compressedTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const GLvoid *data);
+ void copyTextureCHROMIUM(GLuint sourceId,
+ GLuint destId,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+ void copySubTextureCHROMIUM(GLuint sourceId,
+ GLuint destId,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+ void compressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
+
+ void generateMipmap(GLenum target);
+
+ GLboolean enableExtension(const char *name);
+
+ Error flush();
+ Error finish();
+
+ void getBufferPointerv(GLenum target, GLenum pname, void **params);
+ GLvoid *mapBuffer(GLenum target, GLenum access);
+ GLboolean unmapBuffer(GLenum target);
+ GLvoid *mapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+ void flushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
+
+ void beginTransformFeedback(GLenum primitiveMode);
+
+ bool hasActiveTransformFeedback(GLuint program) const;
+
+ void insertEventMarker(GLsizei length, const char *marker);
+ void pushGroupMarker(GLsizei length, const char *marker);
+ void popGroupMarker();
+
+ void bindUniformLocation(GLuint program, GLint location, const GLchar *name);
+
+ // CHROMIUM_framebuffer_mixed_samples
+ void setCoverageModulation(GLenum components);
+
+ // CHROMIUM_path_rendering
+ void loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix);
+ void loadPathRenderingIdentityMatrix(GLenum matrixMode);
+ void stencilFillPath(GLuint path, GLenum fillMode, GLuint mask);
+ void stencilStrokePath(GLuint path, GLint reference, GLuint mask);
+ void coverFillPath(GLuint path, GLenum coverMode);
+ void coverStrokePath(GLuint path, GLenum coverMode);
+ void stencilThenCoverFillPath(GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+ void stencilThenCoverStrokePath(GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+ void coverFillPathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void coverStrokePathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void stencilFillPathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBAse,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void stencilStrokePathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void stencilThenCoverFillPathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void stencilThenCoverStrokePathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void bindFragmentInputLocation(GLuint program, GLint location, const GLchar *name);
+ void programPathFragmentInputGen(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs);
+
+ void bufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
+ void bufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+ void attachShader(GLuint program, GLuint shader);
+ void bindAttribLocation(GLuint program, GLuint index, const GLchar *name);
+ void bindBuffer(GLenum target, GLuint buffer);
+ void bindFramebuffer(GLenum target, GLuint framebuffer);
+ void bindRenderbuffer(GLenum target, GLuint renderbuffer);
+
+ void copyBufferSubData(GLenum readTarget,
+ GLenum writeTarget,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size);
+
+ void handleError(const Error &error) override;
+
+ GLenum getError();
+ void markContextLost();
+ bool isContextLost();
+ GLenum getResetStatus();
+ bool isResetNotificationEnabled();
+
+ const egl::Config *getConfig() const;
+ EGLenum getClientType() const;
+ EGLenum getRenderBuffer() const;
+
+ const char *getRendererString() const;
+
+ const char *getExtensionString() const;
+ const char *getExtensionString(size_t idx) const;
+ size_t getExtensionStringCount() const;
+
+ rx::ContextImpl *getImplementation() const { return mImplementation.get(); }
+ const Workarounds &getWorkarounds() const;
+
+ private:
+ void syncRendererState();
+ void syncRendererState(const State::DirtyBits &bitMask, const State::DirtyObjects &objectMask);
+ void syncStateForReadPixels();
+ void syncStateForTexImage();
+ void syncStateForClear();
+ void syncStateForBlit();
+ VertexArray *checkVertexArrayAllocation(GLuint vertexArrayHandle);
+ TransformFeedback *checkTransformFeedbackAllocation(GLuint transformFeedback);
+ Framebuffer *checkFramebufferAllocation(GLuint framebufferHandle);
+
+ void detachBuffer(GLuint buffer);
+ void detachTexture(GLuint texture);
+ void detachFramebuffer(GLuint framebuffer);
+ void detachRenderbuffer(GLuint renderbuffer);
+ void detachVertexArray(GLuint vertexArray);
+ void detachTransformFeedback(GLuint transformFeedback);
+ void detachSampler(GLuint sampler);
+
+ void initRendererString();
+ void initExtensionStrings();
+
+ void initCaps(bool webGLContext);
+ void updateCaps();
+ void initWorkarounds();
+
+ LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const;
+ LabeledObject *getLabeledObjectFromPtr(const void *ptr) const;
+
+ std::unique_ptr<rx::ContextImpl> mImplementation;
+
+ // Caps to use for validation
+ Caps mCaps;
+ TextureCapsMap mTextureCaps;
+ Extensions mExtensions;
+ Limitations mLimitations;
+
+ // Shader compiler
+ Compiler *mCompiler;
+
+ State mGLState;
+
+ const egl::Config *mConfig;
+ EGLenum mClientType;
+
+ TextureMap mZeroTextures;
+
+ ResourceMap<Framebuffer> mFramebufferMap;
+ HandleAllocator mFramebufferHandleAllocator;
+
+ ResourceMap<FenceNV> mFenceNVMap;
+ HandleAllocator mFenceNVHandleAllocator;
+
+ ResourceMap<Query> mQueryMap;
+ HandleAllocator mQueryHandleAllocator;
+
+ ResourceMap<VertexArray> mVertexArrayMap;
+ HandleAllocator mVertexArrayHandleAllocator;
+
+ ResourceMap<TransformFeedback> mTransformFeedbackMap;
+ HandleAllocator mTransformFeedbackAllocator;
+
+ const char *mRendererString;
+ const char *mExtensionString;
+ std::vector<const char *> mExtensionStrings;
+
+ // Recorded errors
+ typedef std::set<GLenum> ErrorSet;
+ ErrorSet mErrors;
+
+ // Current/lost context flags
+ bool mHasBeenCurrent;
+ bool mContextLost;
+ GLenum mResetStatus;
+ bool mContextLostForced;
+ GLenum mResetStrategy;
+ bool mRobustAccess;
+ egl::Surface *mCurrentSurface;
+
+ ResourceManager *mResourceManager;
+
+ State::DirtyBits mTexImageDirtyBits;
+ State::DirtyObjects mTexImageDirtyObjects;
+ State::DirtyBits mReadPixelsDirtyBits;
+ State::DirtyObjects mReadPixelsDirtyObjects;
+ State::DirtyBits mClearDirtyBits;
+ State::DirtyObjects mClearDirtyObjects;
+ State::DirtyBits mBlitDirtyBits;
+ State::DirtyObjects mBlitDirtyObjects;
+
+ Workarounds mWorkarounds;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_CONTEXT_H_
diff --git a/gfx/angle/src/libANGLE/ContextState.cpp b/gfx/angle/src/libANGLE/ContextState.cpp
new file mode 100755
index 000000000..dbf867909
--- /dev/null
+++ b/gfx/angle/src/libANGLE/ContextState.cpp
@@ -0,0 +1,618 @@
+//
+// Copyright (c) 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.
+//
+
+// Data.cpp: Container class for all GL relevant state, caps and objects
+
+#include "libANGLE/ContextState.h"
+
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/ResourceManager.h"
+
+namespace gl
+{
+
+ContextState::ContextState(uintptr_t contextIn,
+ const Version &clientVersion,
+ State *stateIn,
+ const Caps &capsIn,
+ const TextureCapsMap &textureCapsIn,
+ const Extensions &extensionsIn,
+ const ResourceManager *resourceManagerIn,
+ const Limitations &limitationsIn,
+ const ResourceMap<Framebuffer> &framebufferMap)
+ : mClientVersion(clientVersion),
+ mContext(contextIn),
+ mState(stateIn),
+ mCaps(capsIn),
+ mTextureCaps(textureCapsIn),
+ mExtensions(extensionsIn),
+ mResourceManager(resourceManagerIn),
+ mLimitations(limitationsIn),
+ mFramebufferMap(framebufferMap)
+{
+}
+
+ContextState::~ContextState()
+{
+}
+
+const TextureCaps &ContextState::getTextureCap(GLenum internalFormat) const
+{
+ return mTextureCaps.get(internalFormat);
+}
+
+ValidationContext::ValidationContext(const Version &clientVersion,
+ State *state,
+ const Caps &caps,
+ const TextureCapsMap &textureCaps,
+ const Extensions &extensions,
+ const ResourceManager *resourceManager,
+ const Limitations &limitations,
+ const ResourceMap<Framebuffer> &framebufferMap,
+ bool skipValidation)
+ : mState(reinterpret_cast<uintptr_t>(this),
+ clientVersion,
+ state,
+ caps,
+ textureCaps,
+ extensions,
+ resourceManager,
+ limitations,
+ framebufferMap),
+ mSkipValidation(skipValidation)
+{
+}
+
+bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
+{
+ if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ // 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>(getCaps().compressedTextureFormats.size());
+ return true;
+ }
+ case GL_PROGRAM_BINARY_FORMATS_OES:
+ {
+ *type = GL_INT;
+ *numParams = static_cast<unsigned int>(getCaps().programBinaryFormats.size());
+ return true;
+ }
+ case GL_SHADER_BINARY_FORMATS:
+ {
+ *type = GL_INT;
+ *numParams = static_cast<unsigned int>(getCaps().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_MAX_COLOR_ATTACHMENTS_EXT:
+ case GL_MAX_DRAW_BUFFERS_EXT:
+ case GL_NUM_SHADER_BINARY_FORMATS:
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+ case GL_ARRAY_BUFFER_BINDING:
+ // case GL_FRAMEBUFFER_BINDING: // equivalent to DRAW_FRAMEBUFFER_BINDING_ANGLE
+ case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE:
+ case GL_READ_FRAMEBUFFER_BINDING_ANGLE:
+ case GL_RENDERBUFFER_BINDING:
+ case GL_CURRENT_PROGRAM:
+ case GL_PACK_ALIGNMENT:
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ case GL_UNPACK_ALIGNMENT:
+ case GL_GENERATE_MIPMAP_HINT:
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+ 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:
+ case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_MAX_SAMPLES_ANGLE:
+ {
+ if (!getExtensions().framebufferMultisample)
+ {
+ 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_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 (!getExtensions().maxTextureAnisotropy)
+ {
+ return false;
+ }
+ *type = GL_FLOAT;
+ *numParams = 1;
+ return true;
+ case GL_TIMESTAMP_EXT:
+ if (!getExtensions().disjointTimerQuery)
+ {
+ return false;
+ }
+ *type = GL_INT_64_ANGLEX;
+ *numParams = 1;
+ return true;
+ case GL_GPU_DISJOINT_EXT:
+ if (!getExtensions().disjointTimerQuery)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_COVERAGE_MODULATION_CHROMIUM:
+ if (!getExtensions().framebufferMixedSamples)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_TEXTURE_BINDING_EXTERNAL_OES:
+ if (!getExtensions().eglStreamConsumerExternal && !getExtensions().eglImageExternal)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ if (getExtensions().debug)
+ {
+ 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 (getExtensions().multisampleCompatibility)
+ {
+ switch (pname)
+ {
+ case GL_MULTISAMPLE_EXT:
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (getExtensions().pathRendering)
+ {
+ switch (pname)
+ {
+ case GL_PATH_MODELVIEW_MATRIX_CHROMIUM:
+ case GL_PATH_PROJECTION_MATRIX_CHROMIUM:
+ *type = GL_FLOAT;
+ *numParams = 16;
+ return true;
+ }
+ }
+
+ if (getExtensions().bindGeneratesResource)
+ {
+ switch (pname)
+ {
+ case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (getExtensions().sRGBWriteControl)
+ {
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ // Check for ES3.0+ parameter names which are also exposed as ES2 extensions
+ switch (pname)
+ {
+ case GL_PACK_ROW_LENGTH:
+ case GL_PACK_SKIP_ROWS:
+ case GL_PACK_SKIP_PIXELS:
+ if ((getClientMajorVersion() < 3) && !getExtensions().packSubimage)
+ {
+ 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 ((getClientMajorVersion() < 3) && !getExtensions().unpackSubimage)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_VERTEX_ARRAY_BINDING:
+ if ((getClientMajorVersion() < 3) && !getExtensions().vertexArrayObject)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_PIXEL_PACK_BUFFER_BINDING:
+ case GL_PIXEL_UNPACK_BUFFER_BINDING:
+ if ((getClientMajorVersion() < 3) && !getExtensions().pixelBufferObject)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ if (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_3D_TEXTURE_SIZE:
+ 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:
+ {
+ *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:
+ {
+ *type = GL_FLOAT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (getClientVersion() < Version(3, 1))
+ {
+ return false;
+ }
+
+ switch (pname)
+ {
+ 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_OFFSET_ALIGNMENT:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
+ *type = GL_INT_64_ANGLEX;
+ *numParams = 1;
+ return true;
+ }
+
+ return false;
+}
+
+bool ValidationContext::getIndexedQueryParameterInfo(GLenum target,
+ GLenum *type,
+ unsigned int *numParams)
+{
+ 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 (getClientVersion() < Version(3, 1))
+ {
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
+ case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+Program *ValidationContext::getProgram(GLuint handle) const
+{
+ return mState.mResourceManager->getProgram(handle);
+}
+
+Shader *ValidationContext::getShader(GLuint handle) const
+{
+ return mState.mResourceManager->getShader(handle);
+}
+
+bool ValidationContext::isTextureGenerated(GLuint texture) const
+{
+ return mState.mResourceManager->isTextureGenerated(texture);
+}
+
+bool ValidationContext::isBufferGenerated(GLuint buffer) const
+{
+ return mState.mResourceManager->isBufferGenerated(buffer);
+}
+
+bool ValidationContext::isRenderbufferGenerated(GLuint renderbuffer) const
+{
+ return mState.mResourceManager->isRenderbufferGenerated(renderbuffer);
+}
+
+bool ValidationContext::isFramebufferGenerated(GLuint framebuffer) const
+{
+ ASSERT(mState.mFramebufferMap.find(0) != mState.mFramebufferMap.end());
+ return mState.mFramebufferMap.find(framebuffer) != mState.mFramebufferMap.end();
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/ContextState.h b/gfx/angle/src/libANGLE/ContextState.h
new file mode 100755
index 000000000..494c1a3da
--- /dev/null
+++ b/gfx/angle/src/libANGLE/ContextState.h
@@ -0,0 +1,112 @@
+//
+// Copyright (c) 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.
+//
+
+// ContextState: Container class for all GL context state, caps and objects.
+
+#ifndef LIBANGLE_CONTEXTSTATE_H_
+#define LIBANGLE_CONTEXTSTATE_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Version.h"
+
+namespace gl
+{
+class ValidationContext;
+class ContextState;
+
+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);
+
+class ContextState final : public angle::NonCopyable
+{
+ public:
+ ContextState(uintptr_t context,
+ const Version &clientVersion,
+ State *state,
+ const Caps &caps,
+ const TextureCapsMap &textureCaps,
+ const Extensions &extensions,
+ const ResourceManager *resourceManager,
+ const Limitations &limitations,
+ const ResourceMap<Framebuffer> &framebufferMap);
+ ~ContextState();
+
+ uintptr_t getContext() const { return mContext; }
+ GLint getClientMajorVersion() const { return mClientVersion.major; }
+ GLint getClientMinorVersion() const { return mClientVersion.minor; }
+ const Version &getClientVersion() const { return mClientVersion; }
+ const State &getState() const { return *mState; }
+ const Caps &getCaps() const { return mCaps; }
+ const TextureCapsMap &getTextureCaps() const { return mTextureCaps; }
+ const Extensions &getExtensions() const { return mExtensions; }
+ const ResourceManager &getResourceManager() const { return *mResourceManager; }
+ const Limitations &getLimitations() const { return mLimitations; }
+
+ const TextureCaps &getTextureCap(GLenum internalFormat) const;
+
+ private:
+ friend class Context;
+ friend class ValidationContext;
+
+ Version mClientVersion;
+ uintptr_t mContext;
+ State *mState;
+ const Caps &mCaps;
+ const TextureCapsMap &mTextureCaps;
+ const Extensions &mExtensions;
+ const ResourceManager *mResourceManager;
+ const Limitations &mLimitations;
+ const ResourceMap<Framebuffer> &mFramebufferMap;
+};
+
+class ValidationContext : angle::NonCopyable
+{
+ public:
+ ValidationContext(const Version &clientVersion,
+ State *state,
+ const Caps &caps,
+ const TextureCapsMap &textureCaps,
+ const Extensions &extensions,
+ const ResourceManager *resourceManager,
+ const Limitations &limitations,
+ const ResourceMap<Framebuffer> &framebufferMap,
+ bool skipValidation);
+ virtual ~ValidationContext() {}
+
+ virtual void handleError(const Error &error) = 0;
+
+ const ContextState &getContextState() const { return mState; }
+ GLint getClientMajorVersion() const { return mState.getClientMajorVersion(); }
+ GLint getClientMinorVersion() const { return mState.getClientMinorVersion(); }
+ const Version &getClientVersion() const { return mState.getClientVersion(); }
+ const State &getGLState() const { return mState.getState(); }
+ 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 skipValidation() const { return mSkipValidation; }
+
+ // Specific methods needed for validation.
+ bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
+ bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams);
+
+ Program *getProgram(GLuint handle) const;
+ Shader *getShader(GLuint handle) const;
+
+ bool isTextureGenerated(GLuint texture) const;
+ bool isBufferGenerated(GLuint buffer) const;
+ bool isRenderbufferGenerated(GLuint renderbuffer) const;
+ bool isFramebufferGenerated(GLuint framebuffer) const;
+
+ protected:
+ ContextState mState;
+ bool mSkipValidation;
+};
+} // namespace gl
+
+#endif // LIBANGLE_CONTEXTSTATE_H_
diff --git a/gfx/angle/src/libANGLE/Debug.cpp b/gfx/angle/src/libANGLE/Debug.cpp
new file mode 100755
index 000000000..30321f416
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Debug.cpp
@@ -0,0 +1,303 @@
+//
+// Copyright (c) 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 gl
+{
+
+Debug::Debug()
+ : mOutputEnabled(false),
+ mCallbackFunction(nullptr),
+ mCallbackUserParam(nullptr),
+ mMessages(),
+ mMaxLoggedMessages(0),
+ mOutputSynchronous(false),
+ mGroups()
+{
+ pushDefaultGroup();
+}
+
+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)
+{
+ std::string messageCopy(message);
+ insertMessage(source, type, id, severity, std::move(messageCopy));
+}
+
+void Debug::insertMessage(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ std::string &&message)
+{
+ 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());
+ }
+
+ mMessages.pop_front();
+
+ messageCount++;
+ }
+
+ return messageCount;
+}
+
+size_t Debug::getNextMessageLength() const
+{
+ return mMessages.empty() ? 0 : mMessages.front().message.length();
+}
+
+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));
+
+ 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);
+}
+
+size_t Debug::getGroupStackDepth() const
+{
+ return mGroups.size();
+}
+
+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
diff --git a/gfx/angle/src/libANGLE/Debug.h b/gfx/angle/src/libANGLE/Debug.h
new file mode 100755
index 000000000..f545b815e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Debug.h
@@ -0,0 +1,120 @@
+//
+// Copyright (c) 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/angleutils.h"
+
+#include <deque>
+#include <string>
+#include <vector>
+
+namespace gl
+{
+
+class LabeledObject
+{
+ public:
+ virtual ~LabeledObject() {}
+ virtual void setLabel(const std::string &label) = 0;
+ virtual const std::string &getLabel() const = 0;
+};
+
+class Debug : angle::NonCopyable
+{
+ public:
+ 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);
+ void insertMessage(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ std::string &&message);
+
+ 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;
+
+ 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
+ {
+ GLenum source;
+ GLenum type;
+ GLenum severity;
+ std::vector<GLuint> ids;
+ bool enabled;
+ };
+
+ struct Group
+ {
+ GLenum source;
+ GLuint id;
+ std::string message;
+
+ std::vector<Control> controls;
+ };
+
+ bool mOutputEnabled;
+ GLDEBUGPROCKHR mCallbackFunction;
+ const void *mCallbackUserParam;
+ std::deque<Message> mMessages;
+ GLuint mMaxLoggedMessages;
+ bool mOutputSynchronous;
+ std::vector<Group> mGroups;
+};
+} // namespace gl
+
+#endif // LIBANGLE_DEBUG_H_
diff --git a/gfx/angle/src/libANGLE/Device.cpp b/gfx/angle/src/libANGLE/Device.cpp
new file mode 100755
index 000000000..eb30b2023
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Device.cpp
@@ -0,0 +1,130 @@
+//
+// Copyright (c) 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 <platform/Platform.h>
+#include <EGL/eglext.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 DeviceSet devices;
+ return &devices;
+}
+
+// Static factory methods
+egl::Error Device::CreateDevice(void *devicePointer, EGLint deviceType, Device **outDevice)
+{
+#if defined(ANGLE_ENABLE_D3D11)
+ if (deviceType == EGL_D3D11_DEVICE_ANGLE)
+ {
+ rx::DeviceD3D *deviceD3D = new rx::DeviceD3D();
+ egl::Error error = deviceD3D->initialize(devicePointer, deviceType, EGL_TRUE);
+ if (error.isError())
+ {
+ *outDevice = nullptr;
+ return error;
+ }
+
+ *outDevice = new Device(nullptr, deviceD3D);
+ GetDeviceSet()->insert(*outDevice);
+ return egl::Error(EGL_SUCCESS);
+ }
+#endif
+
+ // Note that creating an EGL device from inputted D3D9 parameters isn't currently supported
+ *outDevice = nullptr;
+ return egl::Error(EGL_BAD_ATTRIBUTE);
+}
+
+egl::Error Device::CreateDevice(Display *owningDisplay, rx::DeviceImpl *impl, Device **outDevice)
+{
+ *outDevice = new Device(owningDisplay, impl);
+ GetDeviceSet()->insert(*outDevice);
+ return egl::Error(EGL_SUCCESS);
+}
+
+bool Device::IsValidDevice(Device *device)
+{
+ const DeviceSet *deviceSet = GetDeviceSet();
+ return deviceSet->find(device) != deviceSet->end();
+}
+
+Device::Device(Display *owningDisplay, rx::DeviceImpl *impl)
+ : mOwningDisplay(owningDisplay), mImplementation(impl)
+{
+ initDeviceExtensions();
+}
+
+Device::~Device()
+{
+ ASSERT(GetDeviceSet()->find(this) != GetDeviceSet()->end());
+ GetDeviceSet()->erase(this);
+
+ if (mImplementation->deviceExternallySourced())
+ {
+ // If the device isn't externally sourced then it is up to the renderer to delete the impl
+ SafeDelete(mImplementation);
+ }
+}
+
+Error Device::getDevice(EGLAttrib *value)
+{
+ void *nativeDevice = nullptr;
+ egl::Error error = getImplementation()->getDevice(&nativeDevice);
+ *value = reinterpret_cast<EGLAttrib>(nativeDevice);
+ return error;
+}
+
+EGLint Device::getType()
+{
+ return getImplementation()->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;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/Device.h b/gfx/angle/src/libANGLE/Device.h
new file mode 100755
index 000000000..4bc58ff04
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Device.h
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 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/Error.h"
+#include "libANGLE/Display.h"
+
+namespace rx
+{
+class DeviceImpl;
+}
+
+namespace egl
+{
+class Device final : angle::NonCopyable
+{
+ public:
+ virtual ~Device();
+
+ Error getDevice(EGLAttrib *value);
+ Display *getOwningDisplay() { return mOwningDisplay; };
+ EGLint getType();
+
+ const DeviceExtensions &getExtensions() const;
+ const std::string &getExtensionString() const;
+
+ rx::DeviceImpl *getImplementation() { return mImplementation; }
+
+ static egl::Error CreateDevice(void *devicePointer, EGLint deviceType, Device **outDevice);
+ static egl::Error CreateDevice(Display *owningDisplay,
+ rx::DeviceImpl *impl,
+ Device **outDevice);
+
+ static bool IsValidDevice(Device *device);
+
+ private:
+ Device(Display *owningDisplay, rx::DeviceImpl *impl);
+ void initDeviceExtensions();
+
+ Display *mOwningDisplay;
+ rx::DeviceImpl *mImplementation;
+
+ DeviceExtensions mDeviceExtensions;
+ std::string mDeviceExtensionString;
+};
+
+}
+
+#endif // LIBANGLE_DEVICE_H_
diff --git a/gfx/angle/src/libANGLE/Display.cpp b/gfx/angle/src/libANGLE/Display.cpp
new file mode 100755
index 000000000..39851f9f8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Display.cpp
@@ -0,0 +1,1033 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 <map>
+#include <sstream>
+#include <vector>
+
+#include <platform/Platform.h>
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/platform.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Device.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/renderer/DisplayImpl.h"
+#include "libANGLE/renderer/ImageImpl.h"
+#include "third_party/trace_event/trace_event.h"
+
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+# 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_USE_X11)
+# include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+# elif defined(ANGLE_PLATFORM_APPLE)
+# include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
+# elif defined(ANGLE_USE_OZONE)
+# include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
+# 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
+
+namespace egl
+{
+
+namespace
+{
+
+class DefaultPlatform : public angle::Platform
+{
+public:
+ DefaultPlatform() {}
+ ~DefaultPlatform() override {}
+};
+
+DefaultPlatform *defaultPlatform = nullptr;
+
+void InitDefaultPlatformImpl()
+{
+ if (ANGLEPlatformCurrent() == nullptr)
+ {
+ if (defaultPlatform == nullptr)
+ {
+ defaultPlatform = new DefaultPlatform();
+ }
+
+ ANGLEPlatformInitialize(defaultPlatform);
+ }
+}
+
+typedef std::map<EGLNativeWindowType, Surface*> 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 WindowSurfaceMap windowSurfaces;
+ return &windowSurfaces;
+}
+
+typedef std::map<EGLNativeDisplayType, Display *> ANGLEPlatformDisplayMap;
+static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap()
+{
+ static ANGLEPlatformDisplayMap displays;
+ return &displays;
+}
+
+typedef std::map<Device *, Display *> DevicePlatformDisplayMap;
+static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap()
+{
+ static DevicePlatformDisplayMap displays;
+ return &displays;
+}
+
+rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice)
+{
+ rx::DisplayImpl *impl = nullptr;
+
+ switch (eglDevice->getType())
+ {
+#if defined(ANGLE_ENABLE_D3D11)
+ case EGL_D3D11_DEVICE_ANGLE:
+ impl = new rx::DisplayD3D();
+ 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;
+}
+
+rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap)
+{
+ rx::DisplayImpl *impl = nullptr;
+ EGLAttrib displayType =
+ attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+ switch (displayType)
+ {
+ case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+ // Default to D3D displays
+ impl = new rx::DisplayD3D();
+#elif defined(ANGLE_USE_X11)
+ impl = new rx::DisplayGLX();
+#elif defined(ANGLE_PLATFORM_APPLE)
+ impl = new rx::DisplayCGL();
+#elif defined(ANGLE_USE_OZONE)
+ impl = new rx::DisplayOzone();
+#elif defined(ANGLE_PLATFORM_ANDROID)
+ impl = new rx::DisplayAndroid();
+#else
+ // No display available
+ UNREACHABLE();
+#endif
+ 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();
+#else
+ // A D3D display was requested on a platform that doesn't support it
+ UNREACHABLE();
+#endif
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+#if defined(ANGLE_ENABLE_OPENGL)
+#if defined(ANGLE_PLATFORM_WINDOWS)
+ impl = new rx::DisplayWGL();
+#elif defined(ANGLE_USE_X11)
+ impl = new rx::DisplayGLX();
+#elif defined(ANGLE_PLATFORM_APPLE)
+ impl = new rx::DisplayCGL();
+#elif defined(ANGLE_USE_OZONE)
+ // This might work but has never been tried, so disallow for now.
+ impl = nullptr;
+#elif defined(ANGLE_PLATFORM_ANDROID)
+ // No GL support on this platform, fail display creation.
+ impl = nullptr;
+#else
+#error Unsupported OpenGL platform.
+#endif
+#else
+ UNREACHABLE();
+#endif
+ break;
+
+#if defined(ANGLE_ENABLE_OPENGL)
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+#if defined(ANGLE_PLATFORM_WINDOWS)
+ impl = new rx::DisplayWGL();
+#elif defined(ANGLE_USE_X11)
+ impl = new rx::DisplayGLX();
+#elif defined(ANGLE_USE_OZONE)
+ impl = new rx::DisplayOzone();
+#elif defined(ANGLE_PLATFORM_ANDROID)
+ impl = new rx::DisplayAndroid();
+#else
+ // No GLES support on this platform, fail display creation.
+ impl = nullptr;
+#endif
+ break;
+#endif
+
+#if defined(ANGLE_ENABLE_NULL)
+ case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
+ impl = new rx::DisplayNULL();
+ break;
+#endif
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return impl;
+}
+
+}
+
+Display *Display::GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap)
+{
+ // Initialize the global platform if not already
+ InitDefaultPlatformImpl();
+
+ Display *display = nullptr;
+
+ EGLNativeDisplayType displayId = reinterpret_cast<EGLNativeDisplayType>(native_display);
+
+ ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
+ ANGLEPlatformDisplayMap::const_iterator iter = displays->find(displayId);
+ if (iter != displays->end())
+ {
+ display = iter->second;
+ }
+
+ if (display == nullptr)
+ {
+ // Validate the native display
+ if (!Display::isValidNativeDisplay(displayId))
+ {
+ return NULL;
+ }
+
+ display = new Display(EGL_PLATFORM_ANGLE_ANGLE, displayId, nullptr);
+ displays->insert(std::make_pair(displayId, display));
+ }
+
+ // Apply new attributes if the display is not initialized yet.
+ if (!display->isInitialized())
+ {
+ rx::DisplayImpl *impl = CreateDisplayFromAttribs(attribMap);
+ if (impl == nullptr)
+ {
+ // No valid display implementation for these attributes
+ return nullptr;
+ }
+
+ display->setAttributes(impl, attribMap);
+ }
+
+ return display;
+}
+
+Display *Display::GetDisplayFromDevice(void *native_display)
+{
+ // Initialize the global platform if not already
+ InitDefaultPlatformImpl();
+
+ Display *display = nullptr;
+
+ Device *eglDevice = reinterpret_cast<Device *>(native_display);
+ ASSERT(Device::IsValidDevice(eglDevice));
+
+ 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() == eglDevice)
+ {
+ display = iterDisplay;
+ }
+ }
+
+ if (display == nullptr)
+ {
+ // See if the eglDevice is in use by a Display created using the DEVICE platform
+ DevicePlatformDisplayMap::const_iterator iter = devicePlatformDisplays->find(eglDevice);
+ if (iter != devicePlatformDisplays->end())
+ {
+ display = iter->second;
+ }
+ }
+
+ if (display == nullptr)
+ {
+ // Otherwise create a new Display
+ display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, eglDevice);
+ devicePlatformDisplays->insert(std::make_pair(eglDevice, display));
+ }
+
+ // Apply new attributes if the display is not initialized yet.
+ if (!display->isInitialized())
+ {
+ rx::DisplayImpl *impl = CreateDisplayFromDevice(eglDevice);
+ display->setAttributes(impl, egl::AttributeMap());
+ }
+
+ return display;
+}
+
+Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
+ : mImplementation(nullptr),
+ mDisplayId(displayId),
+ mAttributeMap(),
+ mConfigSet(),
+ mContextSet(),
+ mStreamSet(),
+ mInitialized(false),
+ mDeviceLost(false),
+ mCaps(),
+ mDisplayExtensions(),
+ mDisplayExtensionString(),
+ mVendorString(),
+ mDevice(eglDevice),
+ mPlatform(platform)
+{
+}
+
+Display::~Display()
+{
+ terminate();
+
+ if (mPlatform == EGL_PLATFORM_ANGLE_ANGLE)
+ {
+ ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
+ ANGLEPlatformDisplayMap::iterator iter = displays->find(mDisplayId);
+ if (iter != displays->end())
+ {
+ displays->erase(iter);
+ }
+ }
+ else if (mPlatform == EGL_PLATFORM_DEVICE_EXT)
+ {
+ DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap();
+ DevicePlatformDisplayMap::iterator iter = displays->find(mDevice);
+ if (iter != displays->end())
+ {
+ displays->erase(iter);
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ SafeDelete(mDevice);
+ SafeDelete(mImplementation);
+}
+
+void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap)
+{
+ ASSERT(!mInitialized);
+
+ ASSERT(impl != nullptr);
+ SafeDelete(mImplementation);
+ mImplementation = impl;
+
+ mAttributeMap = attribMap;
+}
+
+Error Display::initialize()
+{
+ // Re-initialize default platform if it's needed
+ InitDefaultPlatformImpl();
+
+ SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.DisplayInitializeMS");
+ TRACE_EVENT0("gpu.angle", "egl::Display::initialize");
+
+ ASSERT(mImplementation != nullptr);
+
+ if (isInitialized())
+ {
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ Error error = mImplementation->initialize(this);
+ if (error.isError())
+ {
+ // Log extended error message here
+ std::stringstream errorStream;
+ errorStream << "ANGLE Display::initialize error " << error.getID() << ": "
+ << error.getMessage();
+ ANGLEPlatformCurrent()->logError(errorStream.str().c_str());
+ return error;
+ }
+
+ mCaps = mImplementation->getCaps();
+
+ mConfigSet = mImplementation->generateConfigs();
+ if (mConfigSet.size() == 0)
+ {
+ mImplementation->terminate();
+ return Error(EGL_NOT_INITIALIZED);
+ }
+
+ initDisplayExtensions();
+ initVendorString();
+
+ // Populate the Display's EGLDeviceEXT if the Display wasn't created using one
+ if (mPlatform != EGL_PLATFORM_DEVICE_EXT)
+ {
+ if (mDisplayExtensions.deviceQuery)
+ {
+ rx::DeviceImpl *impl = nullptr;
+ ANGLE_TRY(mImplementation->getDevice(&impl));
+ ANGLE_TRY(Device::CreateDevice(this, impl, &mDevice));
+ }
+ else
+ {
+ mDevice = nullptr;
+ }
+ }
+ else
+ {
+ // For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using
+ // an external device
+ ASSERT(mDevice != nullptr);
+ }
+
+ mInitialized = true;
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+void Display::terminate()
+{
+ makeCurrent(nullptr, nullptr, nullptr);
+
+ while (!mContextSet.empty())
+ {
+ destroyContext(*mContextSet.begin());
+ }
+
+ while (!mImageSet.empty())
+ {
+ destroyImage(*mImageSet.begin());
+ }
+
+ while (!mStreamSet.empty())
+ {
+ destroyStream(*mStreamSet.begin());
+ }
+
+ while (!mImplementation->getSurfaceSet().empty())
+ {
+ destroySurface(*mImplementation->getSurfaceSet().begin());
+ }
+
+ 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();
+
+ mInitialized = false;
+
+ // Never de-init default platform.. terminate is not that final.
+}
+
+std::vector<const Config*> Display::getConfigs(const egl::AttributeMap &attribs) const
+{
+ return mConfigSet.filter(attribs);
+}
+
+bool Display::getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value)
+{
+ switch (attribute)
+ {
+ case EGL_BUFFER_SIZE: *value = configuration->bufferSize; break;
+ case EGL_ALPHA_SIZE: *value = configuration->alphaSize; break;
+ case EGL_BLUE_SIZE: *value = configuration->blueSize; break;
+ case EGL_GREEN_SIZE: *value = configuration->greenSize; break;
+ case EGL_RED_SIZE: *value = configuration->redSize; break;
+ case EGL_DEPTH_SIZE: *value = configuration->depthSize; break;
+ case EGL_STENCIL_SIZE: *value = configuration->stencilSize; break;
+ case EGL_CONFIG_CAVEAT: *value = configuration->configCaveat; break;
+ case EGL_CONFIG_ID: *value = configuration->configID; break;
+ case EGL_LEVEL: *value = configuration->level; break;
+ case EGL_NATIVE_RENDERABLE: *value = configuration->nativeRenderable; break;
+ case EGL_NATIVE_VISUAL_ID: *value = configuration->nativeVisualID; break;
+ case EGL_NATIVE_VISUAL_TYPE: *value = configuration->nativeVisualType; break;
+ case EGL_SAMPLES: *value = configuration->samples; break;
+ case EGL_SAMPLE_BUFFERS: *value = configuration->sampleBuffers; break;
+ case EGL_SURFACE_TYPE: *value = configuration->surfaceType; break;
+ case EGL_TRANSPARENT_TYPE: *value = configuration->transparentType; break;
+ case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->transparentBlueValue; break;
+ case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->transparentGreenValue; break;
+ case EGL_TRANSPARENT_RED_VALUE: *value = configuration->transparentRedValue; break;
+ case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->bindToTextureRGB; break;
+ case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->bindToTextureRGBA; break;
+ case EGL_MIN_SWAP_INTERVAL: *value = configuration->minSwapInterval; break;
+ case EGL_MAX_SWAP_INTERVAL: *value = configuration->maxSwapInterval; break;
+ case EGL_LUMINANCE_SIZE: *value = configuration->luminanceSize; break;
+ case EGL_ALPHA_MASK_SIZE: *value = configuration->alphaMaskSize; break;
+ case EGL_COLOR_BUFFER_TYPE: *value = configuration->colorBufferType; break;
+ case EGL_RENDERABLE_TYPE: *value = configuration->renderableType; break;
+ case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break;
+ case EGL_CONFORMANT: *value = configuration->conformant; break;
+ case EGL_MAX_PBUFFER_WIDTH: *value = configuration->maxPBufferWidth; break;
+ case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->maxPBufferHeight; break;
+ case EGL_MAX_PBUFFER_PIXELS: *value = configuration->maxPBufferPixels; break;
+
+ case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+ if (!getExtensions().surfaceOrientation)
+ {
+ return false;
+ }
+ *value = configuration->optimalOrientation;
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+Error Display::createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs,
+ Surface **outSurface)
+{
+ if (mImplementation->testDeviceLost())
+ {
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ std::unique_ptr<Surface> surface(
+ new WindowSurface(mImplementation, configuration, window, attribs));
+ ANGLE_TRY(surface->initialize());
+
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface.release();
+ mImplementation->getSurfaceSet().insert(*outSurface);
+
+ WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
+ ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end());
+ windowSurfaces->insert(std::make_pair(window, *outSurface));
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ std::unique_ptr<Surface> surface(new PbufferSurface(mImplementation, configuration, attribs));
+ ANGLE_TRY(surface->initialize());
+
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface.release();
+ mImplementation->getSurfaceSet().insert(*outSurface);
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::createPbufferFromClientBuffer(const Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs,
+ Surface **outSurface)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ std::unique_ptr<Surface> surface(
+ new PbufferSurface(mImplementation, configuration, buftype, clientBuffer, attribs));
+ ANGLE_TRY(surface->initialize());
+
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface.release();
+ mImplementation->getSurfaceSet().insert(*outSurface);
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs,
+ Surface **outSurface)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ std::unique_ptr<Surface> surface(
+ new PixmapSurface(mImplementation, configuration, nativePixmap, attribs));
+ ANGLE_TRY(surface->initialize());
+
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface.release();
+ mImplementation->getSurfaceSet().insert(*outSurface);
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::createImage(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
+ {
+ UNREACHABLE();
+ }
+ ASSERT(sibling != nullptr);
+
+ rx::ImageImpl *imageImpl = mImplementation->createImage(target, sibling, attribs);
+ ASSERT(imageImpl != nullptr);
+
+ ANGLE_TRY(imageImpl->initialize());
+
+ Image *image = new Image(imageImpl, target, sibling, attribs);
+
+ 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 egl::Error(EGL_SUCCESS);
+}
+
+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 Error(EGL_SUCCESS);
+}
+
+Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
+ gl::Context **outContext)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ gl::Context *context = new gl::Context(mImplementation, configuration, shareContext, attribs);
+
+ ASSERT(context != nullptr);
+ mContextSet.insert(context);
+
+ ASSERT(outContext != nullptr);
+ *outContext = context;
+ return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
+{
+ ANGLE_TRY(mImplementation->makeCurrent(drawSurface, readSurface, context));
+
+ if (context != nullptr && drawSurface != nullptr)
+ {
+ ASSERT(readSurface == drawSurface);
+ context->makeCurrent(drawSurface);
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::restoreLostDevice()
+{
+ for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
+ {
+ if ((*ctx)->isResetNotificationEnabled())
+ {
+ // If reset notifications have been requested, application must delete all contexts first
+ return Error(EGL_CONTEXT_LOST);
+ }
+ }
+
+ return mImplementation->restoreLostDevice();
+}
+
+void Display::destroySurface(Surface *surface)
+{
+ 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);
+ }
+
+ mImplementation->destroySurface(surface);
+}
+
+void Display::destroyImage(egl::Image *image)
+{
+ auto iter = mImageSet.find(image);
+ ASSERT(iter != mImageSet.end());
+ (*iter)->release();
+ mImageSet.erase(iter);
+}
+
+void Display::destroyStream(egl::Stream *stream)
+{
+ mStreamSet.erase(stream);
+ SafeDelete(stream);
+}
+
+void Display::destroyContext(gl::Context *context)
+{
+ mContextSet.erase(context);
+ SafeDelete(context);
+}
+
+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 = mContextSet.begin(); context != mContextSet.end(); context++)
+ {
+ (*context)->markContextLost();
+ }
+
+ mDeviceLost = true;
+}
+
+Error Display::waitClient() const
+{
+ return mImplementation->waitClient();
+}
+
+Error Display::waitNative(EGLint engine, egl::Surface *drawSurface, egl::Surface *readSurface) const
+{
+ return mImplementation->waitNative(engine, drawSurface, readSurface);
+}
+
+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 mContextSet.find(const_cast<gl::Context *>(context)) != mContextSet.end();
+}
+
+bool Display::isValidSurface(const Surface *surface) const
+{
+ return mImplementation->getSurfaceSet().find(const_cast<Surface *>(surface)) !=
+ mImplementation->getSurfaceSet().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::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_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_USE_X11)
+ extensions.x11Visual = true;
+#endif
+
+ extensions.clientGetAllProcAddresses = 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();
+}
+
+const ClientExtensions &Display::getClientExtensions()
+{
+ static const ClientExtensions clientExtensions = GenerateClientExtensions();
+ return clientExtensions;
+}
+
+const std::string &Display::getClientExtensionString()
+{
+ static const 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 = true;
+ mDisplayExtensions.createContextWebGLCompatibility = true;
+ mDisplayExtensions.createContextBindGeneratesResource = true;
+
+ // Force EGL_KHR_get_all_proc_addresses on.
+ mDisplayExtensions.getAllProcAddresses = 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)
+{
+ return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs);
+}
+
+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_STORE)
+ if (display == EGL_SOFTWARE_DISPLAY_ANGLE ||
+ display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+ display == EGL_D3D11_ONLY_DISPLAY_ANGLE)
+ {
+ return true;
+ }
+ return (WindowFromDC(display) != NULL);
+#else
+ return true;
+#endif
+}
+
+void Display::initVendorString()
+{
+ mVendorString = mImplementation->getVendorString();
+}
+
+const DisplayExtensions &Display::getExtensions() const
+{
+ return mDisplayExtensions;
+}
+
+const std::string &Display::getExtensionString() const
+{
+ return mDisplayExtensionString;
+}
+
+const std::string &Display::getVendorString() const
+{
+ return mVendorString;
+}
+
+Device *Display::getDevice() const
+{
+ return mDevice;
+}
+
+gl::Version Display::getMaxSupportedESVersion() const
+{
+ return mImplementation->getMaxSupportedESVersion();
+}
+}
diff --git a/gfx/angle/src/libANGLE/Display.h b/gfx/angle/src/libANGLE/Display.h
new file mode 100755
index 000000000..15754ac37
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Display.h
@@ -0,0 +1,167 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 <set>
+#include <vector>
+
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Version.h"
+
+namespace gl
+{
+class Context;
+}
+
+namespace rx
+{
+class DisplayImpl;
+}
+
+namespace egl
+{
+class Device;
+class Image;
+class Surface;
+class Stream;
+
+class Display final : angle::NonCopyable
+{
+ public:
+ ~Display();
+
+ Error initialize();
+ void terminate();
+
+ static egl::Display *GetDisplayFromDevice(void *native_display);
+ static egl::Display *GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap);
+
+ static const ClientExtensions &getClientExtensions();
+ static const std::string &getClientExtensionString();
+
+ std::vector<const Config*> getConfigs(const egl::AttributeMap &attribs) const;
+ bool getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value);
+
+ 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(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 AttributeMap &attribs,
+ gl::Context **outContext);
+
+ Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context);
+
+ void destroySurface(egl::Surface *surface);
+ void destroyImage(egl::Image *image);
+ void destroyStream(egl::Stream *stream);
+ void destroyContext(gl::Context *context);
+
+ bool isInitialized() const;
+ bool isValidConfig(const Config *config) const;
+ bool isValidContext(const gl::Context *context) const;
+ bool isValidSurface(const egl::Surface *surface) const;
+ bool isValidImage(const Image *image) const;
+ bool isValidStream(const Stream *stream) const;
+ bool isValidNativeWindow(EGLNativeWindowType window) const;
+
+ Error validateClientBuffer(const Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs);
+
+ static bool isValidDisplay(const egl::Display *display);
+ static bool isValidNativeDisplay(EGLNativeDisplayType display);
+ static bool hasExistingWindowSurface(EGLNativeWindowType window);
+
+ bool isDeviceLost() const;
+ bool testDeviceLost();
+ void notifyDeviceLost();
+
+ Error waitClient() const;
+ Error waitNative(EGLint engine, egl::Surface *drawSurface, egl::Surface *readSurface) const;
+
+ const Caps &getCaps() const;
+
+ const DisplayExtensions &getExtensions() const;
+ const std::string &getExtensionString() const;
+ const std::string &getVendorString() const;
+
+ const AttributeMap &getAttributeMap() const { return mAttributeMap; }
+ EGLNativeDisplayType getNativeDisplayId() const { return mDisplayId; }
+
+ rx::DisplayImpl *getImplementation() { return mImplementation; }
+ Device *getDevice() const;
+ EGLenum getPlatform() const { return mPlatform; }
+
+ gl::Version getMaxSupportedESVersion() const;
+
+ private:
+ Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice);
+
+ void setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap);
+
+ Error restoreLostDevice();
+
+ void initDisplayExtensions();
+ void initVendorString();
+
+ rx::DisplayImpl *mImplementation;
+
+ EGLNativeDisplayType mDisplayId;
+ AttributeMap mAttributeMap;
+
+ ConfigSet mConfigSet;
+
+ typedef std::set<gl::Context*> ContextSet;
+ ContextSet mContextSet;
+
+ typedef std::set<Image *> ImageSet;
+ ImageSet mImageSet;
+
+ typedef std::set<Stream *> StreamSet;
+ StreamSet mStreamSet;
+
+ bool mInitialized;
+ bool mDeviceLost;
+
+ Caps mCaps;
+
+ DisplayExtensions mDisplayExtensions;
+ std::string mDisplayExtensionString;
+
+ std::string mVendorString;
+
+ Device *mDevice;
+ EGLenum mPlatform;
+};
+
+}
+
+#endif // LIBANGLE_DISPLAY_H_
diff --git a/gfx/angle/src/libANGLE/Error.cpp b/gfx/angle/src/libANGLE/Error.cpp
new file mode 100755
index 000000000..fed159497
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Error.cpp
@@ -0,0 +1,104 @@
+//
+// Copyright (c) 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 <cstdarg>
+
+namespace gl
+{
+
+Error::Error(GLenum errorCode, const char *msg, ...) : mCode(errorCode), mID(errorCode)
+{
+ va_list vararg;
+ va_start(vararg, msg);
+ createMessageString();
+ *mMessage = FormatString(msg, vararg);
+ va_end(vararg);
+}
+
+Error::Error(GLenum errorCode, GLuint id, const char *msg, ...) : mCode(errorCode), mID(id)
+{
+ va_list vararg;
+ va_start(vararg, msg);
+ createMessageString();
+ *mMessage = FormatString(msg, vararg);
+ va_end(vararg);
+}
+
+void Error::createMessageString() const
+{
+ if (!mMessage)
+ {
+ mMessage.reset(new std::string);
+ }
+}
+
+const std::string &Error::getMessage() const
+{
+ createMessageString();
+ return *mMessage;
+}
+
+bool Error::operator==(const Error &other) const
+{
+ if (mCode != other.mCode)
+ return false;
+
+ // TODO(jmadill): Compare extended error codes instead of strings.
+ if ((!mMessage || !other.mMessage) && (!mMessage != !other.mMessage))
+ return false;
+
+ return (*mMessage == *other.mMessage);
+}
+
+bool Error::operator!=(const Error &other) const
+{
+ return !(*this == other);
+}
+}
+
+namespace egl
+{
+
+Error::Error(EGLint errorCode, const char *msg, ...) : mCode(errorCode), mID(0)
+{
+ va_list vararg;
+ va_start(vararg, msg);
+ createMessageString();
+ *mMessage = FormatString(msg, vararg);
+ va_end(vararg);
+}
+
+Error::Error(EGLint errorCode, EGLint id, const char *msg, ...) : mCode(errorCode), mID(id)
+{
+ va_list vararg;
+ va_start(vararg, msg);
+ createMessageString();
+ *mMessage = FormatString(msg, vararg);
+ va_end(vararg);
+}
+
+void Error::createMessageString() const
+{
+ if (!mMessage)
+ {
+ mMessage.reset(new std::string);
+ }
+}
+
+const std::string &Error::getMessage() const
+{
+ createMessageString();
+ return *mMessage;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/Error.h b/gfx/angle/src/libANGLE/Error.h
new file mode 100755
index 000000000..de3a50eb0
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Error.h
@@ -0,0 +1,146 @@
+//
+// Copyright (c) 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 "angle_gl.h"
+#include <EGL/egl.h>
+
+#include <string>
+#include <memory>
+
+namespace gl
+{
+
+class Error final
+{
+ public:
+ explicit inline Error(GLenum errorCode);
+ Error(GLenum errorCode, const char *msg, ...);
+ Error(GLenum errorCode, GLuint id, const char *msg, ...);
+ inline Error(const Error &other);
+ inline Error(Error &&other);
+
+ inline Error &operator=(const Error &other);
+ inline Error &operator=(Error &&other);
+
+ inline GLenum getCode() const;
+ inline GLuint getID() const;
+ inline bool isError() const;
+
+ const std::string &getMessage() const;
+
+ // Useful for mocking and testing
+ bool operator==(const Error &other) const;
+ bool operator!=(const Error &other) const;
+
+ private:
+ void createMessageString() const;
+
+ GLenum mCode;
+ GLuint mID;
+ mutable std::unique_ptr<std::string> mMessage;
+};
+
+template <typename T>
+class ErrorOrResult
+{
+ public:
+ ErrorOrResult(const gl::Error &error) : mError(error) {}
+ ErrorOrResult(gl::Error &&error) : mError(std::move(error)) {}
+
+ ErrorOrResult(T &&result)
+ : mError(GL_NO_ERROR), mResult(std::forward<T>(result))
+ {
+ }
+
+ ErrorOrResult(const T &result)
+ : mError(GL_NO_ERROR), mResult(result)
+ {
+ }
+
+ bool isError() const { return mError.isError(); }
+ const gl::Error &getError() const { return mError; }
+ T &&getResult() { return std::move(mResult); }
+
+ private:
+ Error mError;
+ T mResult;
+};
+
+inline Error NoError()
+{
+ return Error(GL_NO_ERROR);
+}
+
+} // namespace gl
+
+namespace egl
+{
+
+class Error final
+{
+ public:
+ explicit inline Error(EGLint errorCode);
+ Error(EGLint errorCode, const char *msg, ...);
+ Error(EGLint errorCode, EGLint id, const char *msg, ...);
+ inline Error(const Error &other);
+ inline Error(Error &&other);
+
+ 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;
+
+ private:
+ void createMessageString() const;
+
+ EGLint mCode;
+ EGLint mID;
+ mutable std::unique_ptr<std::string> mMessage;
+};
+
+} // 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(EXPR) \
+ { \
+ auto ANGLE_LOCAL_VAR = EXPR; \
+ if (ANGLE_LOCAL_VAR.isError()) \
+ { \
+ return ANGLE_LOCAL_VAR; \
+ } \
+ } \
+ ANGLE_EMPTY_STATEMENT
+
+#define ANGLE_TRY_RESULT(EXPR, RESULT) \
+ { \
+ auto ANGLE_LOCAL_VAR = EXPR; \
+ if (ANGLE_LOCAL_VAR.isError()) \
+ { \
+ return ANGLE_LOCAL_VAR.getError(); \
+ } \
+ RESULT = ANGLE_LOCAL_VAR.getResult(); \
+ } \
+ ANGLE_EMPTY_STATEMENT
+
+#undef ANGLE_LOCAL_VAR
+#undef ANGLE_CONCAT2
+#undef ANGLE_CONCAT1
+
+#include "Error.inl"
+
+#endif // LIBANGLE_ERROR_H_
diff --git a/gfx/angle/src/libANGLE/Error.inl b/gfx/angle/src/libANGLE/Error.inl
new file mode 100755
index 000000000..900fc5fd0
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Error.inl
@@ -0,0 +1,159 @@
+//
+// Copyright (c) 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.inl: Inline definitions of egl::Error and gl::Error classes which encapsulate API errors
+// and optional error messages.
+
+#include "common/angleutils.h"
+
+#include <cstdarg>
+
+namespace gl
+{
+
+Error::Error(GLenum errorCode)
+ : mCode(errorCode),
+ mID(errorCode)
+{
+}
+
+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.release();
+ }
+
+ return *this;
+}
+
+Error &Error::operator=(Error &&other)
+{
+ if (this != &other)
+ {
+ mCode = other.mCode;
+ mID = other.mID;
+ mMessage = std::move(other.mMessage);
+ }
+
+ return *this;
+}
+
+GLenum Error::getCode() const
+{
+ return mCode;
+}
+
+GLuint Error::getID() const
+{
+ return mID;
+}
+
+bool Error::isError() const
+{
+ return (mCode != GL_NO_ERROR);
+}
+
+}
+
+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.release();
+ }
+
+ 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);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/Fence.cpp b/gfx/angle/src/libANGLE/Fence.cpp
new file mode 100755
index 000000000..e5f3ba69a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Fence.cpp
@@ -0,0 +1,126 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// Fence.cpp: Implements the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence
+// extension and GLES3 sync objects.
+
+#include "libANGLE/Fence.h"
+
+#include "angle_gl.h"
+
+#include "common/utilities.h"
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+namespace gl
+{
+
+FenceNV::FenceNV(rx::FenceNVImpl *impl)
+ : mFence(impl),
+ mIsSet(false),
+ mStatus(GL_FALSE),
+ mCondition(GL_NONE)
+{
+}
+
+FenceNV::~FenceNV()
+{
+ SafeDelete(mFence);
+}
+
+Error FenceNV::set(GLenum condition)
+{
+ Error error = mFence->set(condition);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mCondition = condition;
+ mStatus = GL_FALSE;
+ mIsSet = true;
+
+ return Error(GL_NO_ERROR);
+}
+
+Error FenceNV::test(GLboolean *outResult)
+{
+ // Flush the command buffer by default
+ Error error = mFence->test(&mStatus);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *outResult = mStatus;
+ return Error(GL_NO_ERROR);
+}
+
+Error FenceNV::finish()
+{
+ ASSERT(mIsSet);
+
+ gl::Error error = mFence->finish();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mStatus = GL_TRUE;
+
+ return Error(GL_NO_ERROR);
+}
+
+FenceSync::FenceSync(rx::FenceSyncImpl *impl, GLuint id)
+ : RefCountObject(id), mFence(impl), mLabel(), mCondition(GL_NONE), mFlags(0)
+{
+}
+
+FenceSync::~FenceSync()
+{
+ SafeDelete(mFence);
+}
+
+void FenceSync::setLabel(const std::string &label)
+{
+ mLabel = label;
+}
+
+const std::string &FenceSync::getLabel() const
+{
+ return mLabel;
+}
+
+Error FenceSync::set(GLenum condition, GLbitfield flags)
+{
+ Error error = mFence->set(condition, flags);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mCondition = condition;
+ mFlags = flags;
+ return Error(GL_NO_ERROR);
+}
+
+Error FenceSync::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+{
+ ASSERT(mCondition != GL_NONE);
+ return mFence->clientWait(flags, timeout, outResult);
+}
+
+Error FenceSync::serverWait(GLbitfield flags, GLuint64 timeout)
+{
+ return mFence->serverWait(flags, timeout);
+}
+
+Error FenceSync::getStatus(GLint *outResult) const
+{
+ return mFence->getStatus(outResult);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/Fence.h b/gfx/angle/src/libANGLE/Fence.h
new file mode 100755
index 000000000..b2daed6f0
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Fence.h
@@ -0,0 +1,79 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// Fence.h: Defines the gl::FenceNV and gl::FenceSync 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 FenceNVImpl;
+class FenceSyncImpl;
+}
+
+namespace gl
+{
+
+class FenceNV final : angle::NonCopyable
+{
+ public:
+ explicit FenceNV(rx::FenceNVImpl *impl);
+ virtual ~FenceNV();
+
+ Error set(GLenum condition);
+ Error test(GLboolean *outResult);
+ Error finish();
+
+ 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 FenceSync final : public RefCountObject, public LabeledObject
+{
+ public:
+ FenceSync(rx::FenceSyncImpl *impl, GLuint id);
+ virtual ~FenceSync();
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ Error set(GLenum condition, GLbitfield flags);
+ Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult);
+ Error serverWait(GLbitfield flags, GLuint64 timeout);
+ Error getStatus(GLint *outResult) const;
+
+ GLenum getCondition() const { return mCondition; }
+ GLbitfield getFlags() const { return mFlags; }
+
+ private:
+ rx::FenceSyncImpl *mFence;
+
+ std::string mLabel;
+
+ GLenum mCondition;
+ GLbitfield mFlags;
+};
+
+}
+
+#endif // LIBANGLE_FENCE_H_
diff --git a/gfx/angle/src/libANGLE/Fence_unittest.cpp b/gfx/angle/src/libANGLE/Fence_unittest.cpp
new file mode 100755
index 000000000..37b3e6f56
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Fence_unittest.cpp
@@ -0,0 +1,163 @@
+//
+// Copyright (c) 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 "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SetArgumentPointee;
+
+namespace {
+
+//
+// FenceNV tests
+//
+
+class MockFenceNVImpl : public rx::FenceNVImpl
+{
+ public:
+ virtual ~MockFenceNVImpl() { destroy(); }
+
+ MOCK_METHOD1(set, gl::Error(GLenum));
+ MOCK_METHOD1(test, gl::Error(GLboolean *));
+ MOCK_METHOD0(finish, gl::Error());
+
+ MOCK_METHOD0(destroy, void());
+};
+
+class FenceNVTest : public testing::Test
+{
+ protected:
+ virtual void SetUp()
+ {
+ mImpl = new MockFenceNVImpl;
+ EXPECT_CALL(*mImpl, destroy());
+ mFence = new gl::FenceNV(mImpl);
+ }
+
+ virtual void TearDown()
+ {
+ delete mFence;
+ }
+
+ MockFenceNVImpl *mImpl;
+ gl::FenceNV* mFence;
+};
+
+TEST_F(FenceNVTest, DestructionDeletesImpl)
+{
+ MockFenceNVImpl* impl = new MockFenceNVImpl;
+ EXPECT_CALL(*impl, destroy()).Times(1).RetiresOnSaturation();
+
+ gl::FenceNV* fence = new gl::FenceNV(impl);
+ delete fence;
+
+ // Only needed because the mock is leaked if bugs are present,
+ // which logs an error, but does not cause the test to fail.
+ // Ordinarily mocks are verified when destroyed.
+ testing::Mock::VerifyAndClear(impl);
+}
+
+TEST_F(FenceNVTest, SetAndTestBehavior)
+{
+ EXPECT_CALL(*mImpl, set(_))
+ .WillOnce(Return(gl::Error(GL_NO_ERROR)))
+ .RetiresOnSaturation();
+ EXPECT_FALSE(mFence->isSet());
+ mFence->set(GL_ALL_COMPLETED_NV);
+ EXPECT_TRUE(mFence->isSet());
+ // Fake the behavior of testing the fence before and after it's passed.
+ EXPECT_CALL(*mImpl, test(_))
+ .WillOnce(DoAll(SetArgumentPointee<0>(GL_FALSE),
+ Return(gl::Error(GL_NO_ERROR))))
+ .WillOnce(DoAll(SetArgumentPointee<0>(GL_TRUE),
+ Return(gl::Error(GL_NO_ERROR))))
+ .RetiresOnSaturation();
+ GLboolean out;
+ mFence->test(&out);
+ EXPECT_EQ(GL_FALSE, out);
+ mFence->test(&out);
+ EXPECT_EQ(GL_TRUE, out);
+}
+
+//
+// FenceSync tests
+//
+
+class MockFenceSyncImpl : public rx::FenceSyncImpl
+{
+ public:
+ virtual ~MockFenceSyncImpl() { destroy(); }
+
+ MOCK_METHOD2(set, gl::Error(GLenum, GLbitfield));
+ MOCK_METHOD3(clientWait, gl::Error(GLbitfield, GLuint64, GLenum *));
+ MOCK_METHOD2(serverWait, gl::Error(GLbitfield, GLuint64));
+ MOCK_METHOD1(getStatus, gl::Error(GLint *));
+
+ MOCK_METHOD0(destroy, void());
+};
+
+class FenceSyncTest : public testing::Test
+{
+ protected:
+ virtual void SetUp()
+ {
+ mImpl = new MockFenceSyncImpl;
+ EXPECT_CALL(*mImpl, destroy());
+ mFence = new gl::FenceSync(mImpl, 1);
+ mFence->addRef();
+ }
+
+ virtual void TearDown()
+ {
+ mFence->release();
+ }
+
+ MockFenceSyncImpl *mImpl;
+ gl::FenceSync* mFence;
+};
+
+TEST_F(FenceSyncTest, DestructionDeletesImpl)
+{
+ MockFenceSyncImpl* impl = new MockFenceSyncImpl;
+ EXPECT_CALL(*impl, destroy()).Times(1).RetiresOnSaturation();
+
+ gl::FenceSync* fence = new gl::FenceSync(impl, 1);
+ fence->addRef();
+ fence->release();
+
+ // Only needed because the mock is leaked if bugs are present,
+ // which logs an error, but does not cause the test to fail.
+ // Ordinarily mocks are verified when destroyed.
+ testing::Mock::VerifyAndClear(impl);
+}
+
+TEST_F(FenceSyncTest, SetAndGetStatusBehavior)
+{
+ EXPECT_CALL(*mImpl, set(_, _))
+ .WillOnce(Return(gl::Error(GL_NO_ERROR)))
+ .RetiresOnSaturation();
+ mFence->set(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ EXPECT_EQ(static_cast<GLenum>(GL_SYNC_GPU_COMMANDS_COMPLETE), mFence->getCondition());
+ // Fake the behavior of testing the fence before and after it's passed.
+ EXPECT_CALL(*mImpl, getStatus(_))
+ .WillOnce(DoAll(SetArgumentPointee<0>(GL_UNSIGNALED),
+ Return(gl::Error(GL_NO_ERROR))))
+ .WillOnce(DoAll(SetArgumentPointee<0>(GL_SIGNALED),
+ Return(gl::Error(GL_NO_ERROR))))
+ .RetiresOnSaturation();
+ GLint out;
+ mFence->getStatus(&out);
+ EXPECT_EQ(GL_UNSIGNALED, out);
+ mFence->getStatus(&out);
+ EXPECT_EQ(GL_SIGNALED, out);
+}
+
+} // namespace
diff --git a/gfx/angle/src/libANGLE/Framebuffer.cpp b/gfx/angle/src/libANGLE/Framebuffer.cpp
new file mode 100755
index 000000000..4bb213854
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Framebuffer.cpp
@@ -0,0 +1,938 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/utilities.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.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
+{
+
+void BindResourceChannel(ChannelBinding *binding, FramebufferAttachmentObject *resource)
+{
+ binding->bind(resource ? resource->getDirtyChannel() : nullptr);
+}
+
+} // anonymous namespace
+
+FramebufferState::FramebufferState()
+ : mLabel(),
+ mColorAttachments(1),
+ mDrawBufferStates(1, GL_NONE),
+ mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
+{
+ mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
+}
+
+FramebufferState::FramebufferState(const Caps &caps)
+ : mLabel(),
+ mColorAttachments(caps.maxColorAttachments),
+ mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
+ mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
+{
+ ASSERT(mDrawBufferStates.size() > 0);
+ mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
+}
+
+FramebufferState::~FramebufferState()
+{
+}
+
+const std::string &FramebufferState::getLabel()
+{
+ return mLabel;
+}
+
+const FramebufferAttachment *FramebufferState::getAttachment(GLenum attachment) const
+{
+ if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
+ {
+ return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
+ }
+
+ switch (attachment)
+ {
+ case GL_COLOR:
+ case GL_BACK:
+ return getColorAttachment(0);
+ case GL_DEPTH:
+ case GL_DEPTH_ATTACHMENT:
+ return getDepthAttachment();
+ case GL_STENCIL:
+ case GL_STENCIL_ATTACHMENT:
+ return getStencilAttachment();
+ case GL_DEPTH_STENCIL:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ return getDepthStencilAttachment();
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+const FramebufferAttachment *FramebufferState::getReadAttachment() const
+{
+ ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
+ size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
+ ASSERT(readIndex < mColorAttachments.size());
+ return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
+}
+
+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::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::getStencilAttachment() const
+{
+ return mStencilAttachment.isAttached() ? &mStencilAttachment : 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.type() == mStencilAttachment.type() &&
+ mDepthAttachment.id() == mStencilAttachment.id())
+ {
+ return &mDepthAttachment;
+ }
+
+ return nullptr;
+}
+
+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;
+ }
+
+ return (attachment.getSize() != attachmentSize.value());
+ };
+
+ for (const auto &attachment : mColorAttachments)
+ {
+ if (hasMismatchedSize(attachment))
+ {
+ return false;
+ }
+ }
+
+ if (hasMismatchedSize(mDepthAttachment))
+ {
+ return false;
+ }
+
+ return !hasMismatchedSize(mStencilAttachment);
+}
+
+const gl::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));
+ return getAttachment(mDrawBufferStates[drawBufferIdx]);
+ }
+ 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 gl::FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
+ if (!firstAttachment.isAttached())
+ {
+ continue;
+ }
+
+ for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
+ secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
+ {
+ const gl::FramebufferAttachment &secondAttachment =
+ mColorAttachments[secondAttachmentIdx];
+ if (!secondAttachment.isAttached())
+ {
+ continue;
+ }
+
+ if (firstAttachment == secondAttachment)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
+ : mState(caps),
+ mImpl(factory->createFramebuffer(mState)),
+ mId(id),
+ mCachedStatus(),
+ mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
+ mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
+{
+ ASSERT(mId != 0);
+ ASSERT(mImpl != nullptr);
+ ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
+
+ for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
+ {
+ mDirtyColorAttachmentBindings.push_back(ChannelBinding(
+ this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex)));
+ }
+}
+
+Framebuffer::Framebuffer(rx::SurfaceImpl *surface)
+ : mState(),
+ mImpl(surface->createDefaultFramebuffer(mState)),
+ mId(0),
+ mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
+ mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
+ mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
+{
+ ASSERT(mImpl != nullptr);
+ mDirtyColorAttachmentBindings.push_back(
+ ChannelBinding(this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0)));
+}
+
+Framebuffer::~Framebuffer()
+{
+ SafeDelete(mImpl);
+}
+
+void Framebuffer::setLabel(const std::string &label)
+{
+ mState.mLabel = label;
+}
+
+const std::string &Framebuffer::getLabel() const
+{
+ return mState.mLabel;
+}
+
+void Framebuffer::detachTexture(GLuint textureId)
+{
+ detachResourceById(GL_TEXTURE, textureId);
+}
+
+void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
+{
+ detachResourceById(GL_RENDERBUFFER, renderbufferId);
+}
+
+void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
+{
+ for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
+ {
+ detachMatchingAttachment(&mState.mColorAttachments[colorIndex], resourceType, resourceId,
+ DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
+ }
+
+ detachMatchingAttachment(&mState.mDepthAttachment, resourceType, resourceId,
+ DIRTY_BIT_DEPTH_ATTACHMENT);
+ detachMatchingAttachment(&mState.mStencilAttachment, resourceType, resourceId,
+ DIRTY_BIT_STENCIL_ATTACHMENT);
+}
+
+void Framebuffer::detachMatchingAttachment(FramebufferAttachment *attachment,
+ GLenum matchType,
+ GLuint matchId,
+ size_t dirtyBit)
+{
+ if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
+ {
+ attachment->detach();
+ mDirtyBits.set(dirtyBit);
+ }
+}
+
+const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
+{
+ return mState.getColorAttachment(colorAttachment);
+}
+
+const FramebufferAttachment *Framebuffer::getDepthbuffer() const
+{
+ return mState.getDepthAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getStencilbuffer() const
+{
+ return mState.getStencilAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
+{
+ return mState.getDepthStencilAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
+{
+ return mState.getDepthOrStencilAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
+{
+ return mState.getReadAttachment();
+}
+
+GLenum Framebuffer::getReadColorbufferType() const
+{
+ const FramebufferAttachment *readAttachment = mState.getReadAttachment();
+ return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
+}
+
+const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
+{
+ return mState.getFirstColorAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
+{
+ return mState.getAttachment(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 std::vector<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);
+}
+
+const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
+{
+ return mState.getDrawBuffer(drawBuffer);
+}
+
+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()));
+ mState.mReadBufferState = buffer;
+ mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
+}
+
+size_t Framebuffer::getNumColorBuffers() const
+{
+ return mState.mColorAttachments.size();
+}
+
+bool Framebuffer::hasDepth() const
+{
+ return (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.getDepthSize() > 0);
+}
+
+bool Framebuffer::hasStencil() const
+{
+ return (mState.mStencilAttachment.isAttached() &&
+ mState.mStencilAttachment.getStencilSize() > 0);
+}
+
+bool Framebuffer::usingExtendedDrawBuffers() const
+{
+ for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
+ {
+ if (getDrawBuffer(drawbufferIdx) != nullptr)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+GLenum Framebuffer::checkStatus(const ContextState &state)
+{
+ // The default framebuffer *must* always be complete, though it may not be
+ // subject to the same rules as application FBOs. ie, it could have 0x0 size.
+ if (mId == 0)
+ {
+ return GL_FRAMEBUFFER_COMPLETE;
+ }
+
+ if (hasAnyDirtyBit() || !mCachedStatus.valid())
+ {
+ mCachedStatus = checkStatusImpl(state);
+ }
+
+ return mCachedStatus.value();
+}
+
+GLenum Framebuffer::checkStatusImpl(const ContextState &state)
+{
+ ASSERT(mId != 0);
+
+ unsigned int colorbufferSize = 0;
+ int samples = -1;
+ bool missingAttachment = true;
+
+ for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
+ {
+ if (colorAttachment.isAttached())
+ {
+ const Extents &size = colorAttachment.getSize();
+ if (size.width == 0 || size.height == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ const Format &format = colorAttachment.getFormat();
+ const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
+ if (colorAttachment.type() == GL_TEXTURE)
+ {
+ if (!formatCaps.renderable)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ if (format.info->depthBits > 0 || format.info->stencilBits > 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ if (colorAttachment.layer() >= size.depth)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ // 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 = colorAttachment.getTexture();
+ ASSERT(texture);
+ if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
+ !texture->getTextureState().isCubeComplete())
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+ }
+ else if (colorAttachment.type() == GL_RENDERBUFFER)
+ {
+ if (!formatCaps.renderable || format.info->depthBits > 0 ||
+ format.info->stencilBits > 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+ }
+
+ if (!missingAttachment)
+ {
+ // 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.
+ if (colorAttachment.getSamples() != samples)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
+ }
+
+ // 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 (format.info->pixelBytes != colorbufferSize)
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+ }
+ }
+ else
+ {
+ samples = colorAttachment.getSamples();
+ colorbufferSize = format.info->pixelBytes;
+ missingAttachment = false;
+ }
+ }
+ }
+
+ const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
+ if (depthAttachment.isAttached())
+ {
+ const Extents &size = depthAttachment.getSize();
+ if (size.width == 0 || size.height == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ const Format &format = depthAttachment.getFormat();
+ const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
+ if (depthAttachment.type() == GL_TEXTURE)
+ {
+ // depth texture attachments require OES/ANGLE_depth_texture
+ if (!state.getExtensions().depthTextures)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ if (!formatCaps.renderable)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ if (format.info->depthBits == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+ }
+ else if (depthAttachment.type() == GL_RENDERBUFFER)
+ {
+ if (!formatCaps.renderable || format.info->depthBits == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+ }
+
+ if (missingAttachment)
+ {
+ samples = depthAttachment.getSamples();
+ missingAttachment = false;
+ }
+ else if (samples != depthAttachment.getSamples())
+ {
+ // 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.
+ const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
+ if (!mixedSamples)
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+
+ const int colorSamples = samples ? samples : 1;
+ const int depthSamples = depthAttachment.getSamples();
+ if ((depthSamples % colorSamples) != 0)
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+ }
+ }
+
+ const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
+ if (stencilAttachment.isAttached())
+ {
+ const Extents &size = stencilAttachment.getSize();
+ if (size.width == 0 || size.height == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ const Format &format = stencilAttachment.getFormat();
+ const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
+ if (stencilAttachment.type() == GL_TEXTURE)
+ {
+ // texture stencil attachments come along as part
+ // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
+ if (!state.getExtensions().depthTextures)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ if (!formatCaps.renderable)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ if (format.info->stencilBits == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+ }
+ else if (stencilAttachment.type() == GL_RENDERBUFFER)
+ {
+ if (!formatCaps.renderable || format.info->stencilBits == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+ }
+
+ if (missingAttachment)
+ {
+ samples = stencilAttachment.getSamples();
+ missingAttachment = false;
+ }
+ else if (samples != stencilAttachment.getSamples())
+ {
+ // see the comments in depth attachment check.
+ const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
+ if (!mixedSamples)
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+
+ const int colorSamples = samples ? samples : 1;
+ const int stencilSamples = stencilAttachment.getSamples();
+ if ((stencilSamples % colorSamples) != 0)
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+ }
+
+ // Starting from ES 3.0 stencil and depth, if present, should be the same image
+ if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
+ stencilAttachment != depthAttachment)
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+ }
+
+ // we need to have at least one attachment to be complete
+ if (missingAttachment)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+ }
+
+ // In ES 2.0, all color attachments must have the same width and height.
+ // In ES 3.0, there is no such restriction.
+ if (state.getClientMajorVersion() < 3 && !mState.attachmentsHaveSameDimensions())
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
+
+ syncState();
+ if (!mImpl->checkStatus())
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+
+ return GL_FRAMEBUFFER_COMPLETE;
+}
+
+Error Framebuffer::discard(size_t count, const GLenum *attachments)
+{
+ return mImpl->discard(count, attachments);
+}
+
+Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
+{
+ return mImpl->invalidate(count, attachments);
+}
+
+Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
+{
+ return mImpl->invalidateSub(count, attachments, area);
+}
+
+Error Framebuffer::clear(rx::ContextImpl *context, GLbitfield mask)
+{
+ if (context->getGLState().isRasterizerDiscardEnabled())
+ {
+ return gl::NoError();
+ }
+
+ return mImpl->clear(context, mask);
+}
+
+Error Framebuffer::clearBufferfv(rx::ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values)
+{
+ if (context->getGLState().isRasterizerDiscardEnabled())
+ {
+ return gl::NoError();
+ }
+
+ return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
+}
+
+Error Framebuffer::clearBufferuiv(rx::ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values)
+{
+ if (context->getGLState().isRasterizerDiscardEnabled())
+ {
+ return gl::NoError();
+ }
+
+ return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
+}
+
+Error Framebuffer::clearBufferiv(rx::ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values)
+{
+ if (context->getGLState().isRasterizerDiscardEnabled())
+ {
+ return gl::NoError();
+ }
+
+ return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
+}
+
+Error Framebuffer::clearBufferfi(rx::ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
+{
+ if (context->getGLState().isRasterizerDiscardEnabled())
+ {
+ return gl::NoError();
+ }
+
+ return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
+}
+
+GLenum Framebuffer::getImplementationColorReadFormat() const
+{
+ return mImpl->getImplementationColorReadFormat();
+}
+
+GLenum Framebuffer::getImplementationColorReadType() const
+{
+ return mImpl->getImplementationColorReadType();
+}
+
+Error Framebuffer::readPixels(rx::ContextImpl *context,
+ const Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels) const
+{
+ ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
+
+ Buffer *unpackBuffer = context->getGLState().getUnpackState().pixelBuffer.get();
+ if (unpackBuffer)
+ {
+ unpackBuffer->onPixelUnpack();
+ }
+
+ return NoError();
+}
+
+Error Framebuffer::blit(rx::ContextImpl *context,
+ const Rectangle &sourceArea,
+ const Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter)
+{
+ return mImpl->blit(context, sourceArea, destArea, mask, filter);
+}
+
+int Framebuffer::getSamples(const ContextState &state)
+{
+ if (complete(state))
+ {
+ // For a complete framebuffer, all attachments must have the same sample count.
+ // In this case return the first nonzero sample size.
+ const auto *firstColorAttachment = mState.getFirstColorAttachment();
+ if (firstColorAttachment)
+ {
+ ASSERT(firstColorAttachment->isAttached());
+ return firstColorAttachment->getSamples();
+ }
+ }
+
+ return 0;
+}
+
+bool Framebuffer::hasValidDepthStencil() const
+{
+ return mState.getDepthStencilAttachment() != nullptr;
+}
+
+void Framebuffer::setAttachment(GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource)
+{
+ if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
+ {
+ // ensure this is a legitimate depth+stencil format
+ FramebufferAttachmentObject *attachmentObj = resource;
+ if (resource)
+ {
+ FramebufferAttachment::Target target(binding, textureIndex);
+ const Format &format = resource->getAttachmentFormat(target);
+ if (format.info->depthBits == 0 || format.info->stencilBits == 0)
+ {
+ // Attaching nullptr detaches the current attachment.
+ attachmentObj = nullptr;
+ }
+ }
+
+ mState.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
+ mState.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
+ mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
+ BindResourceChannel(&mDirtyDepthAttachmentBinding, resource);
+ BindResourceChannel(&mDirtyStencilAttachmentBinding, resource);
+ }
+ else
+ {
+ switch (binding)
+ {
+ case GL_DEPTH:
+ case GL_DEPTH_ATTACHMENT:
+ mState.mDepthAttachment.attach(type, binding, textureIndex, resource);
+ mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
+ BindResourceChannel(&mDirtyDepthAttachmentBinding, resource);
+ break;
+ case GL_STENCIL:
+ case GL_STENCIL_ATTACHMENT:
+ mState.mStencilAttachment.attach(type, binding, textureIndex, resource);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
+ BindResourceChannel(&mDirtyStencilAttachmentBinding, resource);
+ break;
+ case GL_BACK:
+ mState.mColorAttachments[0].attach(type, binding, textureIndex, resource);
+ mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
+ // No need for a resource binding for the default FBO, it's always complete.
+ break;
+ default:
+ {
+ size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
+ ASSERT(colorIndex < mState.mColorAttachments.size());
+ mState.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
+ mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
+ BindResourceChannel(&mDirtyColorAttachmentBindings[colorIndex], resource);
+ }
+ break;
+ }
+ }
+}
+
+void Framebuffer::resetAttachment(GLenum binding)
+{
+ setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
+}
+
+void Framebuffer::syncState()
+{
+ if (mDirtyBits.any())
+ {
+ mImpl->syncState(mDirtyBits);
+ mDirtyBits.reset();
+ mCachedStatus.reset();
+ }
+}
+
+void Framebuffer::signal(SignalToken token)
+{
+ // TOOD(jmadill): Make this only update individual attachments to do less work.
+ mCachedStatus.reset();
+}
+
+bool Framebuffer::complete(const ContextState &state)
+{
+ return (checkStatus(state) == GL_FRAMEBUFFER_COMPLETE);
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/Framebuffer.h b/gfx/angle/src/libANGLE/Framebuffer.h
new file mode 100755
index 000000000..db0d6215f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Framebuffer.h
@@ -0,0 +1,235 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/Optional.h"
+#include "common/angleutils.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/signal_utils.h"
+
+namespace rx
+{
+class ContextImpl;
+class GLImplFactory;
+class FramebufferImpl;
+class RenderbufferImpl;
+class SurfaceImpl;
+}
+
+namespace egl
+{
+class Surface;
+}
+
+namespace gl
+{
+class Context;
+class Framebuffer;
+class Renderbuffer;
+class State;
+class Texture;
+class TextureCapsMap;
+struct Caps;
+class ContextState;
+struct Extensions;
+struct ImageIndex;
+struct Rectangle;
+
+class FramebufferState final : angle::NonCopyable
+{
+ public:
+ FramebufferState();
+ explicit FramebufferState(const Caps &caps);
+ ~FramebufferState();
+
+ const std::string &getLabel();
+
+ const FramebufferAttachment *getAttachment(GLenum attachment) const;
+ const FramebufferAttachment *getReadAttachment() const;
+ const FramebufferAttachment *getFirstColorAttachment() const;
+ const FramebufferAttachment *getDepthOrStencilAttachment() const;
+ const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
+ const FramebufferAttachment *getDepthAttachment() const;
+ const FramebufferAttachment *getStencilAttachment() const;
+ const FramebufferAttachment *getDepthStencilAttachment() const;
+
+ const std::vector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; }
+ GLenum getReadBufferState() const { return mReadBufferState; }
+ const std::vector<FramebufferAttachment> &getColorAttachments() const
+ {
+ return mColorAttachments;
+ }
+
+ bool attachmentsHaveSameDimensions() const;
+ bool colorAttachmentsAreUniqueImages() const;
+
+ const FramebufferAttachment *getDrawBuffer(size_t drawBufferIdx) const;
+ size_t getDrawBufferCount() const;
+
+ private:
+ friend class Framebuffer;
+
+ std::string mLabel;
+
+ std::vector<FramebufferAttachment> mColorAttachments;
+ FramebufferAttachment mDepthAttachment;
+ FramebufferAttachment mStencilAttachment;
+
+ std::vector<GLenum> mDrawBufferStates;
+ GLenum mReadBufferState;
+};
+
+class Framebuffer final : public LabeledObject, public angle::SignalReceiver
+{
+ public:
+ Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id);
+ Framebuffer(rx::SurfaceImpl *surface);
+ virtual ~Framebuffer();
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ rx::FramebufferImpl *getImplementation() const { return mImpl; }
+
+ GLuint id() const { return mId; }
+
+ void setAttachment(GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource);
+ void resetAttachment(GLenum binding);
+
+ void detachTexture(GLuint texture);
+ void detachRenderbuffer(GLuint renderbuffer);
+
+ const FramebufferAttachment *getColorbuffer(size_t colorAttachment) const;
+ const FramebufferAttachment *getDepthbuffer() const;
+ const FramebufferAttachment *getStencilbuffer() const;
+ const FramebufferAttachment *getDepthStencilBuffer() const;
+ const FramebufferAttachment *getDepthOrStencilbuffer() const;
+ const FramebufferAttachment *getReadColorbuffer() const;
+ GLenum getReadColorbufferType() const;
+ const FramebufferAttachment *getFirstColorbuffer() const;
+
+ const FramebufferAttachment *getAttachment(GLenum attachment) const;
+
+ size_t getDrawbufferStateCount() const;
+ GLenum getDrawBufferState(size_t drawBuffer) const;
+ const std::vector<GLenum> &getDrawBufferStates() const;
+ void setDrawBuffers(size_t count, const GLenum *buffers);
+ const FramebufferAttachment *getDrawBuffer(size_t drawBuffer) const;
+ bool hasEnabledDrawBuffer() const;
+
+ GLenum getReadBufferState() const;
+ void setReadBuffer(GLenum buffer);
+
+ size_t getNumColorBuffers() const;
+ bool hasDepth() const;
+ bool hasStencil() const;
+
+ bool usingExtendedDrawBuffers() const;
+
+ // This method calls checkStatus.
+ int getSamples(const ContextState &state);
+ GLenum checkStatus(const ContextState &state);
+
+ // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE.
+ bool complete(const ContextState &state);
+
+ bool hasValidDepthStencil() const;
+
+ Error discard(size_t count, const GLenum *attachments);
+ Error invalidate(size_t count, const GLenum *attachments);
+ Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area);
+
+ Error clear(rx::ContextImpl *context, GLbitfield mask);
+ Error clearBufferfv(rx::ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values);
+ Error clearBufferuiv(rx::ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values);
+ Error clearBufferiv(rx::ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values);
+ Error clearBufferfi(rx::ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil);
+
+ GLenum getImplementationColorReadFormat() const;
+ GLenum getImplementationColorReadType() const;
+ Error readPixels(rx::ContextImpl *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels) const;
+
+ Error blit(rx::ContextImpl *context,
+ const Rectangle &sourceArea,
+ const Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter);
+
+ enum DirtyBitType
+ {
+ DIRTY_BIT_COLOR_ATTACHMENT_0,
+ DIRTY_BIT_COLOR_ATTACHMENT_MAX =
+ DIRTY_BIT_COLOR_ATTACHMENT_0 + gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS,
+ DIRTY_BIT_DEPTH_ATTACHMENT = DIRTY_BIT_COLOR_ATTACHMENT_MAX,
+ DIRTY_BIT_STENCIL_ATTACHMENT,
+ DIRTY_BIT_DRAW_BUFFERS,
+ DIRTY_BIT_READ_BUFFER,
+ DIRTY_BIT_UNKNOWN,
+ DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN,
+ };
+
+ typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
+ bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
+ void syncState();
+
+ // angle::SignalReceiver implementation
+ void signal(angle::SignalToken token) override;
+
+ private:
+ void detachResourceById(GLenum resourceType, GLuint resourceId);
+ void detachMatchingAttachment(FramebufferAttachment *attachment,
+ GLenum matchType,
+ GLuint matchId,
+ size_t dirtyBit);
+ GLenum checkStatusImpl(const ContextState &state);
+
+ FramebufferState mState;
+ rx::FramebufferImpl *mImpl;
+ GLuint mId;
+
+ Optional<GLenum> mCachedStatus;
+ std::vector<angle::ChannelBinding> mDirtyColorAttachmentBindings;
+ angle::ChannelBinding mDirtyDepthAttachmentBinding;
+ angle::ChannelBinding mDirtyStencilAttachmentBinding;
+
+ DirtyBits mDirtyBits;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_FRAMEBUFFER_H_
diff --git a/gfx/angle/src/libANGLE/FramebufferAttachment.cpp b/gfx/angle/src/libANGLE/FramebufferAttachment.cpp
new file mode 100755
index 000000000..37af254f2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/FramebufferAttachment.cpp
@@ -0,0 +1,241 @@
+//
+// Copyright (c) 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/Renderbuffer.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/FramebufferImpl.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace gl
+{
+
+////// FramebufferAttachment::Target Implementation //////
+
+FramebufferAttachment::Target::Target()
+ : mBinding(GL_NONE),
+ mTextureIndex(ImageIndex::MakeInvalid())
+{
+}
+
+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)
+{
+}
+
+FramebufferAttachment::FramebufferAttachment(GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource)
+ : mResource(nullptr)
+{
+ attach(type, binding, textureIndex, resource);
+}
+
+FramebufferAttachment::FramebufferAttachment(const FramebufferAttachment &other)
+ : mResource(nullptr)
+{
+ attach(other.mType, other.mTarget.binding(), other.mTarget.textureIndex(), other.mResource);
+}
+
+FramebufferAttachment &FramebufferAttachment::operator=(const FramebufferAttachment &other)
+{
+ attach(other.mType, other.mTarget.binding(), other.mTarget.textureIndex(), other.mResource);
+ return *this;
+}
+
+FramebufferAttachment::~FramebufferAttachment()
+{
+ detach();
+}
+
+void FramebufferAttachment::detach()
+{
+ mType = GL_NONE;
+ if (mResource != nullptr)
+ {
+ mResource->onDetach();
+ mResource = nullptr;
+ }
+
+ // not technically necessary, could omit for performance
+ mTarget = Target();
+}
+
+void FramebufferAttachment::attach(GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource)
+{
+ mType = type;
+ mTarget = Target(binding, textureIndex);
+
+ if (resource)
+ {
+ resource->onAttach();
+ }
+ if (mResource != nullptr)
+ {
+ mResource->onDetach();
+ }
+ mResource = resource;
+}
+
+GLuint FramebufferAttachment::getRedSize() const
+{
+ return getFormat().info->redBits;
+}
+
+GLuint FramebufferAttachment::getGreenSize() const
+{
+ return getFormat().info->greenBits;
+}
+
+GLuint FramebufferAttachment::getBlueSize() const
+{
+ return getFormat().info->blueBits;
+}
+
+GLuint FramebufferAttachment::getAlphaSize() const
+{
+ return getFormat().info->alphaBits;
+}
+
+GLuint FramebufferAttachment::getDepthSize() const
+{
+ return getFormat().info->depthBits;
+}
+
+GLuint FramebufferAttachment::getStencilSize() const
+{
+ return 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();
+}
+
+const ImageIndex &FramebufferAttachment::getTextureImageIndex() const
+{
+ ASSERT(type() == GL_TEXTURE);
+ return mTarget.textureIndex();
+}
+
+GLenum FramebufferAttachment::cubeMapFace() const
+{
+ ASSERT(mType == GL_TEXTURE);
+
+ const auto &index = mTarget.textureIndex();
+ return IsCubeMapTextureTarget(index.type) ? index.type : GL_NONE;
+}
+
+GLint FramebufferAttachment::mipLevel() const
+{
+ ASSERT(type() == GL_TEXTURE);
+ return mTarget.textureIndex().mipIndex;
+}
+
+GLint FramebufferAttachment::layer() const
+{
+ ASSERT(mType == GL_TEXTURE);
+
+ const auto &index = mTarget.textureIndex();
+
+ if (index.type == GL_TEXTURE_2D_ARRAY || index.type == GL_TEXTURE_3D)
+ {
+ return index.layerIndex;
+ }
+ return 0;
+}
+
+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);
+}
+
+bool FramebufferAttachment::operator==(const FramebufferAttachment &other) const
+{
+ if (mResource != other.mResource || mType != other.mType)
+ {
+ return false;
+ }
+
+ if (mType == GL_TEXTURE && getTextureImageIndex() != other.getTextureImageIndex())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool FramebufferAttachment::operator!=(const FramebufferAttachment &other) const
+{
+ return !(*this == other);
+}
+
+Error FramebufferAttachmentObject::getAttachmentRenderTarget(
+ const FramebufferAttachment::Target &target,
+ rx::FramebufferAttachmentRenderTarget **rtOut) const
+{
+ return getAttachmentImpl()->getAttachmentRenderTarget(target, rtOut);
+}
+
+angle::BroadcastChannel *FramebufferAttachmentObject::getDirtyChannel()
+{
+ return &mDirtyChannel;
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/FramebufferAttachment.h b/gfx/angle/src/libANGLE/FramebufferAttachment.h
new file mode 100755
index 000000000..41502737d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/FramebufferAttachment.h
@@ -0,0 +1,201 @@
+//
+// Copyright (c) 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/angletypes.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/signal_utils.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 gl
+{
+class FramebufferAttachmentObject;
+struct Format;
+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(GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource);
+
+ FramebufferAttachment(const FramebufferAttachment &other);
+ FramebufferAttachment &operator=(const FramebufferAttachment &other);
+
+ ~FramebufferAttachment();
+
+ // 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;
+ };
+
+ void detach();
+ void attach(GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource);
+
+ // 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(GLuint textureId) const { return mType == GL_TEXTURE && id() == textureId; }
+ 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;
+ GLenum cubeMapFace() const;
+ GLint mipLevel() const;
+ GLint layer() 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;
+ const Format &getFormat() const;
+ GLsizei getSamples() const;
+ GLenum type() const { return mType; }
+ bool isAttached() const { return mType != GL_NONE; }
+
+ Renderbuffer *getRenderbuffer() const;
+ Texture *getTexture() const;
+ const egl::Surface *getSurface() const;
+
+ // "T" must be static_castable from FramebufferAttachmentRenderTarget
+ template <typename T>
+ gl::Error getRenderTarget(T **rtOut) const
+ {
+ // Cast through the pointer-to-pointer type
+ rx::FramebufferAttachmentRenderTarget *rtPtr = nullptr;
+ gl::Error error = getRenderTarget(&rtPtr);
+ *rtOut = static_cast<T*>(rtPtr);
+ return error;
+ }
+
+ bool operator==(const FramebufferAttachment &other) const;
+ bool operator!=(const FramebufferAttachment &other) const;
+
+ private:
+ gl::Error getRenderTarget(rx::FramebufferAttachmentRenderTarget **rtOut) const;
+
+ GLenum mType;
+ Target mTarget;
+ FramebufferAttachmentObject *mResource;
+};
+
+// A base class for objects that FBO Attachments may point to.
+class FramebufferAttachmentObject
+{
+ public:
+ FramebufferAttachmentObject() {}
+ virtual ~FramebufferAttachmentObject() {}
+
+ virtual Extents getAttachmentSize(const FramebufferAttachment::Target &target) const = 0;
+ virtual const Format &getAttachmentFormat(
+ const FramebufferAttachment::Target &target) const = 0;
+ virtual GLsizei getAttachmentSamples(const FramebufferAttachment::Target &target) const = 0;
+
+ virtual void onAttach() = 0;
+ virtual void onDetach() = 0;
+ virtual GLuint getId() const = 0;
+
+ Error getAttachmentRenderTarget(const FramebufferAttachment::Target &target,
+ rx::FramebufferAttachmentRenderTarget **rtOut) const;
+
+ angle::BroadcastChannel *getDirtyChannel();
+
+ protected:
+ virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0;
+
+ angle::BroadcastChannel mDirtyChannel;
+};
+
+inline Extents FramebufferAttachment::getSize() const
+{
+ return mResource->getAttachmentSize(mTarget);
+}
+
+inline const Format &FramebufferAttachment::getFormat() const
+{
+ return mResource->getAttachmentFormat(mTarget);
+}
+
+inline GLsizei FramebufferAttachment::getSamples() const
+{
+ return mResource->getAttachmentSamples(mTarget);
+}
+
+inline gl::Error FramebufferAttachment::getRenderTarget(rx::FramebufferAttachmentRenderTarget **rtOut) const
+{
+ return mResource->getAttachmentRenderTarget(mTarget, rtOut);
+}
+
+} // namespace gl
+
+#endif // LIBANGLE_FRAMEBUFFERATTACHMENT_H_
diff --git a/gfx/angle/src/libANGLE/HandleAllocator.cpp b/gfx/angle/src/libANGLE/HandleAllocator.cpp
new file mode 100755
index 000000000..c090b3dfc
--- /dev/null
+++ b/gfx/angle/src/libANGLE/HandleAllocator.cpp
@@ -0,0 +1,131 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project 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 "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)
+{
+ mUnallocatedList.push_back(HandleRange(1, std::numeric_limits<GLuint>::max()));
+}
+
+HandleAllocator::HandleAllocator(GLuint maximumHandleValue) : mBaseValue(1), mNextValue(1)
+{
+ 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, constant time.
+ if (!mReleasedList.empty())
+ {
+ GLuint reusedHandle = mReleasedList.back();
+ mReleasedList.pop_back();
+ 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++;
+ }
+
+ return freeListHandle;
+}
+
+void HandleAllocator::release(GLuint handle)
+{
+ // Add to released list, constant time.
+ mReleasedList.push_back(handle);
+}
+
+void HandleAllocator::reserve(GLuint handle)
+{
+ // 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);
+ 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));
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/HandleAllocator.h b/gfx/angle/src/libANGLE/HandleAllocator.h
new file mode 100755
index 000000000..c7e0a0d85
--- /dev/null
+++ b/gfx/angle/src/libANGLE/HandleAllocator.h
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project 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"
+
+#include <stack>
+
+namespace gl
+{
+
+class HandleAllocator final : angle::NonCopyable
+{
+ public:
+ // Maximum handle = MAX_UINT-1
+ HandleAllocator();
+ // Specify maximum handle value
+ HandleAllocator(GLuint maximumHandleValue);
+
+ ~HandleAllocator();
+
+ void setBaseHandle(GLuint value);
+
+ GLuint allocate();
+ void release(GLuint handle);
+ void reserve(GLuint handle);
+
+ private:
+ GLuint mBaseValue;
+ GLuint mNextValue;
+ typedef std::vector<GLuint> HandleList;
+ HandleList mFreeValues;
+
+ // 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 stack.
+ std::vector<HandleRange> mUnallocatedList;
+ std::vector<GLuint> mReleasedList;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_HANDLEALLOCATOR_H_
diff --git a/gfx/angle/src/libANGLE/HandleAllocator_unittest.cpp b/gfx/angle/src/libANGLE/HandleAllocator_unittest.cpp
new file mode 100755
index 000000000..bfcbd8f01
--- /dev/null
+++ b/gfx/angle/src/libANGLE/HandleAllocator_unittest.cpp
@@ -0,0 +1,138 @@
+//
+// 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.
+//
+// Unit tests for HandleAllocator.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "libANGLE/HandleAllocator.h"
+
+namespace
+{
+
+TEST(HandleAllocatorTest, ReservationsWithGaps)
+{
+ gl::HandleAllocator allocator;
+
+ std::set<GLuint> allocationList;
+ for (GLuint id = 2; id < 50; id += 2)
+ {
+ allocationList.insert(id);
+ }
+
+ for (GLuint id : allocationList)
+ {
+ allocator.reserve(id);
+ }
+
+ std::set<GLuint> allocatedList;
+ for (size_t allocationNum = 0; allocationNum < allocationList.size() * 2; ++allocationNum)
+ {
+ GLuint handle = allocator.allocate();
+ EXPECT_EQ(0u, allocationList.count(handle));
+ EXPECT_EQ(0u, allocatedList.count(handle));
+ allocatedList.insert(handle);
+ }
+}
+
+TEST(HandleAllocatorTest, Random)
+{
+ gl::HandleAllocator allocator;
+
+ std::set<GLuint> allocationList;
+ for (size_t iterationCount = 0; iterationCount < 40; ++iterationCount)
+ {
+ for (size_t randomCount = 0; randomCount < 40; ++randomCount)
+ {
+ GLuint randomHandle = (rand() % 1000) + 1;
+ if (allocationList.count(randomHandle) == 0)
+ {
+ allocator.reserve(randomHandle);
+ allocationList.insert(randomHandle);
+ }
+ }
+
+ for (size_t normalCount = 0; normalCount < 40; ++normalCount)
+ {
+ GLuint normalHandle = allocator.allocate();
+ EXPECT_EQ(0u, allocationList.count(normalHandle));
+ allocationList.insert(normalHandle);
+ }
+ }
+}
+
+TEST(HandleAllocatorTest, Reallocation)
+{
+ // Note: no current test for overflow
+ gl::HandleAllocator limitedAllocator(10);
+
+ for (GLuint count = 1; count < 10; count++)
+ {
+ GLuint result = limitedAllocator.allocate();
+ EXPECT_EQ(count, result);
+ }
+
+ for (GLuint count = 1; count < 10; count++)
+ {
+ limitedAllocator.release(count);
+ }
+
+ for (GLuint count = 2; count < 10; count++)
+ {
+ limitedAllocator.reserve(count);
+ }
+
+ GLint finalResult = limitedAllocator.allocate();
+ EXPECT_EQ(finalResult, 1);
+}
+
+// The following test covers reserving a handle with max uint value. See http://anglebug.com/1052
+TEST(HandleAllocatorTest, ReserveMaxUintHandle)
+{
+ gl::HandleAllocator allocator;
+
+ GLuint maxUintHandle = std::numeric_limits<GLuint>::max();
+ allocator.reserve(maxUintHandle);
+
+ GLuint normalHandle = allocator.allocate();
+ EXPECT_EQ(1u, normalHandle);
+}
+
+// The following test covers reserving a handle with max uint value minus one then max uint value.
+TEST(HandleAllocatorTest, ReserveMaxUintHandle2)
+{
+ gl::HandleAllocator allocator;
+
+ GLuint maxUintHandle = std::numeric_limits<GLuint>::max();
+ allocator.reserve(maxUintHandle - 1);
+ allocator.reserve(maxUintHandle);
+
+ GLuint normalHandle = allocator.allocate();
+ EXPECT_EQ(1u, normalHandle);
+}
+
+// To test if the allocator keep the handle in a sorted order.
+TEST(HandleAllocatorTest, SortedOrderHandle)
+{
+ gl::HandleAllocator allocator;
+
+ allocator.reserve(3);
+
+ GLuint allocatedList[5];
+ for (GLuint count = 0; count < 5; count++)
+ {
+ allocatedList[count] = allocator.allocate();
+ }
+
+ EXPECT_EQ(1u, allocatedList[0]);
+ EXPECT_EQ(2u, allocatedList[1]);
+ EXPECT_EQ(4u, allocatedList[2]);
+ EXPECT_EQ(5u, allocatedList[3]);
+ EXPECT_EQ(6u, allocatedList[4]);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/HandleRangeAllocator.cpp b/gfx/angle/src/libANGLE/HandleRangeAllocator.cpp
new file mode 100755
index 000000000..500a79629
--- /dev/null
+++ b/gfx/angle/src/libANGLE/HandleRangeAllocator.cpp
@@ -0,0 +1,225 @@
+//
+// Copyright (c) 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.
+//
+
+// HandleRangeAllocator.cpp : Implementation for HandleRangeAllocator.h
+
+#include "libANGLE/HandleRangeAllocator.h"
+
+#include <algorithm>
+#include <limits>
+#include <utility>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+const GLuint HandleRangeAllocator::kInvalidHandle = 0;
+
+HandleRangeAllocator::HandleRangeAllocator()
+{
+ // Simplify the code by making sure that lower_bound(id) never
+ // returns the beginning of the map, if id is valid (eg != kInvalidHandle).
+ mUsed.insert(std::make_pair(0u, 0u));
+}
+
+GLuint HandleRangeAllocator::allocate()
+{
+ return allocateRange(1u);
+}
+
+GLuint HandleRangeAllocator::allocateAtOrAbove(GLuint wanted)
+{
+ if (wanted == 0u || wanted == 1u)
+ return allocateRange(1u);
+
+ auto current = mUsed.lower_bound(wanted);
+ auto next = current;
+ if (current == mUsed.end() || current->first > wanted)
+ {
+ current--;
+ }
+ else
+ {
+ next++;
+ }
+
+ GLuint firstId = current->first;
+ GLuint lastId = current->second;
+ ASSERT(wanted >= firstId);
+
+ if (wanted - 1u <= lastId)
+ {
+ // Append to current range.
+ lastId++;
+ if (lastId == 0)
+ {
+ // The increment overflowed.
+ return allocateRange(1u);
+ }
+
+ current->second = lastId;
+
+ if (next != mUsed.end() && next->first - 1u == lastId)
+ {
+ // Merge with next range.
+ current->second = next->second;
+ mUsed.erase(next);
+ }
+ return lastId;
+ }
+ else if (next != mUsed.end() && next->first - 1u == wanted)
+ {
+ // Prepend to next range.
+ GLuint lastExisting = next->second;
+ mUsed.erase(next);
+ mUsed.insert(std::make_pair(wanted, lastExisting));
+ return wanted;
+ }
+ mUsed.insert(std::make_pair(wanted, wanted));
+ return wanted;
+}
+
+GLuint HandleRangeAllocator::allocateRange(GLuint range)
+{
+ ASSERT(range != 0);
+
+ auto current = mUsed.begin();
+ auto next = current;
+
+ while (++next != mUsed.end())
+ {
+ if (next->first - current->second > range)
+ break;
+ current = next;
+ }
+ const GLuint firstId = current->second + 1u;
+ const GLuint lastId = firstId + range - 1u;
+
+ // deal with wraparound
+ if (firstId == 0u || lastId < firstId)
+ return kInvalidHandle;
+
+ current->second = lastId;
+
+ if (next != mUsed.end() && next->first - 1u == lastId)
+ {
+ // merge with next range
+ current->second = next->second;
+ mUsed.erase(next);
+ }
+ return firstId;
+}
+
+bool HandleRangeAllocator::markAsUsed(GLuint handle)
+{
+ ASSERT(handle);
+ auto current = mUsed.lower_bound(handle);
+ if (current != mUsed.end() && current->first == handle)
+ return false;
+
+ auto next = current;
+ --current;
+
+ if (current->second >= handle)
+ return false;
+
+ ASSERT(current->first < handle && current->second < handle);
+
+ if (current->second + 1u == handle)
+ {
+ // Append to current range.
+ current->second = handle;
+ if (next != mUsed.end() && next->first - 1u == handle)
+ {
+ // Merge with next range.
+ current->second = next->second;
+ mUsed.erase(next);
+ }
+ return true;
+ }
+ else if (next != mUsed.end() && next->first - 1u == handle)
+ {
+ // Prepend to next range.
+ GLuint lastExisting = next->second;
+ mUsed.erase(next);
+ mUsed.insert(std::make_pair(handle, lastExisting));
+ return true;
+ }
+
+ mUsed.insert(std::make_pair(handle, handle));
+ return true;
+}
+
+void HandleRangeAllocator::release(GLuint handle)
+{
+ releaseRange(handle, 1u);
+}
+
+void HandleRangeAllocator::releaseRange(GLuint first, GLuint range)
+{
+ if (range == 0u || (first == 0u && range == 1u))
+ return;
+
+ if (first == 0u)
+ {
+ first++;
+ range--;
+ }
+
+ GLuint last = first + range - 1u;
+ if (last < first)
+ last = std::numeric_limits<GLuint>::max();
+
+ while (true)
+ {
+ auto current = mUsed.lower_bound(last);
+ if (current == mUsed.end() || current->first > last)
+ --current;
+
+ if (current->second < first)
+ return;
+
+ if (current->first >= first)
+ {
+ const GLuint lastExisting = current->second;
+ mUsed.erase(current);
+ if (last < lastExisting)
+ {
+ mUsed.insert(std::make_pair(last + 1u, lastExisting));
+ }
+ }
+ else if (current->second <= last)
+ {
+ current->second = first - 1u;
+ }
+ else
+ {
+ ASSERT(current->first < first && current->second > last);
+ const GLuint lastExisting = current->second;
+ current->second = first - 1u;
+ mUsed.insert(std::make_pair(last + 1u, lastExisting));
+ }
+ }
+}
+
+bool HandleRangeAllocator::isUsed(GLuint handle) const
+{
+ if (handle == kInvalidHandle)
+ return false;
+
+ auto current = mUsed.lower_bound(handle);
+ if (current != mUsed.end())
+ {
+ if (current->first == handle)
+ return true;
+ }
+ --current;
+ return current->second >= handle;
+}
+
+} // namespace gl \ No newline at end of file
diff --git a/gfx/angle/src/libANGLE/HandleRangeAllocator.h b/gfx/angle/src/libANGLE/HandleRangeAllocator.h
new file mode 100755
index 000000000..20f9a116b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/HandleRangeAllocator.h
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// HandleRangeAllocator.h: Defines the gl::HandleRangeAllocator class, which is used to
+// allocate contiguous ranges of GL path handles.
+
+#ifndef LIBANGLE_HANDLERANGEALLOCATOR_H_
+#define LIBANGLE_HANDLERANGEALLOCATOR_H_
+
+#include <map>
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+
+namespace gl
+{
+
+// Allocates contiguous ranges of path object handles.
+class HandleRangeAllocator final : angle::NonCopyable
+{
+ public:
+ static const GLuint kInvalidHandle;
+
+ HandleRangeAllocator();
+
+ // Allocates a new path handle.
+ GLuint allocate();
+
+ // Allocates a handle starting at or above the value of |wanted|.
+ // Note: may wrap if it starts near limit.
+ GLuint allocateAtOrAbove(GLuint wanted);
+
+ // Allocates |range| amount of contiguous paths.
+ // Returns the first id to |first_id| or |kInvalidHandle| if
+ // allocation failed.
+ GLuint allocateRange(GLuint range);
+
+ // Marks an id as used. Returns false if handle was already used.
+ bool markAsUsed(GLuint handle);
+
+ // Release handle.
+ void release(GLuint handle);
+
+ // Release a |range| amount of contiguous handles, starting from |first|
+ void releaseRange(GLuint first, GLuint range);
+
+ // Checks whether or not a resource ID is in use.
+ bool isUsed(GLuint handle) const;
+
+ private:
+ std::map<GLuint, GLuint> mUsed;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_HANDLERANGEALLOCATOR_H_ \ No newline at end of file
diff --git a/gfx/angle/src/libANGLE/HandleRangeAllocator_unittest.cpp b/gfx/angle/src/libANGLE/HandleRangeAllocator_unittest.cpp
new file mode 100755
index 000000000..1d825f710
--- /dev/null
+++ b/gfx/angle/src/libANGLE/HandleRangeAllocator_unittest.cpp
@@ -0,0 +1,275 @@
+//
+// 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.
+//
+// Unit tests for HandleRangeAllocator.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "libANGLE/HandleRangeAllocator.h"
+
+namespace
+{
+
+class HandleRangeAllocatorTest : public testing::Test
+{
+ protected:
+ gl::HandleRangeAllocator *getAllocator() { return &mAllocator; }
+
+ private:
+ gl::HandleRangeAllocator mAllocator;
+};
+
+// Checks basic functionality: allocate, release, isUsed.
+TEST_F(HandleRangeAllocatorTest, TestBasic)
+{
+ auto *allocator = getAllocator();
+ // Check that resource 1 is not in use
+ EXPECT_FALSE(allocator->isUsed(1));
+
+ // Allocate an ID, check that it's in use.
+ GLuint id1 = allocator->allocate();
+ EXPECT_TRUE(allocator->isUsed(id1));
+
+ // Allocate another ID, check that it's in use, and different from the first
+ // one.
+ GLuint id2 = allocator->allocate();
+ EXPECT_TRUE(allocator->isUsed(id2));
+ EXPECT_NE(id1, id2);
+
+ // Free one of the IDs, check that it's not in use any more.
+ allocator->release(id1);
+ EXPECT_FALSE(allocator->isUsed(id1));
+
+ // Frees the other ID, check that it's not in use any more.
+ allocator->release(id2);
+ EXPECT_FALSE(allocator->isUsed(id2));
+}
+
+// Checks that the resource handles are re-used after being freed.
+TEST_F(HandleRangeAllocatorTest, TestAdvanced)
+{
+ auto *allocator = getAllocator();
+
+ // Allocate the highest possible ID, to make life awkward.
+ allocator->allocateAtOrAbove(~static_cast<GLuint>(0));
+
+ // Allocate a significant number of resources.
+ const unsigned int kNumResources = 100;
+ GLuint ids[kNumResources];
+ for (unsigned int i = 0; i < kNumResources; ++i)
+ {
+ ids[i] = allocator->allocate();
+ EXPECT_TRUE(allocator->isUsed(ids[i]));
+ }
+
+ // Check that a new allocation re-uses the resource we just freed.
+ GLuint id1 = ids[kNumResources / 2];
+ allocator->release(id1);
+ EXPECT_FALSE(allocator->isUsed(id1));
+ GLuint id2 = allocator->allocate();
+ EXPECT_TRUE(allocator->isUsed(id2));
+ EXPECT_EQ(id1, id2);
+}
+
+// Checks that we can choose our own ids and they won't be reused.
+TEST_F(HandleRangeAllocatorTest, MarkAsUsed)
+{
+ auto *allocator = getAllocator();
+ GLuint id = allocator->allocate();
+ allocator->release(id);
+ EXPECT_FALSE(allocator->isUsed(id));
+ EXPECT_TRUE(allocator->markAsUsed(id));
+ EXPECT_TRUE(allocator->isUsed(id));
+ GLuint id2 = allocator->allocate();
+ EXPECT_NE(id, id2);
+ EXPECT_TRUE(allocator->markAsUsed(id2 + 1));
+ GLuint id3 = allocator->allocate();
+ // Checks our algorithm. If the algorithm changes this check should be
+ // changed.
+ EXPECT_EQ(id3, id2 + 2);
+}
+
+// Checks allocateAtOrAbove.
+TEST_F(HandleRangeAllocatorTest, AllocateAtOrAbove)
+{
+ const GLuint kOffset = 123456;
+ auto *allocator = getAllocator();
+ GLuint id1 = allocator->allocateAtOrAbove(kOffset);
+ EXPECT_EQ(kOffset, id1);
+ GLuint id2 = allocator->allocateAtOrAbove(kOffset);
+ EXPECT_GT(id2, kOffset);
+ GLuint id3 = allocator->allocateAtOrAbove(kOffset);
+ EXPECT_GT(id3, kOffset);
+}
+
+// Checks that allocateAtOrAbove wraps around at the maximum value.
+TEST_F(HandleRangeAllocatorTest, AllocateIdAtOrAboveWrapsAround)
+{
+ const GLuint kMaxPossibleOffset = ~static_cast<GLuint>(0);
+ auto *allocator = getAllocator();
+ GLuint id1 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
+ EXPECT_EQ(kMaxPossibleOffset, id1);
+ GLuint id2 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
+ EXPECT_EQ(1u, id2);
+ GLuint id3 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
+ EXPECT_EQ(2u, id3);
+}
+
+// Checks that freeing an already freed range causes no harm.
+TEST_F(HandleRangeAllocatorTest, RedundantFreeIsIgnored)
+{
+ auto *allocator = getAllocator();
+ GLuint id1 = allocator->allocate();
+ allocator->release(0);
+ allocator->release(id1);
+ allocator->release(id1);
+ allocator->release(id1 + 1);
+ GLuint id2 = allocator->allocate();
+ GLuint id3 = allocator->allocate();
+ EXPECT_NE(id2, id3);
+ EXPECT_NE(allocator->kInvalidHandle, id2);
+ EXPECT_NE(allocator->kInvalidHandle, id3);
+}
+
+// Check allocating and releasing multiple ranges.
+TEST_F(HandleRangeAllocatorTest, allocateRange)
+{
+ const GLuint kMaxPossibleOffset = std::numeric_limits<GLuint>::max();
+
+ auto *allocator = getAllocator();
+
+ GLuint id1 = allocator->allocateRange(1);
+ EXPECT_EQ(1u, id1);
+ GLuint id2 = allocator->allocateRange(2);
+ EXPECT_EQ(2u, id2);
+ GLuint id3 = allocator->allocateRange(3);
+ EXPECT_EQ(4u, id3);
+ GLuint id4 = allocator->allocate();
+ EXPECT_EQ(7u, id4);
+ allocator->release(3);
+ GLuint id5 = allocator->allocateRange(1);
+ EXPECT_EQ(3u, id5);
+ allocator->release(5);
+ allocator->release(2);
+ allocator->release(4);
+ GLuint id6 = allocator->allocateRange(2);
+ EXPECT_EQ(4u, id6);
+ GLuint id7 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
+ EXPECT_EQ(kMaxPossibleOffset, id7);
+ GLuint id8 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
+ EXPECT_EQ(2u, id8);
+ GLuint id9 = allocator->allocateRange(50);
+ EXPECT_EQ(8u, id9);
+ GLuint id10 = allocator->allocateRange(50);
+ EXPECT_EQ(58u, id10);
+ // Remove all the low-numbered ids.
+ allocator->release(1);
+ allocator->release(15);
+ allocator->releaseRange(2, 107);
+ GLuint id11 = allocator->allocateRange(100);
+ EXPECT_EQ(1u, id11);
+ allocator->release(kMaxPossibleOffset);
+ GLuint id12 = allocator->allocateRange(100);
+ EXPECT_EQ(101u, id12);
+
+ GLuint id13 = allocator->allocateAtOrAbove(kMaxPossibleOffset - 2u);
+ EXPECT_EQ(kMaxPossibleOffset - 2u, id13);
+ GLuint id14 = allocator->allocateRange(3);
+ EXPECT_EQ(201u, id14);
+}
+
+// Checks that having allocated a high range doesn't interfere
+// with normal low range allocation.
+TEST_F(HandleRangeAllocatorTest, AllocateRangeEndNoEffect)
+{
+ const GLuint kMaxPossibleOffset = std::numeric_limits<GLuint>::max();
+
+ auto *allocator = getAllocator();
+ GLuint id1 = allocator->allocateAtOrAbove(kMaxPossibleOffset - 2u);
+ EXPECT_EQ(kMaxPossibleOffset - 2u, id1);
+ GLuint id3 = allocator->allocateRange(3);
+ EXPECT_EQ(1u, id3);
+ GLuint id2 = allocator->allocateRange(2);
+ EXPECT_EQ(4u, id2);
+}
+
+// Checks allocating a range that consumes the whole uint32 space.
+TEST_F(HandleRangeAllocatorTest, AllocateMax)
+{
+ const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
+
+ auto *allocator = getAllocator();
+ GLuint id = allocator->allocateRange(kMaxPossibleRange);
+ EXPECT_EQ(1u, id);
+ allocator->releaseRange(id, kMaxPossibleRange - 1u);
+ GLuint id2 = allocator->allocateRange(kMaxPossibleRange);
+ EXPECT_EQ(0u, id2);
+ allocator->releaseRange(id, kMaxPossibleRange);
+ GLuint id3 = allocator->allocateRange(kMaxPossibleRange);
+ EXPECT_EQ(1u, id3);
+}
+
+// Checks allocating a range that consumes the whole uint32 space
+// causes next allocation to fail.
+// Subsequently checks that once the big range is reduced new allocations
+// are possible.
+TEST_F(HandleRangeAllocatorTest, AllocateFullRange)
+{
+ const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
+ const GLuint kFreedId = 555u;
+ auto *allocator = getAllocator();
+
+ GLuint id1 = allocator->allocateRange(kMaxPossibleRange);
+ EXPECT_EQ(1u, id1);
+ GLuint id2 = allocator->allocate();
+ EXPECT_EQ(gl::HandleRangeAllocator::kInvalidHandle, id2);
+ allocator->release(kFreedId);
+ GLuint id3 = allocator->allocate();
+ EXPECT_EQ(kFreedId, id3);
+ GLuint id4 = allocator->allocate();
+ EXPECT_EQ(0u, id4);
+ allocator->release(kFreedId + 1u);
+ allocator->release(kFreedId + 4u);
+ allocator->release(kFreedId + 3u);
+ allocator->release(kFreedId + 5u);
+ allocator->release(kFreedId + 2u);
+ GLuint id5 = allocator->allocateRange(5);
+ EXPECT_EQ(kFreedId + 1u, id5);
+}
+
+// Checks that allocating a range that exceeds uint32
+// does not wrap incorrectly and fails.
+TEST_F(HandleRangeAllocatorTest, AllocateRangeNoWrapInRange)
+{
+ const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
+ const GLuint kAllocId = 10u;
+ auto *allocator = getAllocator();
+
+ GLuint id1 = allocator->allocateAtOrAbove(kAllocId);
+ EXPECT_EQ(kAllocId, id1);
+ GLuint id2 = allocator->allocateRange(kMaxPossibleRange - 5u);
+ EXPECT_EQ(0u, id2);
+ GLuint id3 = allocator->allocateRange(kMaxPossibleRange - kAllocId);
+ EXPECT_EQ(kAllocId + 1u, id3);
+}
+
+// Check special cases for 0 range allocations and zero handles.
+TEST_F(HandleRangeAllocatorTest, ZeroIdCases)
+{
+ auto *allocator = getAllocator();
+ EXPECT_FALSE(allocator->isUsed(0));
+ GLuint id1 = allocator->allocateAtOrAbove(0);
+ EXPECT_NE(0u, id1);
+ EXPECT_FALSE(allocator->isUsed(0));
+ allocator->release(0);
+ EXPECT_FALSE(allocator->isUsed(0));
+ EXPECT_TRUE(allocator->isUsed(id1));
+ allocator->release(id1);
+ EXPECT_FALSE(allocator->isUsed(id1));
+}
+
+} // namespace \ No newline at end of file
diff --git a/gfx/angle/src/libANGLE/Image.cpp b/gfx/angle/src/libANGLE/Image.cpp
new file mode 100755
index 000000000..828f86238
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Image.cpp
@@ -0,0 +1,193 @@
+//
+// Copyright (c) 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/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace egl
+{
+ImageSibling::ImageSibling(GLuint id) : RefCountObject(id), 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.
+ ASSERT(mSourcesOf.empty());
+ orphanImages();
+}
+
+void ImageSibling::setTargetImage(egl::Image *imageTarget)
+{
+ ASSERT(imageTarget != nullptr);
+ mTargetOf.set(imageTarget);
+ imageTarget->addTargetSibling(this);
+}
+
+gl::Error ImageSibling::orphanImages()
+{
+ if (mTargetOf.get() != nullptr)
+ {
+ // Can't be a target and have sources.
+ ASSERT(mSourcesOf.empty());
+
+ gl::Error error = mTargetOf->orphanSibling(this);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mTargetOf.set(nullptr);
+ }
+ else
+ {
+ for (auto &sourceImage : mSourcesOf)
+ {
+ gl::Error error = sourceImage->orphanSibling(this);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ mSourcesOf.clear();
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+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);
+}
+
+Image::Image(rx::ImageImpl *impl, EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
+ : RefCountObject(0),
+ mImplementation(impl),
+ mFormat(gl::Format::Invalid()),
+ mWidth(0),
+ mHeight(0),
+ mSamples(0),
+ mSource(),
+ mTargets()
+{
+ ASSERT(mImplementation != nullptr);
+ ASSERT(buffer != nullptr);
+
+ mSource.set(buffer);
+ mSource->addImageSource(this);
+
+ if (IsTextureTarget(target))
+ {
+ gl::Texture *texture = rx::GetAs<gl::Texture>(mSource.get());
+ GLenum textureTarget = egl_gl::EGLImageTargetToGLTextureTarget(target);
+ size_t level = attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
+ mFormat = texture->getFormat(textureTarget, level);
+ mWidth = texture->getWidth(textureTarget, level);
+ mHeight = texture->getHeight(textureTarget, level);
+ mSamples = 0;
+ }
+ else if (IsRenderbufferTarget(target))
+ {
+ gl::Renderbuffer *renderbuffer = rx::GetAs<gl::Renderbuffer>(mSource.get());
+ mFormat = renderbuffer->getFormat();
+ mWidth = renderbuffer->getWidth();
+ mHeight = renderbuffer->getHeight();
+ mSamples = renderbuffer->getSamples();
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+}
+
+Image::~Image()
+{
+ SafeDelete(mImplementation);
+
+ // All targets should hold a ref to the egl image and it should not be deleted until there are
+ // no siblings left.
+ ASSERT(mTargets.empty());
+
+ // Tell the source that it is no longer used by this image
+ if (mSource.get() != nullptr)
+ {
+ mSource->removeImageSource(this);
+ mSource.set(nullptr);
+ }
+}
+
+void Image::addTargetSibling(ImageSibling *sibling)
+{
+ mTargets.insert(sibling);
+}
+
+gl::Error Image::orphanSibling(ImageSibling *sibling)
+{
+ // notify impl
+ gl::Error error = mImplementation->orphan(sibling);
+
+ if (mSource.get() == sibling)
+ {
+ // If the sibling is the source, it cannot be a target.
+ ASSERT(mTargets.find(sibling) == mTargets.end());
+
+ mSource.set(nullptr);
+ }
+ else
+ {
+ mTargets.erase(sibling);
+ }
+
+ return error;
+}
+
+const gl::Format &Image::getFormat() const
+{
+ return mFormat;
+}
+
+size_t Image::getWidth() const
+{
+ return mWidth;
+}
+
+size_t Image::getHeight() const
+{
+ return mHeight;
+}
+
+size_t Image::getSamples() const
+{
+ return mSamples;
+}
+
+rx::ImageImpl *Image::getImplementation()
+{
+ return mImplementation;
+}
+
+const rx::ImageImpl *Image::getImplementation() const
+{
+ return mImplementation;
+}
+} // namespace egl
diff --git a/gfx/angle/src/libANGLE/Image.h b/gfx/angle/src/libANGLE/Image.h
new file mode 100755
index 000000000..a579beab2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Image.h
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 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/angleutils.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/formatutils.h"
+
+#include <set>
+
+namespace rx
+{
+class ImageImpl;
+}
+
+namespace egl
+{
+class Image;
+
+class ImageSibling : public RefCountObject
+{
+ public:
+ ImageSibling(GLuint id);
+ virtual ~ImageSibling();
+
+ protected:
+ // Set the image target of this sibling
+ void setTargetImage(egl::Image *imageTarget);
+
+ // Orphan all EGL image sources and targets
+ gl::Error orphanImages();
+
+ 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);
+
+ std::set<Image *> mSourcesOf;
+ BindingPointer<Image> mTargetOf;
+};
+
+class Image final : public RefCountObject
+{
+ public:
+ Image(rx::ImageImpl *impl, EGLenum target, ImageSibling *buffer, const AttributeMap &attribs);
+ ~Image();
+
+ const gl::Format &getFormat() const;
+ size_t getWidth() const;
+ size_t getHeight() const;
+ size_t getSamples() const;
+
+ rx::ImageImpl *getImplementation();
+ const rx::ImageImpl *getImplementation() const;
+
+ 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.
+ gl::Error orphanSibling(ImageSibling *sibling);
+
+ rx::ImageImpl *mImplementation;
+
+ gl::Format mFormat;
+ size_t mWidth;
+ size_t mHeight;
+ size_t mSamples;
+
+ BindingPointer<ImageSibling> mSource;
+ std::set<ImageSibling *> mTargets;
+};
+}
+
+#endif // LIBANGLE_IMAGE_H_
diff --git a/gfx/angle/src/libANGLE/ImageIndex.cpp b/gfx/angle/src/libANGLE/ImageIndex.cpp
new file mode 100755
index 000000000..f74ce19d9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/ImageIndex.cpp
@@ -0,0 +1,207 @@
+//
+// 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 "libANGLE/Constants.h"
+#include "common/utilities.h"
+
+namespace gl
+{
+
+ImageIndex::ImageIndex(const ImageIndex &other)
+ : type(other.type),
+ mipIndex(other.mipIndex),
+ layerIndex(other.layerIndex)
+{}
+
+ImageIndex &ImageIndex::operator=(const ImageIndex &other)
+{
+ type = other.type;
+ mipIndex = other.mipIndex;
+ layerIndex = other.layerIndex;
+ return *this;
+}
+
+bool ImageIndex::is3D() const
+{
+ return type == GL_TEXTURE_3D || type == GL_TEXTURE_2D_ARRAY;
+}
+
+ImageIndex ImageIndex::Make2D(GLint mipIndex)
+{
+ return ImageIndex(GL_TEXTURE_2D, mipIndex, ENTIRE_LEVEL);
+}
+
+ImageIndex ImageIndex::MakeCube(GLenum target, GLint mipIndex)
+{
+ ASSERT(gl::IsCubeMapTextureTarget(target));
+ return ImageIndex(target, mipIndex,
+ static_cast<GLint>(CubeMapTextureTargetToLayerIndex(target)));
+}
+
+ImageIndex ImageIndex::Make2DArray(GLint mipIndex, GLint layerIndex)
+{
+ return ImageIndex(GL_TEXTURE_2D_ARRAY, mipIndex, layerIndex);
+}
+
+ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex)
+{
+ return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex);
+}
+
+ImageIndex ImageIndex::MakeGeneric(GLenum target, GLint mipIndex)
+{
+ GLint layerIndex = IsCubeMapTextureTarget(target)
+ ? static_cast<GLint>(CubeMapTextureTargetToLayerIndex(target))
+ : ENTIRE_LEVEL;
+ return ImageIndex(target, mipIndex, layerIndex);
+}
+
+ImageIndex ImageIndex::MakeInvalid()
+{
+ return ImageIndex(GL_NONE, -1, -1);
+}
+
+bool ImageIndex::operator<(const ImageIndex &other) const
+{
+ if (type != other.type)
+ {
+ return type < other.type;
+ }
+ else if (mipIndex != other.mipIndex)
+ {
+ return mipIndex < other.mipIndex;
+ }
+ else
+ {
+ return layerIndex < other.layerIndex;
+ }
+}
+
+bool ImageIndex::operator==(const ImageIndex &other) const
+{
+ return (type == other.type) && (mipIndex == other.mipIndex) && (layerIndex == other.layerIndex);
+}
+
+bool ImageIndex::operator!=(const ImageIndex &other) const
+{
+ return !(*this == other);
+}
+
+ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn)
+ : type(typeIn),
+ mipIndex(mipIndexIn),
+ layerIndex(layerIndexIn)
+{}
+
+ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
+{
+ return ImageIndexIterator(GL_TEXTURE_2D, Range<GLint>(minMip, maxMip),
+ Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), NULL);
+}
+
+ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
+{
+ return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, Range<GLint>(minMip, maxMip), Range<GLint>(0, 6), NULL);
+}
+
+ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip,
+ GLint minLayer, GLint maxLayer)
+{
+ return ImageIndexIterator(GL_TEXTURE_3D, Range<GLint>(minMip, maxMip), Range<GLint>(minLayer, maxLayer), NULL);
+}
+
+ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip,
+ const GLsizei *layerCounts)
+{
+ return ImageIndexIterator(GL_TEXTURE_2D_ARRAY, Range<GLint>(minMip, maxMip),
+ Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS), layerCounts);
+}
+
+ImageIndexIterator::ImageIndexIterator(GLenum type, const Range<GLint> &mipRange,
+ const Range<GLint> &layerRange, const GLsizei *layerCounts)
+ : mType(type),
+ mMipRange(mipRange),
+ mLayerRange(layerRange),
+ mLayerCounts(layerCounts),
+ mCurrentMip(mipRange.start),
+ mCurrentLayer(layerRange.start)
+{}
+
+GLint ImageIndexIterator::maxLayer() const
+{
+ if (mLayerCounts)
+ {
+ ASSERT(mCurrentMip >= 0);
+ return (mCurrentMip < mMipRange.end) ? mLayerCounts[mCurrentMip] : 0;
+ }
+ return mLayerRange.end;
+}
+
+ImageIndex ImageIndexIterator::next()
+{
+ ASSERT(hasNext());
+
+ ImageIndex value = current();
+
+ // Iterate layers in the inner loop for now. We can add switchable
+ // layer or mip iteration if we need it.
+
+ if (mCurrentLayer != ImageIndex::ENTIRE_LEVEL)
+ {
+ if (mCurrentLayer < maxLayer() - 1)
+ {
+ mCurrentLayer++;
+ }
+ else if (mCurrentMip < mMipRange.end - 1)
+ {
+ mCurrentMip++;
+ mCurrentLayer = mLayerRange.start;
+ }
+ else
+ {
+ done();
+ }
+ }
+ else if (mCurrentMip < mMipRange.end - 1)
+ {
+ mCurrentMip++;
+ mCurrentLayer = mLayerRange.start;
+ }
+ else
+ {
+ done();
+ }
+
+ return value;
+}
+
+ImageIndex ImageIndexIterator::current() const
+{
+ ImageIndex value(mType, mCurrentMip, mCurrentLayer);
+
+ if (mType == GL_TEXTURE_CUBE_MAP)
+ {
+ value.type = LayerIndexToCubeMapTextureTarget(mCurrentLayer);
+ }
+
+ return value;
+}
+
+bool ImageIndexIterator::hasNext() const
+{
+ return (mCurrentMip < mMipRange.end || mCurrentLayer < maxLayer());
+}
+
+void ImageIndexIterator::done()
+{
+ mCurrentMip = mMipRange.end;
+ mCurrentLayer = maxLayer();
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/ImageIndex.h b/gfx/angle/src/libANGLE/ImageIndex.h
new file mode 100755
index 000000000..5961f0cb0
--- /dev/null
+++ b/gfx/angle/src/libANGLE/ImageIndex.h
@@ -0,0 +1,83 @@
+//
+// 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/mathutil.h"
+
+#include "angle_gl.h"
+
+namespace gl
+{
+
+class ImageIndexIterator;
+
+struct ImageIndex
+{
+ GLenum type;
+ GLint mipIndex;
+ GLint layerIndex;
+
+ ImageIndex(const ImageIndex &other);
+ ImageIndex &operator=(const ImageIndex &other);
+
+ bool hasLayer() const { return layerIndex != ENTIRE_LEVEL; }
+ bool is3D() const;
+
+ static ImageIndex Make2D(GLint mipIndex);
+ static ImageIndex MakeCube(GLenum target, GLint mipIndex);
+ static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex);
+ static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL);
+ static ImageIndex MakeGeneric(GLenum target, GLint mipIndex);
+
+ static ImageIndex MakeInvalid();
+
+ static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1);
+
+ bool operator<(const ImageIndex &other) const;
+ bool operator==(const ImageIndex &other) const;
+ bool operator!=(const ImageIndex &other) const;
+
+ private:
+ friend class ImageIndexIterator;
+
+ ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn);
+};
+
+class ImageIndexIterator
+{
+ public:
+ static ImageIndexIterator Make2D(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);
+
+ ImageIndex next();
+ ImageIndex current() const;
+ bool hasNext() const;
+
+ private:
+
+ ImageIndexIterator(GLenum type, const Range<GLint> &mipRange,
+ const Range<GLint> &layerRange, const GLsizei *layerCounts);
+
+ GLint maxLayer() const;
+ void done();
+
+ GLenum mType;
+ Range<GLint> mMipRange;
+ Range<GLint> mLayerRange;
+ const GLsizei *mLayerCounts;
+ GLint mCurrentMip;
+ GLint mCurrentLayer;
+};
+
+}
+
+#endif // LIBANGLE_IMAGE_INDEX_H_
diff --git a/gfx/angle/src/libANGLE/ImageIndexIterator_unittest.cpp b/gfx/angle/src/libANGLE/ImageIndexIterator_unittest.cpp
new file mode 100755
index 000000000..2f97e8eba
--- /dev/null
+++ b/gfx/angle/src/libANGLE/ImageIndexIterator_unittest.cpp
@@ -0,0 +1,122 @@
+//
+// Copyright (c) 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 "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "common/utilities.h"
+#include "libANGLE/ImageIndex.h"
+
+using namespace gl;
+
+namespace
+{
+
+static const GLint minMip = 0;
+static const GLint maxMip = 4;
+static const GLint minLayer = 1;
+static const GLint maxLayer = 3;
+
+TEST(ImageIndexTest, Iterator2D)
+{
+ ImageIndexIterator iter = ImageIndexIterator::Make2D(minMip, maxMip);
+
+ ASSERT_GE(0, minMip);
+
+ for (GLint mip = minMip; mip < maxMip; mip++)
+ {
+ EXPECT_TRUE(iter.hasNext());
+ ImageIndex current = iter.current();
+ ImageIndex nextIndex = iter.next();
+
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), nextIndex.type);
+ EXPECT_EQ(mip, nextIndex.mipIndex);
+ EXPECT_FALSE(nextIndex.hasLayer());
+
+ // Also test current
+ EXPECT_EQ(current.type, nextIndex.type);
+ EXPECT_EQ(current.mipIndex, nextIndex.mipIndex);
+ EXPECT_EQ(current.layerIndex, nextIndex.layerIndex);
+ }
+
+ EXPECT_FALSE(iter.hasNext());
+}
+
+TEST(ImageIndexTest, IteratorCube)
+{
+ ImageIndexIterator iter = ImageIndexIterator::MakeCube(0, 4);
+
+ ASSERT_GE(0, minMip);
+
+ for (GLint mip = minMip; mip < maxMip; mip++)
+ {
+ for (GLint layer = 0; layer < 6; layer++)
+ {
+ EXPECT_TRUE(iter.hasNext());
+ ImageIndex nextIndex = iter.next();
+
+ GLenum cubeTarget = LayerIndexToCubeMapTextureTarget(layer);
+
+ EXPECT_EQ(cubeTarget, nextIndex.type);
+ EXPECT_EQ(mip, nextIndex.mipIndex);
+ EXPECT_EQ(layer, nextIndex.layerIndex);
+ EXPECT_TRUE(nextIndex.hasLayer());
+ }
+ }
+
+ EXPECT_FALSE(iter.hasNext());
+}
+
+TEST(ImageIndexTest, Iterator3D)
+{
+ ImageIndexIterator iter = ImageIndexIterator::Make3D(minMip, maxMip, minLayer, maxLayer);
+
+ ASSERT_GE(0, minMip);
+
+ for (GLint mip = minMip; mip < maxMip; mip++)
+ {
+ for (GLint layer = minLayer; layer < maxLayer; layer++)
+ {
+ EXPECT_TRUE(iter.hasNext());
+ ImageIndex nextIndex = iter.next();
+
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_3D), nextIndex.type);
+ EXPECT_EQ(mip, nextIndex.mipIndex);
+ EXPECT_EQ(layer, nextIndex.layerIndex);
+ EXPECT_TRUE(nextIndex.hasLayer());
+ }
+ }
+
+ EXPECT_FALSE(iter.hasNext());
+}
+
+TEST(ImageIndexTest, Iterator2DArray)
+{
+ GLsizei layerCounts[] = { 1, 3, 5, 2 };
+
+ ImageIndexIterator iter = ImageIndexIterator::Make2DArray(minMip, maxMip, layerCounts);
+
+ ASSERT_GE(0, minMip);
+ ASSERT_EQ(ArraySize(layerCounts), static_cast<size_t>(maxMip));
+
+ for (GLint mip = minMip; mip < maxMip; mip++)
+ {
+ for (GLint layer = 0; layer < layerCounts[mip]; layer++)
+ {
+ EXPECT_TRUE(iter.hasNext());
+ ImageIndex nextIndex = iter.next();
+
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D_ARRAY), nextIndex.type);
+ EXPECT_EQ(mip, nextIndex.mipIndex);
+ EXPECT_EQ(layer, nextIndex.layerIndex);
+ EXPECT_TRUE(nextIndex.hasLayer());
+ }
+ }
+
+ EXPECT_FALSE(iter.hasNext());
+}
+
+} // namespace
diff --git a/gfx/angle/src/libANGLE/Image_unittest.cpp b/gfx/angle/src/libANGLE/Image_unittest.cpp
new file mode 100755
index 000000000..0978ac678
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Image_unittest.cpp
@@ -0,0 +1,137 @@
+//
+// Copyright (c) 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_unittest.cpp : Unittets of the Image and ImageSibling classes.
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/renderer/ImageImpl_mock.h"
+#include "libANGLE/renderer/TextureImpl_mock.h"
+#include "libANGLE/renderer/RenderbufferImpl_mock.h"
+#include "tests/angle_unittests_utils.h"
+
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+
+namespace angle
+{
+// Verify ref counts are maintained between images and their siblings when objects are deleted
+TEST(ImageTest, RefCounting)
+{
+ NiceMock<rx::MockGLFactory> mockFactory;
+ // Create a texture and an EGL image that uses the texture as its source
+ rx::MockTextureImpl *textureImpl = new rx::MockTextureImpl();
+ EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
+ gl::Texture *texture = new gl::Texture(&mockFactory, 1, GL_TEXTURE_2D);
+ texture->addRef();
+
+ rx::MockImageImpl *imageImpl = new rx::MockImageImpl();
+ egl::Image *image = new egl::Image(imageImpl, EGL_GL_TEXTURE_2D, texture, egl::AttributeMap());
+ image->addRef();
+
+ // Verify that the image added a ref to the texture and the texture has not added a ref to the
+ // image
+ EXPECT_EQ(texture->getRefCount(), 2u);
+ EXPECT_EQ(image->getRefCount(), 1u);
+
+ // Create a renderbuffer and set it as a target of the EGL image
+ rx::MockRenderbufferImpl *renderbufferImpl = new rx::MockRenderbufferImpl();
+ gl::Renderbuffer *renderbuffer = new gl::Renderbuffer(renderbufferImpl, 1);
+ renderbuffer->addRef();
+
+ EXPECT_CALL(*renderbufferImpl, setStorageEGLImageTarget(_))
+ .WillOnce(Return(gl::Error(GL_NO_ERROR)))
+ .RetiresOnSaturation();
+ renderbuffer->setStorageEGLImageTarget(image);
+
+ // Verify that the renderbuffer added a ref to the image and the image did not add a ref to
+ // the renderbuffer
+ EXPECT_EQ(texture->getRefCount(), 2u);
+ EXPECT_EQ(image->getRefCount(), 2u);
+ EXPECT_EQ(renderbuffer->getRefCount(), 1u);
+
+ // Simulate deletion of the texture and verify that it still exists because the image holds a
+ // ref
+ texture->release();
+ EXPECT_EQ(texture->getRefCount(), 1u);
+ EXPECT_EQ(image->getRefCount(), 2u);
+ EXPECT_EQ(renderbuffer->getRefCount(), 1u);
+
+ // Simulate deletion of the image and verify that it still exists because the renderbuffer holds
+ // a ref
+ image->release();
+ EXPECT_EQ(texture->getRefCount(), 1u);
+ EXPECT_EQ(image->getRefCount(), 1u);
+ EXPECT_EQ(renderbuffer->getRefCount(), 1u);
+
+ // Simulate deletion of the renderbuffer and verify that the deletion cascades to all objects
+ EXPECT_CALL(*imageImpl, destructor()).Times(1).RetiresOnSaturation();
+ EXPECT_CALL(*imageImpl, orphan(_))
+ .WillOnce(Return(gl::Error(GL_NO_ERROR)))
+ .RetiresOnSaturation();
+
+ EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
+ EXPECT_CALL(*renderbufferImpl, destructor()).Times(1).RetiresOnSaturation();
+
+ renderbuffer->release();
+}
+
+// Verify that respecifiying textures releases references to the Image.
+TEST(ImageTest, RespecificationReleasesReferences)
+{
+ NiceMock<rx::MockGLFactory> mockFactory;
+ // Create a texture and an EGL image that uses the texture as its source
+ rx::MockTextureImpl *textureImpl = new rx::MockTextureImpl();
+ EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
+ gl::Texture *texture = new gl::Texture(&mockFactory, 1, GL_TEXTURE_2D);
+ texture->addRef();
+
+ gl::PixelUnpackState defaultUnpackState;
+
+ EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _))
+ .WillOnce(Return(gl::Error(GL_NO_ERROR)))
+ .RetiresOnSaturation();
+ texture->setImage(defaultUnpackState, GL_TEXTURE_2D, 0, GL_RGBA8, gl::Extents(1, 1, 1), GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+
+ rx::MockImageImpl *imageImpl = new rx::MockImageImpl();
+ egl::Image *image = new egl::Image(imageImpl, EGL_GL_TEXTURE_2D, texture, egl::AttributeMap());
+ image->addRef();
+
+ // Verify that the image added a ref to the texture and the texture has not added a ref to the
+ // image
+ EXPECT_EQ(texture->getRefCount(), 2u);
+ EXPECT_EQ(image->getRefCount(), 1u);
+
+ // Respecify the texture and verify that the image releases its reference
+ EXPECT_CALL(*imageImpl, orphan(_))
+ .WillOnce(Return(gl::Error(GL_NO_ERROR)))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _))
+ .WillOnce(Return(gl::Error(GL_NO_ERROR)))
+ .RetiresOnSaturation();
+
+ texture->setImage(defaultUnpackState, GL_TEXTURE_2D, 0, GL_RGBA8, gl::Extents(1, 1, 1), GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+
+ EXPECT_EQ(texture->getRefCount(), 1u);
+ EXPECT_EQ(image->getRefCount(), 1u);
+
+ // Delete the texture and verify that the image still exists
+ EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
+ texture->release();
+
+ EXPECT_EQ(image->getRefCount(), 1u);
+
+ // Delete the image
+ EXPECT_CALL(*imageImpl, destructor()).Times(1).RetiresOnSaturation();
+ image->release();
+}
+}
diff --git a/gfx/angle/src/libANGLE/IndexRangeCache.cpp b/gfx/angle/src/libANGLE/IndexRangeCache.cpp
new file mode 100755
index 000000000..4f165c1b2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/IndexRangeCache.cpp
@@ -0,0 +1,113 @@
+//
+// Copyright (c) 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
+{
+
+void IndexRangeCache::addRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ const IndexRange &range)
+{
+ mIndexRangeCache[IndexRangeKey(type, offset, count, primitiveRestartEnabled)] = range;
+}
+
+bool IndexRangeCache::findRange(GLenum 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 + (GetTypeInfo(i->first.type).bytes * i->first.count);
+
+ if (invalidateEnd < rangeStart || invalidateStart > rangeEnd)
+ {
+ ++i;
+ }
+ else
+ {
+ mIndexRangeCache.erase(i++);
+ }
+ }
+}
+
+void IndexRangeCache::clear()
+{
+ mIndexRangeCache.clear();
+}
+
+IndexRangeCache::IndexRangeKey::IndexRangeKey()
+ : IndexRangeCache::IndexRangeKey(GL_NONE, 0, 0, false)
+{
+}
+
+IndexRangeCache::IndexRangeKey::IndexRangeKey(GLenum 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;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/IndexRangeCache.h b/gfx/angle/src/libANGLE/IndexRangeCache.h
new file mode 100755
index 000000000..69de421c1
--- /dev/null
+++ b/gfx/angle/src/libANGLE/IndexRangeCache.h
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 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 "common/angleutils.h"
+#include "common/mathutil.h"
+
+#include "angle_gl.h"
+
+#include <map>
+
+namespace gl
+{
+
+class IndexRangeCache
+{
+ public:
+ void addRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ const IndexRange &range);
+ bool findRange(GLenum 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(GLenum type, size_t offset, size_t count, bool primitiveRestart);
+
+ bool operator<(const IndexRangeKey &rhs) const;
+
+ GLenum type;
+ size_t offset;
+ size_t count;
+ bool primitiveRestartEnabled;
+ };
+
+ typedef std::map<IndexRangeKey, IndexRange> IndexRangeMap;
+ IndexRangeMap mIndexRangeCache;
+};
+
+}
+
+#endif // LIBANGLE_INDEXRANGECACHE_H_
diff --git a/gfx/angle/src/libANGLE/Path.cpp b/gfx/angle/src/libANGLE/Path.cpp
new file mode 100755
index 000000000..e0c45db2b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Path.cpp
@@ -0,0 +1,78 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// Path.h: Defines the gl::Path class, representing CHROMIUM_path_rendering
+// path object.
+
+#include "libANGLE/Path.h"
+#include "libANGLE/renderer/PathImpl.h"
+
+#include "common/mathutil.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+Path::Path(rx::PathImpl *impl)
+ : mPath(impl),
+ mHasData(false),
+ mEndCaps(GL_FLAT_CHROMIUM),
+ mJoinStyle(GL_MITER_REVERT_CHROMIUM),
+ mStrokeWidth(1.0f),
+ mStrokeBound(0.2f),
+ mMiterLimit(4.0f)
+{
+}
+
+Path::~Path()
+{
+ delete mPath;
+}
+
+Error Path::setCommands(GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords)
+{
+ ANGLE_TRY(mPath->setCommands(numCommands, commands, numCoords, coordType, coords));
+
+ mHasData = true;
+
+ return gl::NoError();
+}
+
+void Path::setStrokeWidth(GLfloat width)
+{
+ mStrokeWidth = width;
+ mPath->setPathParameter(GL_PATH_STROKE_WIDTH_CHROMIUM, mStrokeWidth);
+}
+
+void Path::setStrokeBound(GLfloat bound)
+{
+ mStrokeBound = clamp(bound, 0.0f, 1.0f);
+ mPath->setPathParameter(GL_PATH_STROKE_BOUND_CHROMIUM, mStrokeBound);
+}
+
+void Path::setEndCaps(GLenum type)
+{
+ mEndCaps = type;
+ mPath->setPathParameter(GL_PATH_END_CAPS_CHROMIUM, static_cast<GLfloat>(type));
+}
+
+void Path::setJoinStyle(GLenum type)
+{
+ mJoinStyle = type;
+ mPath->setPathParameter(GL_PATH_JOIN_STYLE_CHROMIUM, static_cast<GLfloat>(type));
+}
+
+void Path::setMiterLimit(GLfloat value)
+{
+ mMiterLimit = value;
+ mPath->setPathParameter(GL_PATH_MITER_LIMIT_CHROMIUM, value);
+}
+
+} // gl
diff --git a/gfx/angle/src/libANGLE/Path.h b/gfx/angle/src/libANGLE/Path.h
new file mode 100755
index 000000000..b103c8460
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Path.h
@@ -0,0 +1,71 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// Path.h: Defines the gl::Path class, representing CHROMIUM_path_rendering
+// path object.
+
+#ifndef LIBANGLE_PATH_H_
+#define LIBANGLE_PATH_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class PathImpl;
+}
+
+namespace gl
+{
+class Path final : angle::NonCopyable
+{
+ public:
+ Path(rx::PathImpl *impl);
+
+ ~Path();
+
+ Error setCommands(GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords);
+
+ void setStrokeWidth(GLfloat width);
+ void setStrokeBound(GLfloat bound);
+ void setEndCaps(GLenum type);
+ void setJoinStyle(GLenum type);
+ void setMiterLimit(GLfloat value);
+
+ GLfloat getStrokeWidth() const { return mStrokeWidth; }
+ GLfloat getStrokeBound() const { return mStrokeBound; }
+ GLfloat getMiterLimit() const { return mMiterLimit; }
+ GLenum getEndCaps() const { return mEndCaps; }
+ GLenum getJoinStyle() const { return mJoinStyle; }
+
+ bool hasPathData() const { return mHasData; }
+
+ rx::PathImpl *getImplementation() const { return mPath; }
+
+ private:
+ rx::PathImpl *mPath;
+
+ // a Path object is not actually considered "a path"
+ // untill it has been specified with data. So we'll
+ // keep this flag to support this semantics.
+ bool mHasData;
+
+ GLenum mEndCaps;
+ GLenum mJoinStyle;
+ GLfloat mStrokeWidth;
+ GLfloat mStrokeBound;
+ GLfloat mMiterLimit;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_PATH_H_ \ No newline at end of file
diff --git a/gfx/angle/src/libANGLE/Platform.cpp b/gfx/angle/src/libANGLE/Platform.cpp
new file mode 100755
index 000000000..bfcdb1494
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Platform.cpp
@@ -0,0 +1,35 @@
+//
+// 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/Platform.h>
+
+#include "common/debug.h"
+
+namespace
+{
+angle::Platform *currentPlatform = nullptr;
+}
+
+// static
+angle::Platform *ANGLE_APIENTRY ANGLEPlatformCurrent()
+{
+ return currentPlatform;
+}
+
+// static
+void ANGLE_APIENTRY ANGLEPlatformInitialize(angle::Platform *platformImpl)
+{
+ ASSERT(platformImpl != nullptr);
+ currentPlatform = platformImpl;
+}
+
+// static
+void ANGLE_APIENTRY ANGLEPlatformShutdown()
+{
+ currentPlatform = nullptr;
+}
diff --git a/gfx/angle/src/libANGLE/Program.cpp b/gfx/angle/src/libANGLE/Program.cpp
new file mode 100755
index 000000000..06d8d1534
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Program.cpp
@@ -0,0 +1,2961 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 "common/BitSetIterator.h"
+#include "common/debug.h"
+#include "common/platform.h"
+#include "common/utilities.h"
+#include "common/version.h"
+#include "compiler/translator/blocklayout.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/ProgramImpl.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/Uniform.h"
+
+namespace gl
+{
+
+namespace
+{
+
+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->writeInt(var.arraySize);
+ stream->writeInt(var.staticUse);
+ stream->writeString(var.structName);
+ ASSERT(var.fields.empty());
+}
+
+void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
+{
+ var->type = stream->readInt<GLenum>();
+ var->precision = stream->readInt<GLenum>();
+ var->name = stream->readString();
+ var->mappedName = stream->readString();
+ var->arraySize = stream->readInt<unsigned int>();
+ var->staticUse = stream->readBool();
+ var->structName = stream->readString();
+}
+
+// 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 (value == GL_TRUE ? 1.0f : 0.0f);
+}
+
+template <>
+GLint UniformStateQueryCast(GLboolean value)
+{
+ return (value == GL_TRUE ? 1 : 0);
+}
+
+template <>
+GLuint UniformStateQueryCast(GLboolean value)
+{
+ return (value == GL_TRUE ? 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);
+ }
+}
+
+bool UniformInList(const std::vector<LinkedUniform> &list, const std::string &name)
+{
+ for (const LinkedUniform &uniform : list)
+ {
+ if (uniform.name == name)
+ return true;
+ }
+
+ return false;
+}
+
+} // anonymous namespace
+
+const char *const g_fakepath = "C:\\fakepath";
+
+InfoLog::InfoLog()
+{
+}
+
+InfoLog::~InfoLog()
+{
+}
+
+size_t InfoLog::getLength() const
+{
+ const std::string &logString = mStream.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 str(mStream.str());
+
+ if (!str.empty())
+ {
+ index = std::min(static_cast<size_t>(bufSize) - 1, str.length());
+ memcpy(infoLog, str.c_str(), index);
+ }
+
+ infoLog[index] = '\0';
+ }
+
+ if (length)
+ {
+ *length = static_cast<GLsizei>(index);
+ }
+}
+
+// append a santized 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)
+{
+ 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);
+
+ mStream << message << std::endl;
+}
+
+void InfoLog::reset()
+{
+}
+
+VariableLocation::VariableLocation() : name(), element(0), index(0), used(false), ignored(false)
+{
+}
+
+VariableLocation::VariableLocation(const std::string &name,
+ unsigned int element,
+ unsigned int index)
+ : name(name), element(element), index(index), used(true), ignored(false)
+{
+}
+
+void Program::Bindings::bindLocation(GLuint index, const std::string &name)
+{
+ mBindings[name] = index;
+}
+
+int Program::Bindings::getBinding(const std::string &name) const
+{
+ auto iter = mBindings.find(name);
+ return (iter != mBindings.end()) ? iter->second : -1;
+}
+
+Program::Bindings::const_iterator Program::Bindings::begin() const
+{
+ return mBindings.begin();
+}
+
+Program::Bindings::const_iterator Program::Bindings::end() const
+{
+ return mBindings.end();
+}
+
+ProgramState::ProgramState()
+ : mLabel(),
+ mAttachedFragmentShader(nullptr),
+ mAttachedVertexShader(nullptr),
+ mAttachedComputeShader(nullptr),
+ mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
+ mBinaryRetrieveableHint(false)
+{
+ mComputeShaderLocalSize.fill(1);
+}
+
+ProgramState::~ProgramState()
+{
+ if (mAttachedVertexShader != nullptr)
+ {
+ mAttachedVertexShader->release();
+ }
+
+ if (mAttachedFragmentShader != nullptr)
+ {
+ mAttachedFragmentShader->release();
+ }
+
+ if (mAttachedComputeShader != nullptr)
+ {
+ mAttachedComputeShader->release();
+ }
+}
+
+const std::string &ProgramState::getLabel()
+{
+ return mLabel;
+}
+
+const LinkedUniform *ProgramState::getUniformByName(const std::string &name) const
+{
+ for (const LinkedUniform &linkedUniform : mUniforms)
+ {
+ if (linkedUniform.name == name)
+ {
+ return &linkedUniform;
+ }
+ }
+
+ return nullptr;
+}
+
+GLint ProgramState::getUniformLocation(const std::string &name) const
+{
+ size_t subscript = GL_INVALID_INDEX;
+ std::string baseName = gl::ParseUniformName(name, &subscript);
+
+ for (size_t location = 0; location < mUniformLocations.size(); ++location)
+ {
+ const VariableLocation &uniformLocation = mUniformLocations[location];
+ if (!uniformLocation.used)
+ {
+ continue;
+ }
+
+ const LinkedUniform &uniform = mUniforms[uniformLocation.index];
+
+ if (uniform.name == baseName)
+ {
+ if (uniform.isArray())
+ {
+ if (uniformLocation.element == subscript ||
+ (uniformLocation.element == 0 && subscript == GL_INVALID_INDEX))
+ {
+ return static_cast<GLint>(location);
+ }
+ }
+ else
+ {
+ if (subscript == GL_INVALID_INDEX)
+ {
+ return static_cast<GLint>(location);
+ }
+ }
+ }
+ }
+
+ return -1;
+}
+
+GLuint ProgramState::getUniformIndex(const std::string &name) const
+{
+ size_t subscript = GL_INVALID_INDEX;
+ std::string baseName = gl::ParseUniformName(name, &subscript);
+
+ // The app is not allowed to specify array indices other than 0 for arrays of basic types
+ if (subscript != 0 && subscript != GL_INVALID_INDEX)
+ {
+ return GL_INVALID_INDEX;
+ }
+
+ for (size_t index = 0; index < mUniforms.size(); index++)
+ {
+ const LinkedUniform &uniform = mUniforms[index];
+ if (uniform.name == baseName)
+ {
+ if (uniform.isArray() || subscript == GL_INVALID_INDEX)
+ {
+ return static_cast<GLuint>(index);
+ }
+ }
+ }
+
+ return GL_INVALID_INDEX;
+}
+
+Program::Program(rx::GLImplFactory *factory, ResourceManager *manager, GLuint handle)
+ : mProgram(factory->createProgram(mState)),
+ mValidated(false),
+ mLinked(false),
+ mDeleteStatus(false),
+ mRefCount(0),
+ mResourceManager(manager),
+ mHandle(handle),
+ mSamplerUniformRange(0, 0)
+{
+ ASSERT(mProgram);
+
+ resetUniformBlockBindings();
+ unlink();
+}
+
+Program::~Program()
+{
+ unlink(true);
+
+ SafeDelete(mProgram);
+}
+
+void Program::setLabel(const std::string &label)
+{
+ mState.mLabel = label;
+}
+
+const std::string &Program::getLabel() const
+{
+ return mState.mLabel;
+}
+
+void Program::attachShader(Shader *shader)
+{
+ switch (shader->getType())
+ {
+ case GL_VERTEX_SHADER:
+ {
+ ASSERT(!mState.mAttachedVertexShader);
+ mState.mAttachedVertexShader = shader;
+ mState.mAttachedVertexShader->addRef();
+ break;
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ ASSERT(!mState.mAttachedFragmentShader);
+ mState.mAttachedFragmentShader = shader;
+ mState.mAttachedFragmentShader->addRef();
+ break;
+ }
+ case GL_COMPUTE_SHADER:
+ {
+ ASSERT(!mState.mAttachedComputeShader);
+ mState.mAttachedComputeShader = shader;
+ mState.mAttachedComputeShader->addRef();
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+}
+
+bool Program::detachShader(Shader *shader)
+{
+ switch (shader->getType())
+ {
+ case GL_VERTEX_SHADER:
+ {
+ if (mState.mAttachedVertexShader != shader)
+ {
+ return false;
+ }
+
+ shader->release();
+ mState.mAttachedVertexShader = nullptr;
+ break;
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ if (mState.mAttachedFragmentShader != shader)
+ {
+ return false;
+ }
+
+ shader->release();
+ mState.mAttachedFragmentShader = nullptr;
+ break;
+ }
+ case GL_COMPUTE_SHADER:
+ {
+ if (mState.mAttachedComputeShader != shader)
+ {
+ return false;
+ }
+
+ shader->release();
+ mState.mAttachedComputeShader = nullptr;
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ return true;
+}
+
+int Program::getAttachedShadersCount() const
+{
+ return (mState.mAttachedVertexShader ? 1 : 0) + (mState.mAttachedFragmentShader ? 1 : 0) +
+ (mState.mAttachedComputeShader ? 1 : 0);
+}
+
+void Program::bindAttributeLocation(GLuint index, const char *name)
+{
+ mAttributeBindings.bindLocation(index, name);
+}
+
+void Program::bindUniformLocation(GLuint index, const char *name)
+{
+ // Bind the base uniform name only since array indices other than 0 cannot be bound
+ mUniformBindings.bindLocation(index, ParseUniformName(name, nullptr));
+}
+
+void Program::bindFragmentInputLocation(GLint index, const char *name)
+{
+ mFragmentInputBindings.bindLocation(index, name);
+}
+
+BindingInfo Program::getFragmentInputBindingInfo(GLint index) const
+{
+ BindingInfo ret;
+ ret.type = GL_NONE;
+ ret.valid = false;
+
+ const Shader *fragmentShader = mState.getAttachedFragmentShader();
+ ASSERT(fragmentShader);
+
+ // Find the actual fragment shader varying we're interested in
+ const std::vector<sh::Varying> &inputs = fragmentShader->getVaryings();
+
+ for (const auto &binding : mFragmentInputBindings)
+ {
+ if (binding.second != static_cast<GLuint>(index))
+ continue;
+
+ ret.valid = true;
+
+ std::string originalName = binding.first;
+ unsigned int arrayIndex = ParseAndStripArrayIndex(&originalName);
+
+ for (const auto &in : inputs)
+ {
+ if (in.name == originalName)
+ {
+ if (in.isArray())
+ {
+ // The client wants to bind either "name" or "name[0]".
+ // GL ES 3.1 spec refers to active array names with language such as:
+ // "if 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".
+ if (arrayIndex == GL_INVALID_INDEX)
+ arrayIndex = 0;
+
+ ret.name = in.mappedName + "[" + ToString(arrayIndex) + "]";
+ }
+ else
+ {
+ ret.name = in.mappedName;
+ }
+ ret.type = in.type;
+ return ret;
+ }
+ }
+ }
+
+ return ret;
+}
+
+void Program::pathFragmentInputGen(GLint index,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ // If the location is -1 then the command is silently ignored
+ if (index == -1)
+ return;
+
+ const auto &binding = getFragmentInputBindingInfo(index);
+
+ // If the input doesn't exist then then the command is silently ignored
+ // This could happen through optimization for example, the shader translator
+ // decides that a variable is not actually being used and optimizes it away.
+ if (binding.name.empty())
+ return;
+
+ mProgram->setPathFragmentInputGen(binding.name, genMode, components, coeffs);
+}
+
+// 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.
+Error Program::link(const ContextState &data)
+{
+ unlink(false);
+
+ mInfoLog.reset();
+ resetUniformBlockBindings();
+
+ const Caps &caps = data.getCaps();
+
+ bool isComputeShaderAttached = (mState.mAttachedComputeShader != nullptr);
+ bool nonComputeShadersAttached =
+ (mState.mAttachedVertexShader != nullptr || mState.mAttachedFragmentShader != nullptr);
+ // 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 == true && nonComputeShadersAttached == true)
+ {
+ mInfoLog << "Both a compute and non-compute shaders are attached to the same program.";
+ return NoError();
+ }
+
+ if (mState.mAttachedComputeShader)
+ {
+ if (!mState.mAttachedComputeShader->isCompiled())
+ {
+ mInfoLog << "Attached compute shader is not compiled.";
+ return NoError();
+ }
+ ASSERT(mState.mAttachedComputeShader->getType() == GL_COMPUTE_SHADER);
+
+ mState.mComputeShaderLocalSize = mState.mAttachedComputeShader->getWorkGroupSize();
+
+ // 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())
+ {
+ mInfoLog << "Work group size is not specified.";
+ return NoError();
+ }
+
+ if (!linkUniforms(mInfoLog, caps, mUniformBindings))
+ {
+ return NoError();
+ }
+
+ if (!linkUniformBlocks(mInfoLog, caps))
+ {
+ return NoError();
+ }
+
+ ANGLE_TRY_RESULT(mProgram->link(data, mInfoLog), mLinked);
+ if (!mLinked)
+ {
+ return NoError();
+ }
+ }
+ else
+ {
+ if (!mState.mAttachedFragmentShader || !mState.mAttachedFragmentShader->isCompiled())
+ {
+ return NoError();
+ }
+ ASSERT(mState.mAttachedFragmentShader->getType() == GL_FRAGMENT_SHADER);
+
+ if (!mState.mAttachedVertexShader || !mState.mAttachedVertexShader->isCompiled())
+ {
+ return NoError();
+ }
+ ASSERT(mState.mAttachedVertexShader->getType() == GL_VERTEX_SHADER);
+
+ if (mState.mAttachedFragmentShader->getShaderVersion() !=
+ mState.mAttachedVertexShader->getShaderVersion())
+ {
+ mInfoLog << "Fragment shader version does not match vertex shader version.";
+ return NoError();
+ }
+
+ if (!linkAttributes(data, mInfoLog, mAttributeBindings, mState.mAttachedVertexShader))
+ {
+ return NoError();
+ }
+
+ if (!linkVaryings(mInfoLog, mState.mAttachedVertexShader, mState.mAttachedFragmentShader))
+ {
+ return NoError();
+ }
+
+ if (!linkUniforms(mInfoLog, caps, mUniformBindings))
+ {
+ return NoError();
+ }
+
+ if (!linkUniformBlocks(mInfoLog, caps))
+ {
+ return NoError();
+ }
+
+ const auto &mergedVaryings = getMergedVaryings();
+
+ if (!linkValidateTransformFeedback(mInfoLog, mergedVaryings, caps))
+ {
+ return NoError();
+ }
+
+ linkOutputVariables();
+
+ ANGLE_TRY_RESULT(mProgram->link(data, mInfoLog), mLinked);
+ if (!mLinked)
+ {
+ return NoError();
+ }
+
+ gatherTransformFeedbackVaryings(mergedVaryings);
+ }
+
+ gatherInterfaceBlockInfo();
+
+ return NoError();
+}
+
+// Returns the program object to an unlinked state, before re-linking, or at destruction
+void Program::unlink(bool destroy)
+{
+ if (destroy) // Object being destructed
+ {
+ if (mState.mAttachedFragmentShader)
+ {
+ mState.mAttachedFragmentShader->release();
+ mState.mAttachedFragmentShader = nullptr;
+ }
+
+ if (mState.mAttachedVertexShader)
+ {
+ mState.mAttachedVertexShader->release();
+ mState.mAttachedVertexShader = nullptr;
+ }
+
+ if (mState.mAttachedComputeShader)
+ {
+ mState.mAttachedComputeShader->release();
+ mState.mAttachedComputeShader = nullptr;
+ }
+ }
+
+ mState.mAttributes.clear();
+ mState.mActiveAttribLocationsMask.reset();
+ mState.mTransformFeedbackVaryingVars.clear();
+ mState.mUniforms.clear();
+ mState.mUniformLocations.clear();
+ mState.mUniformBlocks.clear();
+ mState.mOutputVariables.clear();
+ mState.mComputeShaderLocalSize.fill(1);
+
+ mValidated = false;
+
+ mLinked = false;
+}
+
+bool Program::isLinked() const
+{
+ return mLinked;
+}
+
+Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei length)
+{
+ unlink(false);
+
+#if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
+ return Error(GL_NO_ERROR);
+#else
+ ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
+ if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
+ {
+ mInfoLog << "Invalid program binary format.";
+ return Error(GL_NO_ERROR);
+ }
+
+ BinaryInputStream stream(binary, length);
+
+ int majorVersion = stream.readInt<int>();
+ int minorVersion = stream.readInt<int>();
+ if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
+ {
+ mInfoLog << "Invalid program binary version.";
+ return Error(GL_NO_ERROR);
+ }
+
+ unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
+ stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
+ if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0)
+ {
+ mInfoLog << "Invalid program binary version.";
+ return Error(GL_NO_ERROR);
+ }
+
+ mState.mComputeShaderLocalSize[0] = stream.readInt<int>();
+ mState.mComputeShaderLocalSize[1] = stream.readInt<int>();
+ mState.mComputeShaderLocalSize[2] = stream.readInt<int>();
+
+ static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8,
+ "Too many vertex attribs for mask");
+ mState.mActiveAttribLocationsMask = stream.readInt<unsigned long>();
+
+ unsigned int attribCount = stream.readInt<unsigned int>();
+ ASSERT(mState.mAttributes.empty());
+ for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
+ {
+ sh::Attribute attrib;
+ LoadShaderVar(&stream, &attrib);
+ attrib.location = stream.readInt<int>();
+ mState.mAttributes.push_back(attrib);
+ }
+
+ unsigned int uniformCount = stream.readInt<unsigned int>();
+ ASSERT(mState.mUniforms.empty());
+ for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
+ {
+ LinkedUniform uniform;
+ LoadShaderVar(&stream, &uniform);
+
+ uniform.blockIndex = stream.readInt<int>();
+ uniform.blockInfo.offset = stream.readInt<int>();
+ uniform.blockInfo.arrayStride = stream.readInt<int>();
+ uniform.blockInfo.matrixStride = stream.readInt<int>();
+ uniform.blockInfo.isRowMajorMatrix = stream.readBool();
+
+ mState.mUniforms.push_back(uniform);
+ }
+
+ const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
+ ASSERT(mState.mUniformLocations.empty());
+ for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount;
+ uniformIndexIndex++)
+ {
+ VariableLocation variable;
+ stream.readString(&variable.name);
+ stream.readInt(&variable.element);
+ stream.readInt(&variable.index);
+ stream.readBool(&variable.used);
+ stream.readBool(&variable.ignored);
+
+ mState.mUniformLocations.push_back(variable);
+ }
+
+ unsigned int uniformBlockCount = stream.readInt<unsigned int>();
+ ASSERT(mState.mUniformBlocks.empty());
+ for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount;
+ ++uniformBlockIndex)
+ {
+ UniformBlock uniformBlock;
+ stream.readString(&uniformBlock.name);
+ stream.readBool(&uniformBlock.isArray);
+ stream.readInt(&uniformBlock.arrayElement);
+ stream.readInt(&uniformBlock.dataSize);
+ stream.readBool(&uniformBlock.vertexStaticUse);
+ stream.readBool(&uniformBlock.fragmentStaticUse);
+
+ unsigned int numMembers = stream.readInt<unsigned int>();
+ for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
+ {
+ uniformBlock.memberUniformIndexes.push_back(stream.readInt<unsigned int>());
+ }
+
+ mState.mUniformBlocks.push_back(uniformBlock);
+ }
+
+ unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
+ ASSERT(mState.mTransformFeedbackVaryingVars.empty());
+ for (unsigned int transformFeedbackVaryingIndex = 0;
+ transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
+ ++transformFeedbackVaryingIndex)
+ {
+ sh::Varying varying;
+ stream.readInt(&varying.arraySize);
+ stream.readInt(&varying.type);
+ stream.readString(&varying.name);
+
+ mState.mTransformFeedbackVaryingVars.push_back(varying);
+ }
+
+ stream.readInt(&mState.mTransformFeedbackBufferMode);
+
+ unsigned int outputVarCount = stream.readInt<unsigned int>();
+ for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
+ {
+ int locationIndex = stream.readInt<int>();
+ VariableLocation locationData;
+ stream.readInt(&locationData.element);
+ stream.readInt(&locationData.index);
+ stream.readString(&locationData.name);
+ mState.mOutputVariables[locationIndex] = locationData;
+ }
+
+ stream.readInt(&mSamplerUniformRange.start);
+ stream.readInt(&mSamplerUniformRange.end);
+
+ ANGLE_TRY_RESULT(mProgram->load(mInfoLog, &stream), mLinked);
+
+ return NoError();
+#endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
+}
+
+Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const
+{
+ if (binaryFormat)
+ {
+ *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
+ }
+
+ BinaryOutputStream stream;
+
+ stream.writeInt(ANGLE_MAJOR_VERSION);
+ stream.writeInt(ANGLE_MINOR_VERSION);
+ stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
+
+ stream.writeInt(mState.mComputeShaderLocalSize[0]);
+ stream.writeInt(mState.mComputeShaderLocalSize[1]);
+ stream.writeInt(mState.mComputeShaderLocalSize[2]);
+
+ stream.writeInt(mState.mActiveAttribLocationsMask.to_ulong());
+
+ stream.writeInt(mState.mAttributes.size());
+ for (const sh::Attribute &attrib : mState.mAttributes)
+ {
+ WriteShaderVar(&stream, attrib);
+ stream.writeInt(attrib.location);
+ }
+
+ stream.writeInt(mState.mUniforms.size());
+ for (const gl::LinkedUniform &uniform : mState.mUniforms)
+ {
+ WriteShaderVar(&stream, uniform);
+
+ // FIXME: referenced
+
+ stream.writeInt(uniform.blockIndex);
+ stream.writeInt(uniform.blockInfo.offset);
+ stream.writeInt(uniform.blockInfo.arrayStride);
+ stream.writeInt(uniform.blockInfo.matrixStride);
+ stream.writeInt(uniform.blockInfo.isRowMajorMatrix);
+ }
+
+ stream.writeInt(mState.mUniformLocations.size());
+ for (const auto &variable : mState.mUniformLocations)
+ {
+ stream.writeString(variable.name);
+ stream.writeInt(variable.element);
+ stream.writeInt(variable.index);
+ stream.writeInt(variable.used);
+ stream.writeInt(variable.ignored);
+ }
+
+ stream.writeInt(mState.mUniformBlocks.size());
+ for (const UniformBlock &uniformBlock : mState.mUniformBlocks)
+ {
+ stream.writeString(uniformBlock.name);
+ stream.writeInt(uniformBlock.isArray);
+ stream.writeInt(uniformBlock.arrayElement);
+ stream.writeInt(uniformBlock.dataSize);
+
+ stream.writeInt(uniformBlock.vertexStaticUse);
+ stream.writeInt(uniformBlock.fragmentStaticUse);
+
+ stream.writeInt(uniformBlock.memberUniformIndexes.size());
+ for (unsigned int memberUniformIndex : uniformBlock.memberUniformIndexes)
+ {
+ stream.writeInt(memberUniformIndex);
+ }
+ }
+
+ stream.writeInt(mState.mTransformFeedbackVaryingVars.size());
+ for (const sh::Varying &varying : mState.mTransformFeedbackVaryingVars)
+ {
+ stream.writeInt(varying.arraySize);
+ stream.writeInt(varying.type);
+ stream.writeString(varying.name);
+ }
+
+ stream.writeInt(mState.mTransformFeedbackBufferMode);
+
+ stream.writeInt(mState.mOutputVariables.size());
+ for (const auto &outputPair : mState.mOutputVariables)
+ {
+ stream.writeInt(outputPair.first);
+ stream.writeIntOrNegOne(outputPair.second.element);
+ stream.writeInt(outputPair.second.index);
+ stream.writeString(outputPair.second.name);
+ }
+
+ stream.writeInt(mSamplerUniformRange.start);
+ stream.writeInt(mSamplerUniformRange.end);
+
+ gl::Error error = mProgram->save(&stream);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ GLsizei streamLength = static_cast<GLsizei>(stream.length());
+ const void *streamState = stream.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.
+ return Error(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 Error(GL_NO_ERROR);
+}
+
+GLint Program::getBinaryLength() const
+{
+ GLint length;
+ Error error = saveBinary(nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
+ if (error.isError())
+ {
+ return 0;
+ }
+
+ return length;
+}
+
+void Program::setBinaryRetrievableHint(bool retrievable)
+{
+ // TODO(jmadill) : replace with dirty bits
+ mProgram->setBinaryRetrievableHint(retrievable);
+ mState.mBinaryRetrieveableHint = retrievable;
+}
+
+bool Program::getBinaryRetrievableHint() const
+{
+ return mState.mBinaryRetrieveableHint;
+}
+
+void Program::release()
+{
+ mRefCount--;
+
+ if (mRefCount == 0 && mDeleteStatus)
+ {
+ mResourceManager->deleteProgram(mHandle);
+ }
+}
+
+void Program::addRef()
+{
+ mRefCount++;
+}
+
+unsigned int Program::getRefCount() const
+{
+ return mRefCount;
+}
+
+int Program::getInfoLogLength() const
+{
+ return static_cast<int>(mInfoLog.getLength());
+}
+
+void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
+{
+ return mInfoLog.getLog(bufSize, length, infoLog);
+}
+
+void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const
+{
+ int total = 0;
+
+ if (mState.mAttachedComputeShader)
+ {
+ if (total < maxCount)
+ {
+ shaders[total] = mState.mAttachedComputeShader->getHandle();
+ total++;
+ }
+ }
+
+ if (mState.mAttachedVertexShader)
+ {
+ if (total < maxCount)
+ {
+ shaders[total] = mState.mAttachedVertexShader->getHandle();
+ total++;
+ }
+ }
+
+ if (mState.mAttachedFragmentShader)
+ {
+ if (total < maxCount)
+ {
+ shaders[total] = mState.mAttachedFragmentShader->getHandle();
+ total++;
+ }
+ }
+
+ if (count)
+ {
+ *count = total;
+ }
+}
+
+GLuint Program::getAttributeLocation(const std::string &name) const
+{
+ for (const sh::Attribute &attribute : mState.mAttributes)
+ {
+ if (attribute.name == name && attribute.staticUse)
+ {
+ return attribute.location;
+ }
+ }
+
+ return static_cast<GLuint>(-1);
+}
+
+bool Program::isAttribLocationActive(size_t attribLocation) const
+{
+ ASSERT(attribLocation < mState.mActiveAttribLocationsMask.size());
+ return mState.mActiveAttribLocationsMask[attribLocation];
+}
+
+void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+ if (!mLinked)
+ {
+ if (bufsize > 0)
+ {
+ name[0] = '\0';
+ }
+
+ if (length)
+ {
+ *length = 0;
+ }
+
+ *type = GL_NONE;
+ *size = 1;
+ return;
+ }
+
+ size_t attributeIndex = 0;
+
+ for (const sh::Attribute &attribute : mState.mAttributes)
+ {
+ // Skip over inactive attributes
+ if (attribute.staticUse)
+ {
+ if (static_cast<size_t>(index) == attributeIndex)
+ {
+ break;
+ }
+ attributeIndex++;
+ }
+ }
+
+ ASSERT(index == attributeIndex && attributeIndex < mState.mAttributes.size());
+ const sh::Attribute &attrib = mState.mAttributes[attributeIndex];
+
+ if (bufsize > 0)
+ {
+ const char *string = attrib.name.c_str();
+
+ strncpy(name, string, bufsize);
+ name[bufsize - 1] = '\0';
+
+ if (length)
+ {
+ *length = static_cast<GLsizei>(strlen(name));
+ }
+ }
+
+ // Always a single 'type' instance
+ *size = 1;
+ *type = attrib.type;
+}
+
+GLint Program::getActiveAttributeCount() const
+{
+ if (!mLinked)
+ {
+ return 0;
+ }
+
+ GLint count = 0;
+
+ for (const sh::Attribute &attrib : mState.mAttributes)
+ {
+ count += (attrib.staticUse ? 1 : 0);
+ }
+
+ return count;
+}
+
+GLint Program::getActiveAttributeMaxLength() const
+{
+ if (!mLinked)
+ {
+ return 0;
+ }
+
+ size_t maxLength = 0;
+
+ for (const sh::Attribute &attrib : mState.mAttributes)
+ {
+ if (attrib.staticUse)
+ {
+ maxLength = std::max(attrib.name.length() + 1, maxLength);
+ }
+ }
+
+ return static_cast<GLint>(maxLength);
+}
+
+GLint Program::getFragDataLocation(const std::string &name) const
+{
+ std::string baseName(name);
+ unsigned int arrayIndex = ParseAndStripArrayIndex(&baseName);
+ for (auto outputPair : mState.mOutputVariables)
+ {
+ const VariableLocation &outputVariable = outputPair.second;
+ if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
+ {
+ return static_cast<GLint>(outputPair.first);
+ }
+ }
+ return -1;
+}
+
+void Program::getActiveUniform(GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name) const
+{
+ if (mLinked)
+ {
+ // index must be smaller than getActiveUniformCount()
+ ASSERT(index < mState.mUniforms.size());
+ const LinkedUniform &uniform = mState.mUniforms[index];
+
+ if (bufsize > 0)
+ {
+ std::string string = uniform.name;
+ if (uniform.isArray())
+ {
+ string += "[0]";
+ }
+
+ strncpy(name, string.c_str(), bufsize);
+ name[bufsize - 1] = '\0';
+
+ if (length)
+ {
+ *length = static_cast<GLsizei>(strlen(name));
+ }
+ }
+
+ *size = uniform.elementCount();
+ *type = uniform.type;
+ }
+ else
+ {
+ if (bufsize > 0)
+ {
+ name[0] = '\0';
+ }
+
+ if (length)
+ {
+ *length = 0;
+ }
+
+ *size = 0;
+ *type = GL_NONE;
+ }
+}
+
+GLint Program::getActiveUniformCount() const
+{
+ if (mLinked)
+ {
+ return static_cast<GLint>(mState.mUniforms.size());
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+GLint Program::getActiveUniformMaxLength() const
+{
+ size_t maxLength = 0;
+
+ if (mLinked)
+ {
+ for (const LinkedUniform &uniform : mState.mUniforms)
+ {
+ 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);
+}
+
+GLint Program::getActiveUniformi(GLuint index, GLenum pname) const
+{
+ ASSERT(static_cast<size_t>(index) < mState.mUniforms.size());
+ const gl::LinkedUniform &uniform = mState.mUniforms[index];
+ switch (pname)
+ {
+ case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type);
+ case GL_UNIFORM_SIZE: return static_cast<GLint>(uniform.elementCount());
+ case GL_UNIFORM_NAME_LENGTH: return static_cast<GLint>(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0));
+ case GL_UNIFORM_BLOCK_INDEX: return uniform.blockIndex;
+ case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset;
+ case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride;
+ case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride;
+ case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix);
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return 0;
+}
+
+bool Program::isValidUniformLocation(GLint location) const
+{
+ ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
+ return (location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size() &&
+ mState.mUniformLocations[static_cast<size_t>(location)].used);
+}
+
+bool Program::isIgnoredUniformLocation(GLint location) const
+{
+ // Location is ignored if it is -1 or it was bound but non-existant in the shader or optimized
+ // out
+ return location == -1 ||
+ (location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size() &&
+ mState.mUniformLocations[static_cast<size_t>(location)].ignored);
+}
+
+const LinkedUniform &Program::getUniformByLocation(GLint location) const
+{
+ ASSERT(location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size());
+ return mState.mUniforms[mState.mUniformLocations[location].index];
+}
+
+GLint Program::getUniformLocation(const std::string &name) const
+{
+ return mState.getUniformLocation(name);
+}
+
+GLuint Program::getUniformIndex(const std::string &name) const
+{
+ return mState.getUniformIndex(name);
+}
+
+void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ GLsizei clampedCount = setUniformInternal(location, count, 1, v);
+ mProgram->setUniform1fv(location, clampedCount, v);
+}
+
+void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ GLsizei clampedCount = setUniformInternal(location, count, 2, v);
+ mProgram->setUniform2fv(location, clampedCount, v);
+}
+
+void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ GLsizei clampedCount = setUniformInternal(location, count, 3, v);
+ mProgram->setUniform3fv(location, clampedCount, v);
+}
+
+void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ GLsizei clampedCount = setUniformInternal(location, count, 4, v);
+ mProgram->setUniform4fv(location, clampedCount, v);
+}
+
+void Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+ GLsizei clampedCount = setUniformInternal(location, count, 1, v);
+ mProgram->setUniform1iv(location, clampedCount, v);
+}
+
+void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+ GLsizei clampedCount = setUniformInternal(location, count, 2, v);
+ mProgram->setUniform2iv(location, clampedCount, v);
+}
+
+void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+ GLsizei clampedCount = setUniformInternal(location, count, 3, v);
+ mProgram->setUniform3iv(location, clampedCount, v);
+}
+
+void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+ GLsizei clampedCount = setUniformInternal(location, count, 4, v);
+ mProgram->setUniform4iv(location, clampedCount, v);
+}
+
+void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ GLsizei clampedCount = setUniformInternal(location, count, 1, v);
+ mProgram->setUniform1uiv(location, clampedCount, v);
+}
+
+void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ GLsizei clampedCount = setUniformInternal(location, count, 2, v);
+ mProgram->setUniform2uiv(location, clampedCount, v);
+}
+
+void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ GLsizei clampedCount = setUniformInternal(location, count, 3, v);
+ mProgram->setUniform3uiv(location, clampedCount, v);
+}
+
+void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ GLsizei clampedCount = setUniformInternal(location, count, 4, v);
+ mProgram->setUniform4uiv(location, clampedCount, v);
+}
+
+void Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ GLsizei clampedCount = setMatrixUniformInternal<2, 2>(location, count, transpose, v);
+ mProgram->setUniformMatrix2fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ GLsizei clampedCount = setMatrixUniformInternal<3, 3>(location, count, transpose, v);
+ mProgram->setUniformMatrix3fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ GLsizei clampedCount = setMatrixUniformInternal<4, 4>(location, count, transpose, v);
+ mProgram->setUniformMatrix4fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ GLsizei clampedCount = setMatrixUniformInternal<2, 3>(location, count, transpose, v);
+ mProgram->setUniformMatrix2x3fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ GLsizei clampedCount = setMatrixUniformInternal<2, 4>(location, count, transpose, v);
+ mProgram->setUniformMatrix2x4fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ GLsizei clampedCount = setMatrixUniformInternal<3, 2>(location, count, transpose, v);
+ mProgram->setUniformMatrix3x2fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ GLsizei clampedCount = setMatrixUniformInternal<3, 4>(location, count, transpose, v);
+ mProgram->setUniformMatrix3x4fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ GLsizei clampedCount = setMatrixUniformInternal<4, 2>(location, count, transpose, v);
+ mProgram->setUniformMatrix4x2fv(location, clampedCount, transpose, v);
+}
+
+void Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ GLsizei clampedCount = setMatrixUniformInternal<4, 3>(location, count, transpose, v);
+ mProgram->setUniformMatrix4x3fv(location, clampedCount, transpose, v);
+}
+
+void Program::getUniformfv(GLint location, GLfloat *v) const
+{
+ getUniformInternal(location, v);
+}
+
+void Program::getUniformiv(GLint location, GLint *v) const
+{
+ getUniformInternal(location, v);
+}
+
+void Program::getUniformuiv(GLint location, GLuint *v) const
+{
+ getUniformInternal(location, v);
+}
+
+void Program::flagForDeletion()
+{
+ mDeleteStatus = true;
+}
+
+bool Program::isFlaggedForDeletion() const
+{
+ return mDeleteStatus;
+}
+
+void Program::validate(const Caps &caps)
+{
+ mInfoLog.reset();
+
+ if (mLinked)
+ {
+ mValidated = (mProgram->validate(caps, &mInfoLog) == GL_TRUE);
+ }
+ else
+ {
+ mInfoLog << "Program has not been successfully linked.";
+ }
+}
+
+bool Program::validateSamplers(InfoLog *infoLog, const Caps &caps)
+{
+ // Skip cache if we're using an infolog, so we get the full error.
+ // Also skip the cache if the sample mapping has changed, or if we haven't ever validated.
+ if (infoLog == nullptr && mCachedValidateSamplersResult.valid())
+ {
+ return mCachedValidateSamplersResult.value();
+ }
+
+ if (mTextureUnitTypesCache.empty())
+ {
+ mTextureUnitTypesCache.resize(caps.maxCombinedTextureImageUnits, GL_NONE);
+ }
+ else
+ {
+ std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE);
+ }
+
+ // 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 (unsigned int samplerIndex = mSamplerUniformRange.start;
+ samplerIndex < mSamplerUniformRange.end; ++samplerIndex)
+ {
+ const LinkedUniform &uniform = mState.mUniforms[samplerIndex];
+ ASSERT(uniform.isSampler());
+
+ if (!uniform.staticUse)
+ continue;
+
+ const GLuint *dataPtr = reinterpret_cast<const GLuint *>(uniform.getDataPtrToElement(0));
+ GLenum textureType = SamplerTypeToTextureType(uniform.type);
+
+ for (unsigned int arrayElement = 0; arrayElement < uniform.elementCount(); ++arrayElement)
+ {
+ GLuint textureUnit = dataPtr[arrayElement];
+
+ if (textureUnit >= caps.maxCombinedTextureImageUnits)
+ {
+ if (infoLog)
+ {
+ (*infoLog) << "Sampler uniform (" << textureUnit
+ << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
+ << caps.maxCombinedTextureImageUnits << ")";
+ }
+
+ mCachedValidateSamplersResult = false;
+ return false;
+ }
+
+ if (mTextureUnitTypesCache[textureUnit] != GL_NONE)
+ {
+ if (textureType != mTextureUnitTypesCache[textureUnit])
+ {
+ if (infoLog)
+ {
+ (*infoLog) << "Samplers of conflicting types refer to the same texture "
+ "image unit ("
+ << textureUnit << ").";
+ }
+
+ mCachedValidateSamplersResult = false;
+ return false;
+ }
+ }
+ else
+ {
+ mTextureUnitTypesCache[textureUnit] = textureType;
+ }
+ }
+ }
+
+ mCachedValidateSamplersResult = true;
+ return true;
+}
+
+bool Program::isValidated() const
+{
+ return mValidated;
+}
+
+GLuint Program::getActiveUniformBlockCount() const
+{
+ return static_cast<GLuint>(mState.mUniformBlocks.size());
+}
+
+void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
+{
+ ASSERT(
+ uniformBlockIndex <
+ mState.mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
+
+ const UniformBlock &uniformBlock = mState.mUniformBlocks[uniformBlockIndex];
+
+ if (bufSize > 0)
+ {
+ std::string string = uniformBlock.name;
+
+ if (uniformBlock.isArray)
+ {
+ string += ArrayString(uniformBlock.arrayElement);
+ }
+
+ strncpy(uniformBlockName, string.c_str(), bufSize);
+ uniformBlockName[bufSize - 1] = '\0';
+
+ if (length)
+ {
+ *length = static_cast<GLsizei>(strlen(uniformBlockName));
+ }
+ }
+}
+
+GLint Program::getActiveUniformBlockMaxLength() const
+{
+ int maxLength = 0;
+
+ if (mLinked)
+ {
+ unsigned int numUniformBlocks = static_cast<unsigned int>(mState.mUniformBlocks.size());
+ for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
+ {
+ const UniformBlock &uniformBlock = mState.mUniformBlocks[uniformBlockIndex];
+ if (!uniformBlock.name.empty())
+ {
+ const int length = static_cast<int>(uniformBlock.name.length()) + 1;
+
+ // Counting in "[0]".
+ const int arrayLength = (uniformBlock.isArray ? 3 : 0);
+
+ maxLength = std::max(length + arrayLength, maxLength);
+ }
+ }
+ }
+
+ return maxLength;
+}
+
+GLuint Program::getUniformBlockIndex(const std::string &name) const
+{
+ size_t subscript = GL_INVALID_INDEX;
+ std::string baseName = gl::ParseUniformName(name, &subscript);
+
+ unsigned int numUniformBlocks = static_cast<unsigned int>(mState.mUniformBlocks.size());
+ for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
+ {
+ const gl::UniformBlock &uniformBlock = mState.mUniformBlocks[blockIndex];
+ if (uniformBlock.name == baseName)
+ {
+ const bool arrayElementZero =
+ (subscript == GL_INVALID_INDEX &&
+ (!uniformBlock.isArray || uniformBlock.arrayElement == 0));
+ if (subscript == uniformBlock.arrayElement || arrayElementZero)
+ {
+ return blockIndex;
+ }
+ }
+ }
+
+ return GL_INVALID_INDEX;
+}
+
+const UniformBlock &Program::getUniformBlockByIndex(GLuint index) const
+{
+ ASSERT(index < static_cast<GLuint>(mState.mUniformBlocks.size()));
+ return mState.mUniformBlocks[index];
+}
+
+void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+{
+ mState.mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
+ mProgram->setUniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
+}
+
+GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
+{
+ return mState.getUniformBlockBinding(uniformBlockIndex);
+}
+
+void Program::resetUniformBlockBindings()
+{
+ for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++)
+ {
+ mState.mUniformBlockBindings[blockId] = 0;
+ }
+ mState.mActiveUniformBlockBindings.reset();
+}
+
+void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
+{
+ mState.mTransformFeedbackVaryingNames.resize(count);
+ for (GLsizei i = 0; i < count; i++)
+ {
+ mState.mTransformFeedbackVaryingNames[i] = varyings[i];
+ }
+
+ mState.mTransformFeedbackBufferMode = bufferMode;
+}
+
+void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
+{
+ if (mLinked)
+ {
+ ASSERT(index < mState.mTransformFeedbackVaryingVars.size());
+ const sh::Varying &varying = mState.mTransformFeedbackVaryingVars[index];
+ GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length()));
+ if (length)
+ {
+ *length = lastNameIdx;
+ }
+ if (size)
+ {
+ *size = varying.elementCount();
+ }
+ if (type)
+ {
+ *type = varying.type;
+ }
+ if (name)
+ {
+ memcpy(name, varying.name.c_str(), lastNameIdx);
+ name[lastNameIdx] = '\0';
+ }
+ }
+}
+
+GLsizei Program::getTransformFeedbackVaryingCount() const
+{
+ if (mLinked)
+ {
+ return static_cast<GLsizei>(mState.mTransformFeedbackVaryingVars.size());
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+GLsizei Program::getTransformFeedbackVaryingMaxLength() const
+{
+ if (mLinked)
+ {
+ GLsizei maxSize = 0;
+ for (const sh::Varying &varying : mState.mTransformFeedbackVaryingVars)
+ {
+ maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1));
+ }
+
+ return maxSize;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+GLenum Program::getTransformFeedbackBufferMode() const
+{
+ return mState.mTransformFeedbackBufferMode;
+}
+
+bool Program::linkVaryings(InfoLog &infoLog,
+ const Shader *vertexShader,
+ const Shader *fragmentShader) const
+{
+ ASSERT(vertexShader->getShaderVersion() == fragmentShader->getShaderVersion());
+
+ const std::vector<sh::Varying> &vertexVaryings = vertexShader->getVaryings();
+ const std::vector<sh::Varying> &fragmentVaryings = fragmentShader->getVaryings();
+
+ std::map<GLuint, std::string> staticFragmentInputLocations;
+
+ for (const sh::Varying &output : fragmentVaryings)
+ {
+ bool matched = false;
+
+ // Built-in varyings obey special rules
+ if (output.isBuiltIn())
+ {
+ continue;
+ }
+
+ for (const sh::Varying &input : vertexVaryings)
+ {
+ if (output.name == input.name)
+ {
+ ASSERT(!input.isBuiltIn());
+ if (!linkValidateVaryings(infoLog, output.name, input, output,
+ vertexShader->getShaderVersion()))
+ {
+ return false;
+ }
+
+ matched = true;
+ break;
+ }
+ }
+
+ // We permit unmatched, unreferenced varyings
+ if (!matched && output.staticUse)
+ {
+ infoLog << "Fragment varying " << output.name << " does not match any vertex varying";
+ return false;
+ }
+
+ // Check for aliased path rendering input bindings (if any).
+ // If more than one binding refer statically to the same
+ // location the link must fail.
+
+ if (!output.staticUse)
+ continue;
+
+ const auto inputBinding = mFragmentInputBindings.getBinding(output.name);
+ if (inputBinding == -1)
+ continue;
+
+ const auto it = staticFragmentInputLocations.find(inputBinding);
+ if (it == std::end(staticFragmentInputLocations))
+ {
+ staticFragmentInputLocations.insert(std::make_pair(inputBinding, output.name));
+ }
+ else
+ {
+ infoLog << "Binding for fragment input " << output.name << " conflicts with "
+ << it->second;
+ return false;
+ }
+ }
+
+ // TODO(jmadill): verify no unmatched vertex varyings?
+
+ return true;
+}
+
+bool Program::validateVertexAndFragmentUniforms(InfoLog &infoLog) const
+{
+ // Check that uniforms defined in the vertex and fragment shaders are identical
+ std::map<std::string, LinkedUniform> linkedUniforms;
+ const std::vector<sh::Uniform> &vertexUniforms = mState.mAttachedVertexShader->getUniforms();
+ const std::vector<sh::Uniform> &fragmentUniforms =
+ mState.mAttachedFragmentShader->getUniforms();
+
+ for (const sh::Uniform &vertexUniform : vertexUniforms)
+ {
+ linkedUniforms[vertexUniform.name] = LinkedUniform(vertexUniform);
+ }
+
+ for (const sh::Uniform &fragmentUniform : fragmentUniforms)
+ {
+ auto entry = linkedUniforms.find(fragmentUniform.name);
+ if (entry != linkedUniforms.end())
+ {
+ LinkedUniform *vertexUniform = &entry->second;
+ const std::string &uniformName = "uniform '" + vertexUniform->name + "'";
+ if (!linkValidateUniforms(infoLog, uniformName, *vertexUniform, fragmentUniform))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool Program::linkUniforms(gl::InfoLog &infoLog,
+ const gl::Caps &caps,
+ const Bindings &uniformBindings)
+{
+ if (mState.mAttachedVertexShader && mState.mAttachedFragmentShader)
+ {
+ ASSERT(mState.mAttachedComputeShader == nullptr);
+ if (!validateVertexAndFragmentUniforms(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 (!indexUniforms(infoLog, caps, uniformBindings))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::indexUniforms(gl::InfoLog &infoLog,
+ const gl::Caps &caps,
+ const Bindings &uniformBindings)
+{
+ // Uniforms awaiting a location
+ std::vector<VariableLocation> unboundUniforms;
+ std::map<GLuint, VariableLocation> boundUniforms;
+ int maxUniformLocation = -1;
+
+ // Gather bound and unbound uniforms
+ for (size_t uniformIndex = 0; uniformIndex < mState.mUniforms.size(); uniformIndex++)
+ {
+ const gl::LinkedUniform &uniform = mState.mUniforms[uniformIndex];
+
+ if (uniform.isBuiltIn())
+ {
+ continue;
+ }
+
+ int bindingLocation = uniformBindings.getBinding(uniform.name);
+
+ // Verify that this location isn't bound twice
+ if (bindingLocation != -1 && boundUniforms.find(bindingLocation) != boundUniforms.end())
+ {
+ infoLog << "Multiple uniforms bound to location " << bindingLocation << ".";
+ return false;
+ }
+
+ for (unsigned int arrayIndex = 0; arrayIndex < uniform.elementCount(); arrayIndex++)
+ {
+ VariableLocation location(uniform.name, arrayIndex,
+ static_cast<unsigned int>(uniformIndex));
+
+ if (arrayIndex == 0 && bindingLocation != -1)
+ {
+ boundUniforms[bindingLocation] = location;
+ maxUniformLocation = std::max(maxUniformLocation, bindingLocation);
+ }
+ else
+ {
+ unboundUniforms.push_back(location);
+ }
+ }
+ }
+
+ // Gather the reserved bindings, ones that are bound but not referenced. Other uniforms should
+ // not be assigned to those locations.
+ std::set<GLuint> reservedLocations;
+ for (const auto &binding : uniformBindings)
+ {
+ GLuint location = binding.second;
+ if (boundUniforms.find(location) == boundUniforms.end())
+ {
+ reservedLocations.insert(location);
+ maxUniformLocation = std::max(maxUniformLocation, static_cast<int>(location));
+ }
+ }
+
+ // Make enough space for all uniforms, bound and unbound
+ mState.mUniformLocations.resize(
+ std::max(unboundUniforms.size() + boundUniforms.size() + reservedLocations.size(),
+ static_cast<size_t>(maxUniformLocation + 1)));
+
+ // Assign bound uniforms
+ for (const auto &boundUniform : boundUniforms)
+ {
+ mState.mUniformLocations[boundUniform.first] = boundUniform.second;
+ }
+
+ // Assign reserved uniforms
+ for (const auto &reservedLocation : reservedLocations)
+ {
+ mState.mUniformLocations[reservedLocation].ignored = true;
+ }
+
+ // Assign unbound uniforms
+ size_t nextUniformLocation = 0;
+ for (const auto &unboundUniform : unboundUniforms)
+ {
+ while (mState.mUniformLocations[nextUniformLocation].used ||
+ mState.mUniformLocations[nextUniformLocation].ignored)
+ {
+ nextUniformLocation++;
+ }
+
+ ASSERT(nextUniformLocation < mState.mUniformLocations.size());
+ mState.mUniformLocations[nextUniformLocation] = unboundUniform;
+ nextUniformLocation++;
+ }
+
+ return true;
+}
+
+bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog,
+ const std::string &uniformName,
+ const sh::InterfaceBlockField &vertexUniform,
+ const sh::InterfaceBlockField &fragmentUniform)
+{
+ // We don't validate precision on UBO fields. See resolution of Khronos bug 10287.
+ if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, false))
+ {
+ return false;
+ }
+
+ if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout)
+ {
+ infoLog << "Matrix packings for " << uniformName << " differ between vertex and fragment shaders";
+ return false;
+ }
+
+ return true;
+}
+
+// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
+bool Program::linkAttributes(const ContextState &data,
+ InfoLog &infoLog,
+ const Bindings &attributeBindings,
+ const Shader *vertexShader)
+{
+ unsigned int usedLocations = 0;
+ mState.mAttributes = vertexShader->getActiveAttributes();
+ GLuint maxAttribs = data.getCaps().maxVertexAttributes;
+
+ // TODO(jmadill): handle aliasing robustly
+ if (mState.mAttributes.size() > maxAttribs)
+ {
+ infoLog << "Too many vertex attributes.";
+ return false;
+ }
+
+ std::vector<sh::Attribute *> usedAttribMap(maxAttribs, nullptr);
+
+ // Link attributes that have a binding location
+ for (sh::Attribute &attribute : mState.mAttributes)
+ {
+ // TODO(jmadill): do staticUse filtering step here, or not at all
+ ASSERT(attribute.staticUse);
+
+ int bindingLocation = attributeBindings.getBinding(attribute.name);
+ 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 << "Active 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 3.00, attribute aliasing produces a link error
+ // In GLSL 1.00, attribute aliasing is allowed, but ANGLE currently has a bug
+ if (linkedAttribute)
+ {
+ // TODO(jmadill): fix aliasing on ES2
+ // if (mProgram->getShaderVersion() >= 300)
+ {
+ infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
+ << linkedAttribute->name << "' at location " << regLocation;
+ return false;
+ }
+ }
+ else
+ {
+ usedAttribMap[regLocation] = &attribute;
+ }
+
+ usedLocations |= 1 << regLocation;
+ }
+ }
+ }
+
+ // Link attributes that don't have a binding location
+ for (sh::Attribute &attribute : mState.mAttributes)
+ {
+ ASSERT(attribute.staticUse);
+
+ // 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 active attributes (" << attribute.name << ")";
+ return false;
+ }
+
+ attribute.location = availableIndex;
+ }
+ }
+
+ for (const sh::Attribute &attribute : mState.mAttributes)
+ {
+ ASSERT(attribute.staticUse);
+ ASSERT(attribute.location != -1);
+ int regs = VariableRegisterCount(attribute.type);
+
+ for (int r = 0; r < regs; r++)
+ {
+ mState.mActiveAttribLocationsMask.set(attribute.location + r);
+ }
+ }
+
+ return true;
+}
+
+bool Program::validateUniformBlocksCount(GLuint maxUniformBlocks,
+ const std::vector<sh::InterfaceBlock> &intefaceBlocks,
+ const std::string &errorMessage,
+ InfoLog &infoLog) const
+{
+ GLuint blockCount = 0;
+ for (const sh::InterfaceBlock &block : intefaceBlocks)
+ {
+ if (block.staticUse || block.layout != sh::BLOCKLAYOUT_PACKED)
+ {
+ if (++blockCount > maxUniformBlocks)
+ {
+ infoLog << errorMessage << maxUniformBlocks << ")";
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool Program::validateVertexAndFragmentInterfaceBlocks(
+ const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
+ const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks,
+ InfoLog &infoLog) const
+{
+ // Check that interface blocks defined in the vertex and fragment shaders are identical
+ typedef std::map<std::string, const sh::InterfaceBlock *> UniformBlockMap;
+ UniformBlockMap linkedUniformBlocks;
+
+ for (const sh::InterfaceBlock &vertexInterfaceBlock : vertexInterfaceBlocks)
+ {
+ linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
+ }
+
+ for (const sh::InterfaceBlock &fragmentInterfaceBlock : fragmentInterfaceBlocks)
+ {
+ auto entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name);
+ if (entry != linkedUniformBlocks.end())
+ {
+ const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
+ if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool Program::linkUniformBlocks(InfoLog &infoLog, const Caps &caps)
+{
+ if (mState.mAttachedComputeShader)
+ {
+ const Shader &computeShader = *mState.mAttachedComputeShader;
+ const auto &computeInterfaceBlocks = computeShader.getInterfaceBlocks();
+
+ if (!validateUniformBlocksCount(
+ caps.maxComputeUniformBlocks, computeInterfaceBlocks,
+ "Compute shader uniform block count exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS (",
+ infoLog))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ const Shader &vertexShader = *mState.mAttachedVertexShader;
+ const Shader &fragmentShader = *mState.mAttachedFragmentShader;
+
+ const auto &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks();
+ const auto &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks();
+
+ if (!validateUniformBlocksCount(
+ caps.maxVertexUniformBlocks, vertexInterfaceBlocks,
+ "Vertex shader uniform block count exceeds GL_MAX_VERTEX_UNIFORM_BLOCKS (", infoLog))
+ {
+ return false;
+ }
+ if (!validateUniformBlocksCount(
+ caps.maxFragmentUniformBlocks, fragmentInterfaceBlocks,
+ "Fragment shader uniform block count exceeds GL_MAX_FRAGMENT_UNIFORM_BLOCKS (",
+ infoLog))
+ {
+
+ return false;
+ }
+ if (!validateVertexAndFragmentInterfaceBlocks(vertexInterfaceBlocks, fragmentInterfaceBlocks,
+ infoLog))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::areMatchingInterfaceBlocks(gl::InfoLog &infoLog,
+ const sh::InterfaceBlock &vertexInterfaceBlock,
+ const sh::InterfaceBlock &fragmentInterfaceBlock) const
+{
+ const char* blockName = vertexInterfaceBlock.name.c_str();
+ // validate blocks for the same member types
+ if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size())
+ {
+ infoLog << "Types for interface block '" << blockName
+ << "' differ between vertex and fragment shaders";
+ return false;
+ }
+ if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize)
+ {
+ infoLog << "Array sizes differ for interface block '" << blockName
+ << "' between vertex and fragment shaders";
+ return false;
+ }
+ if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
+ {
+ infoLog << "Layout qualifiers differ for interface block '" << blockName
+ << "' between vertex and fragment shaders";
+ return false;
+ }
+ const unsigned int numBlockMembers =
+ static_cast<unsigned int>(vertexInterfaceBlock.fields.size());
+ for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
+ {
+ const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex];
+ const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex];
+ if (vertexMember.name != fragmentMember.name)
+ {
+ infoLog << "Name mismatch for field " << blockMemberIndex
+ << " of interface block '" << blockName
+ << "': (in vertex: '" << vertexMember.name
+ << "', in fragment: '" << fragmentMember.name << "')";
+ return false;
+ }
+ std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
+ if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable,
+ const sh::ShaderVariable &fragmentVariable, bool validatePrecision)
+{
+ if (vertexVariable.type != fragmentVariable.type)
+ {
+ infoLog << "Types for " << variableName << " differ between vertex and fragment shaders";
+ return false;
+ }
+ if (vertexVariable.arraySize != fragmentVariable.arraySize)
+ {
+ infoLog << "Array sizes for " << variableName << " differ between vertex and fragment shaders";
+ return false;
+ }
+ if (validatePrecision && vertexVariable.precision != fragmentVariable.precision)
+ {
+ infoLog << "Precisions for " << variableName << " differ between vertex and fragment shaders";
+ return false;
+ }
+
+ if (vertexVariable.fields.size() != fragmentVariable.fields.size())
+ {
+ infoLog << "Structure lengths for " << variableName << " differ between vertex and fragment shaders";
+ return false;
+ }
+ const unsigned int numMembers = static_cast<unsigned int>(vertexVariable.fields.size());
+ for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
+ {
+ const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex];
+ const sh::ShaderVariable &fragmentMember = fragmentVariable.fields[memberIndex];
+
+ if (vertexMember.name != fragmentMember.name)
+ {
+ infoLog << "Name mismatch for field '" << memberIndex
+ << "' of " << variableName
+ << ": (in vertex: '" << vertexMember.name
+ << "', in fragment: '" << fragmentMember.name << "')";
+ return false;
+ }
+
+ const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." +
+ vertexMember.name + "'";
+
+ if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool Program::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform)
+{
+#if ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION == ANGLE_ENABLED
+ const bool validatePrecision = true;
+#else
+ const bool validatePrecision = false;
+#endif
+
+ if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, validatePrecision))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::linkValidateVaryings(InfoLog &infoLog,
+ const std::string &varyingName,
+ const sh::Varying &vertexVarying,
+ const sh::Varying &fragmentVarying,
+ int shaderVersion)
+{
+ if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
+ {
+ return false;
+ }
+
+ if (!sh::InterpolationTypesMatch(vertexVarying.interpolation, fragmentVarying.interpolation))
+ {
+ infoLog << "Interpolation types for " << varyingName
+ << " differ between vertex and fragment shaders.";
+ return false;
+ }
+
+ if (shaderVersion == 100 && vertexVarying.isInvariant != fragmentVarying.isInvariant)
+ {
+ infoLog << "Invariance for " << varyingName
+ << " differs between vertex and fragment shaders.";
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::linkValidateTransformFeedback(InfoLog &infoLog,
+ const std::vector<const sh::Varying *> &varyings,
+ const Caps &caps) const
+{
+ size_t totalComponents = 0;
+
+ std::set<std::string> uniqueNames;
+
+ for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
+ {
+ bool found = false;
+ for (const sh::Varying *varying : varyings)
+ {
+ if (tfVaryingName == varying->name)
+ {
+ if (uniqueNames.count(tfVaryingName) > 0)
+ {
+ infoLog << "Two transform feedback varyings specify the same output variable ("
+ << tfVaryingName << ").";
+ return false;
+ }
+ uniqueNames.insert(tfVaryingName);
+
+ if (varying->isArray())
+ {
+ infoLog << "Capture of arrays is undefined and not supported.";
+ return false;
+ }
+
+ // TODO(jmadill): Investigate implementation limits on D3D11
+ size_t componentCount = gl::VariableComponentCount(varying->type);
+ if (mState.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
+ componentCount > caps.maxTransformFeedbackSeparateComponents)
+ {
+ infoLog << "Transform feedback varying's " << varying->name << " components ("
+ << componentCount << ") exceed the maximum separate components ("
+ << caps.maxTransformFeedbackSeparateComponents << ").";
+ return false;
+ }
+
+ totalComponents += componentCount;
+ found = true;
+ break;
+ }
+ }
+
+ if (tfVaryingName.find('[') != std::string::npos)
+ {
+ infoLog << "Capture of array elements is undefined and not supported.";
+ return false;
+ }
+
+ // All transform feedback varyings are expected to exist since packVaryings checks for them.
+ ASSERT(found);
+ }
+
+ if (mState.mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
+ totalComponents > caps.maxTransformFeedbackInterleavedComponents)
+ {
+ infoLog << "Transform feedback varying total components (" << totalComponents
+ << ") exceed the maximum interleaved components ("
+ << caps.maxTransformFeedbackInterleavedComponents << ").";
+ return false;
+ }
+
+ return true;
+}
+
+void Program::gatherTransformFeedbackVaryings(const std::vector<const sh::Varying *> &varyings)
+{
+ // Gather the linked varyings that are used for transform feedback, they should all exist.
+ mState.mTransformFeedbackVaryingVars.clear();
+ for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
+ {
+ for (const sh::Varying *varying : varyings)
+ {
+ if (tfVaryingName == varying->name)
+ {
+ mState.mTransformFeedbackVaryingVars.push_back(*varying);
+ break;
+ }
+ }
+ }
+}
+
+std::vector<const sh::Varying *> Program::getMergedVaryings() const
+{
+ std::set<std::string> uniqueNames;
+ std::vector<const sh::Varying *> varyings;
+
+ for (const sh::Varying &varying : mState.mAttachedVertexShader->getVaryings())
+ {
+ if (uniqueNames.count(varying.name) == 0)
+ {
+ uniqueNames.insert(varying.name);
+ varyings.push_back(&varying);
+ }
+ }
+
+ for (const sh::Varying &varying : mState.mAttachedFragmentShader->getVaryings())
+ {
+ if (uniqueNames.count(varying.name) == 0)
+ {
+ uniqueNames.insert(varying.name);
+ varyings.push_back(&varying);
+ }
+ }
+
+ return varyings;
+}
+
+void Program::linkOutputVariables()
+{
+ const Shader *fragmentShader = mState.mAttachedFragmentShader;
+ ASSERT(fragmentShader != nullptr);
+
+ // Skip this step for GLES2 shaders.
+ if (fragmentShader->getShaderVersion() == 100)
+ return;
+
+ const auto &shaderOutputVars = fragmentShader->getActiveOutputVariables();
+
+ // TODO(jmadill): any caps validation here?
+
+ for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size();
+ outputVariableIndex++)
+ {
+ const sh::OutputVariable &outputVariable = shaderOutputVars[outputVariableIndex];
+
+ // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
+ if (outputVariable.isBuiltIn())
+ continue;
+
+ // Since multiple output locations must be specified, use 0 for non-specified locations.
+ int baseLocation = (outputVariable.location == -1 ? 0 : outputVariable.location);
+
+ ASSERT(outputVariable.staticUse);
+
+ for (unsigned int elementIndex = 0; elementIndex < outputVariable.elementCount();
+ elementIndex++)
+ {
+ const int location = baseLocation + elementIndex;
+ ASSERT(mState.mOutputVariables.count(location) == 0);
+ unsigned int element = outputVariable.isArray() ? elementIndex : GL_INVALID_INDEX;
+ mState.mOutputVariables[location] =
+ VariableLocation(outputVariable.name, element, outputVariableIndex);
+ }
+ }
+}
+
+bool Program::flattenUniformsAndCheckCapsForShader(const gl::Shader &shader,
+ GLuint maxUniformComponents,
+ GLuint maxTextureImageUnits,
+ const std::string &componentsErrorMessage,
+ const std::string &samplerErrorMessage,
+ std::vector<LinkedUniform> &samplerUniforms,
+ InfoLog &infoLog)
+{
+ VectorAndSamplerCount vasCount;
+ for (const sh::Uniform &uniform : shader.getUniforms())
+ {
+ if (uniform.staticUse)
+ {
+ vasCount += flattenUniform(uniform, uniform.name, &samplerUniforms);
+ }
+ }
+
+ if (vasCount.vectorCount > maxUniformComponents)
+ {
+ infoLog << componentsErrorMessage << maxUniformComponents << ").";
+ return false;
+ }
+
+ if (vasCount.samplerCount > maxTextureImageUnits)
+ {
+ infoLog << samplerErrorMessage << maxTextureImageUnits << ").";
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog)
+{
+ std::vector<LinkedUniform> samplerUniforms;
+
+ if (mState.mAttachedComputeShader)
+ {
+ const gl::Shader *computeShader = mState.getAttachedComputeShader();
+
+ // TODO (mradev): check whether we need finer-grained component counting
+ if (!flattenUniformsAndCheckCapsForShader(
+ *computeShader, caps.maxComputeUniformComponents / 4,
+ caps.maxComputeTextureImageUnits,
+ "Compute shader active uniforms exceed MAX_COMPUTE_UNIFORM_COMPONENTS (",
+ "Compute shader sampler count exceeds MAX_COMPUTE_TEXTURE_IMAGE_UNITS (",
+ samplerUniforms, infoLog))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ const gl::Shader *vertexShader = mState.getAttachedVertexShader();
+
+ if (!flattenUniformsAndCheckCapsForShader(
+ *vertexShader, caps.maxVertexUniformVectors, caps.maxVertexTextureImageUnits,
+ "Vertex shader active uniforms exceed MAX_VERTEX_UNIFORM_VECTORS (",
+ "Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (",
+ samplerUniforms, infoLog))
+ {
+ return false;
+ }
+ const gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
+
+ if (!flattenUniformsAndCheckCapsForShader(
+ *fragmentShader, caps.maxFragmentUniformVectors, caps.maxTextureImageUnits,
+ "Fragment shader active uniforms exceed MAX_FRAGMENT_UNIFORM_VECTORS (",
+ "Fragment shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (", samplerUniforms,
+ infoLog))
+ {
+ return false;
+ }
+ }
+
+ mSamplerUniformRange.start = static_cast<unsigned int>(mState.mUniforms.size());
+ mSamplerUniformRange.end =
+ mSamplerUniformRange.start + static_cast<unsigned int>(samplerUniforms.size());
+
+ mState.mUniforms.insert(mState.mUniforms.end(), samplerUniforms.begin(), samplerUniforms.end());
+
+ return true;
+}
+
+Program::VectorAndSamplerCount Program::flattenUniform(const sh::ShaderVariable &uniform,
+ const std::string &fullName,
+ std::vector<LinkedUniform> *samplerUniforms)
+{
+ VectorAndSamplerCount vectorAndSamplerCount;
+
+ if (uniform.isStruct())
+ {
+ for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
+ {
+ const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
+
+ for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
+ {
+ const sh::ShaderVariable &field = uniform.fields[fieldIndex];
+ const std::string &fieldFullName = (fullName + elementString + "." + field.name);
+
+ vectorAndSamplerCount += flattenUniform(field, fieldFullName, samplerUniforms);
+ }
+ }
+
+ return vectorAndSamplerCount;
+ }
+
+ // Not a struct
+ bool isSampler = IsSamplerType(uniform.type);
+ if (!UniformInList(mState.getUniforms(), fullName) &&
+ !UniformInList(*samplerUniforms, fullName))
+ {
+ gl::LinkedUniform linkedUniform(uniform.type, uniform.precision, fullName,
+ uniform.arraySize, -1,
+ sh::BlockMemberInfo::getDefaultBlockInfo());
+ linkedUniform.staticUse = true;
+
+ // Store sampler uniforms separately, so we'll append them to the end of the list.
+ if (isSampler)
+ {
+ samplerUniforms->push_back(linkedUniform);
+ }
+ else
+ {
+ mState.mUniforms.push_back(linkedUniform);
+ }
+ }
+
+ unsigned int elementCount = uniform.elementCount();
+
+ // Samplers aren't "real" uniforms, so they don't count towards register usage.
+ // Likewise, don't count "real" uniforms towards sampler count.
+ vectorAndSamplerCount.vectorCount =
+ (isSampler ? 0 : (VariableRegisterCount(uniform.type) * elementCount));
+ vectorAndSamplerCount.samplerCount = (isSampler ? elementCount : 0);
+
+ return vectorAndSamplerCount;
+}
+
+void Program::gatherInterfaceBlockInfo()
+{
+ ASSERT(mState.mUniformBlocks.empty());
+
+ if (mState.mAttachedComputeShader)
+ {
+ const gl::Shader *computeShader = mState.getAttachedComputeShader();
+
+ for (const sh::InterfaceBlock &computeBlock : computeShader->getInterfaceBlocks())
+ {
+
+ // Only 'packed' blocks are allowed to be considered inactive.
+ if (!computeBlock.staticUse && computeBlock.layout == sh::BLOCKLAYOUT_PACKED)
+ continue;
+
+ for (gl::UniformBlock &block : mState.mUniformBlocks)
+ {
+ if (block.name == computeBlock.name)
+ {
+ block.computeStaticUse = computeBlock.staticUse;
+ }
+ }
+
+ defineUniformBlock(computeBlock, GL_COMPUTE_SHADER);
+ }
+ return;
+ }
+
+ std::set<std::string> visitedList;
+
+ const gl::Shader *vertexShader = mState.getAttachedVertexShader();
+
+ for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
+ {
+ // Only 'packed' blocks are allowed to be considered inactive.
+ if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
+ continue;
+
+ if (visitedList.count(vertexBlock.name) > 0)
+ continue;
+
+ defineUniformBlock(vertexBlock, GL_VERTEX_SHADER);
+ visitedList.insert(vertexBlock.name);
+ }
+
+ const gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
+
+ for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
+ {
+ // Only 'packed' blocks are allowed to be considered inactive.
+ if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
+ continue;
+
+ if (visitedList.count(fragmentBlock.name) > 0)
+ {
+ for (gl::UniformBlock &block : mState.mUniformBlocks)
+ {
+ if (block.name == fragmentBlock.name)
+ {
+ block.fragmentStaticUse = fragmentBlock.staticUse;
+ }
+ }
+
+ continue;
+ }
+
+ defineUniformBlock(fragmentBlock, GL_FRAGMENT_SHADER);
+ visitedList.insert(fragmentBlock.name);
+ }
+}
+
+template <typename VarT>
+void Program::defineUniformBlockMembers(const std::vector<VarT> &fields,
+ const std::string &prefix,
+ int blockIndex)
+{
+ for (const VarT &field : fields)
+ {
+ const std::string &fullName = (prefix.empty() ? field.name : prefix + "." + field.name);
+
+ if (field.isStruct())
+ {
+ for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
+ {
+ const std::string uniformElementName =
+ fullName + (field.isArray() ? ArrayString(arrayElement) : "");
+ defineUniformBlockMembers(field.fields, uniformElementName, blockIndex);
+ }
+ }
+ else
+ {
+ // If getBlockMemberInfo returns false, the uniform is optimized out.
+ sh::BlockMemberInfo memberInfo;
+ if (!mProgram->getUniformBlockMemberInfo(fullName, &memberInfo))
+ {
+ continue;
+ }
+
+ LinkedUniform newUniform(field.type, field.precision, fullName, field.arraySize,
+ blockIndex, memberInfo);
+
+ // Since block uniforms have no location, we don't need to store them in the uniform
+ // locations list.
+ mState.mUniforms.push_back(newUniform);
+ }
+ }
+}
+
+void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType)
+{
+ int blockIndex = static_cast<int>(mState.mUniformBlocks.size());
+ size_t blockSize = 0;
+
+ // Don't define this block at all if it's not active in the implementation.
+ std::stringstream blockNameStr;
+ blockNameStr << interfaceBlock.name;
+ if (interfaceBlock.arraySize > 0)
+ {
+ blockNameStr << "[0]";
+ }
+ if (!mProgram->getUniformBlockSize(blockNameStr.str(), &blockSize))
+ {
+ return;
+ }
+
+ // Track the first and last uniform index to determine the range of active uniforms in the
+ // block.
+ size_t firstBlockUniformIndex = mState.mUniforms.size();
+ defineUniformBlockMembers(interfaceBlock.fields, interfaceBlock.fieldPrefix(), blockIndex);
+ size_t lastBlockUniformIndex = mState.mUniforms.size();
+
+ std::vector<unsigned int> blockUniformIndexes;
+ for (size_t blockUniformIndex = firstBlockUniformIndex;
+ blockUniformIndex < lastBlockUniformIndex; ++blockUniformIndex)
+ {
+ blockUniformIndexes.push_back(static_cast<unsigned int>(blockUniformIndex));
+ }
+
+ if (interfaceBlock.arraySize > 0)
+ {
+ for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.arraySize; ++arrayElement)
+ {
+ UniformBlock block(interfaceBlock.name, true, arrayElement);
+ block.memberUniformIndexes = blockUniformIndexes;
+
+ switch (shaderType)
+ {
+ case GL_VERTEX_SHADER:
+ {
+ block.vertexStaticUse = interfaceBlock.staticUse;
+ break;
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ block.fragmentStaticUse = interfaceBlock.staticUse;
+ break;
+ }
+ case GL_COMPUTE_SHADER:
+ {
+ block.computeStaticUse = interfaceBlock.staticUse;
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ // Since all block elements in an array share the same active uniforms, they will all be
+ // active once any uniform 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);
+ mState.mUniformBlocks.push_back(block);
+ }
+ }
+ else
+ {
+ UniformBlock block(interfaceBlock.name, false, 0);
+ block.memberUniformIndexes = blockUniformIndexes;
+
+ switch (shaderType)
+ {
+ case GL_VERTEX_SHADER:
+ {
+ block.vertexStaticUse = interfaceBlock.staticUse;
+ break;
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ block.fragmentStaticUse = interfaceBlock.staticUse;
+ break;
+ }
+ case GL_COMPUTE_SHADER:
+ {
+ block.computeStaticUse = interfaceBlock.staticUse;
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ block.dataSize = static_cast<unsigned int>(blockSize);
+ mState.mUniformBlocks.push_back(block);
+ }
+}
+
+template <typename T>
+GLsizei Program::setUniformInternal(GLint location, GLsizei countIn, int vectorSize, const T *v)
+{
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ LinkedUniform *linkedUniform = &mState.mUniforms[locationInfo.index];
+ uint8_t *destPointer = linkedUniform->getDataPtrToElement(locationInfo.element);
+
+ // 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->elementCount() - locationInfo.element;
+ GLsizei maxElementCount =
+ static_cast<GLsizei>(remainingElements * linkedUniform->getElementComponents());
+
+ GLsizei count = countIn;
+ GLsizei clampedCount = count * vectorSize;
+ if (clampedCount > maxElementCount)
+ {
+ clampedCount = maxElementCount;
+ count = maxElementCount / vectorSize;
+ }
+
+ if (VariableComponentType(linkedUniform->type) == GL_BOOL)
+ {
+ // Do a cast conversion for boolean types. From the spec:
+ // "The uniform is set to FALSE if the input value is 0 or 0.0f, and set to TRUE otherwise."
+ GLint *destAsInt = reinterpret_cast<GLint *>(destPointer);
+ for (GLsizei component = 0; component < clampedCount; ++component)
+ {
+ destAsInt[component] = (v[component] != static_cast<T>(0) ? GL_TRUE : GL_FALSE);
+ }
+ }
+ else
+ {
+ // Invalide the validation cache if we modify the sampler data.
+ if (linkedUniform->isSampler() && memcmp(destPointer, v, sizeof(T) * clampedCount) != 0)
+ {
+ mCachedValidateSamplersResult.reset();
+ }
+
+ memcpy(destPointer, v, sizeof(T) * clampedCount);
+ }
+
+ return count;
+}
+
+template <size_t cols, size_t rows, typename T>
+GLsizei Program::setMatrixUniformInternal(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const T *v)
+{
+ if (!transpose)
+ {
+ return setUniformInternal(location, count, cols * rows, v);
+ }
+
+ // Perform a transposing copy.
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ LinkedUniform *linkedUniform = &mState.mUniforms[locationInfo.index];
+ T *destPtr = reinterpret_cast<T *>(linkedUniform->getDataPtrToElement(locationInfo.element));
+
+ // 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->elementCount() - locationInfo.element;
+ GLsizei clampedCount = std::min(count, static_cast<GLsizei>(remainingElements));
+
+ for (GLsizei element = 0; element < clampedCount; ++element)
+ {
+ size_t elementOffset = element * rows * cols;
+
+ for (size_t row = 0; row < rows; ++row)
+ {
+ for (size_t col = 0; col < cols; ++col)
+ {
+ destPtr[col * rows + row + elementOffset] = v[row * cols + col + elementOffset];
+ }
+ }
+ }
+
+ return clampedCount;
+}
+
+template <typename DestT>
+void Program::getUniformInternal(GLint location, DestT *dataOut) const
+{
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ const LinkedUniform &uniform = mState.mUniforms[locationInfo.index];
+
+ const uint8_t *srcPointer = uniform.getDataPtrToElement(locationInfo.element);
+
+ GLenum componentType = VariableComponentType(uniform.type);
+ if (componentType == GLTypeToGLenum<DestT>::value)
+ {
+ memcpy(dataOut, srcPointer, uniform.getElementSize());
+ return;
+ }
+
+ int components = VariableComponentCount(uniform.type);
+
+ switch (componentType)
+ {
+ case GL_INT:
+ UniformStateQueryCastLoop<GLint>(dataOut, srcPointer, components);
+ break;
+ case GL_UNSIGNED_INT:
+ UniformStateQueryCastLoop<GLuint>(dataOut, srcPointer, components);
+ break;
+ case GL_BOOL:
+ UniformStateQueryCastLoop<GLboolean>(dataOut, srcPointer, components);
+ break;
+ case GL_FLOAT:
+ UniformStateQueryCastLoop<GLfloat>(dataOut, srcPointer, components);
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+}
diff --git a/gfx/angle/src/libANGLE/Program.h b/gfx/angle/src/libANGLE/Program.h
new file mode 100755
index 000000000..18bec495f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Program.h
@@ -0,0 +1,504 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/ShaderLang.h>
+
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "common/Optional.h"
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class GLImplFactory;
+class ProgramImpl;
+struct TranslatedAttribute;
+}
+
+namespace gl
+{
+struct Caps;
+class ContextState;
+class ResourceManager;
+class Shader;
+class InfoLog;
+class Buffer;
+class Framebuffer;
+struct UniformBlock;
+struct LinkedUniform;
+
+extern const char * const g_fakepath;
+
+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) << 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)
+ {
+ StreamHelper helper(&mStream);
+ helper << value;
+ return helper;
+ }
+
+ std::string str() const { return mStream.str(); }
+
+ private:
+ std::stringstream mStream;
+};
+
+// Struct used for correlating uniforms/elements of uniform arrays to handles
+struct VariableLocation
+{
+ VariableLocation();
+ VariableLocation(const std::string &name, unsigned int element, unsigned int index);
+
+ std::string name;
+ unsigned int element;
+ unsigned int index;
+
+ // If this is a valid uniform location
+ bool used;
+
+ // 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;
+};
+
+class ProgramState final : angle::NonCopyable
+{
+ public:
+ ProgramState();
+ ~ProgramState();
+
+ const std::string &getLabel();
+
+ const Shader *getAttachedVertexShader() const { return mAttachedVertexShader; }
+ const Shader *getAttachedFragmentShader() const { return mAttachedFragmentShader; }
+ const Shader *getAttachedComputeShader() const { return mAttachedComputeShader; }
+ const std::vector<std::string> &getTransformFeedbackVaryingNames() const
+ {
+ return mTransformFeedbackVaryingNames;
+ }
+ GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
+ GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
+ {
+ ASSERT(uniformBlockIndex < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
+ return mUniformBlockBindings[uniformBlockIndex];
+ }
+ const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
+ {
+ return mActiveUniformBlockBindings;
+ }
+ const std::vector<sh::Attribute> &getAttributes() const { return mAttributes; }
+ const AttributesMask &getActiveAttribLocationsMask() const
+ {
+ return mActiveAttribLocationsMask;
+ }
+ const std::map<int, VariableLocation> &getOutputVariables() const { return mOutputVariables; }
+ const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
+ const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
+ const std::vector<UniformBlock> &getUniformBlocks() const { return mUniformBlocks; }
+
+ const LinkedUniform *getUniformByName(const std::string &name) const;
+ GLint getUniformLocation(const std::string &name) const;
+ GLuint getUniformIndex(const std::string &name) const;
+
+ private:
+ friend class Program;
+
+ std::string mLabel;
+
+ sh::WorkGroupSize mComputeShaderLocalSize;
+
+ Shader *mAttachedFragmentShader;
+ Shader *mAttachedVertexShader;
+ Shader *mAttachedComputeShader;
+
+ std::vector<std::string> mTransformFeedbackVaryingNames;
+ std::vector<sh::Varying> mTransformFeedbackVaryingVars;
+ GLenum mTransformFeedbackBufferMode;
+
+ GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
+ UniformBlockBindingMask mActiveUniformBlockBindings;
+
+ std::vector<sh::Attribute> mAttributes;
+ std::bitset<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
+
+ // Uniforms are sorted in order:
+ // 1. Non-sampler uniforms
+ // 2. Sampler uniforms
+ // 3. Uniform block uniforms
+ // This makes sampler validation easier, since we don't need a separate list.
+ std::vector<LinkedUniform> mUniforms;
+ std::vector<VariableLocation> mUniformLocations;
+ std::vector<UniformBlock> mUniformBlocks;
+
+ // TODO(jmadill): use unordered/hash map when available
+ std::map<int, VariableLocation> mOutputVariables;
+
+ bool mBinaryRetrieveableHint;
+};
+
+class Program final : angle::NonCopyable, public LabeledObject
+{
+ public:
+ Program(rx::GLImplFactory *factory, ResourceManager *manager, GLuint handle);
+ ~Program();
+
+ GLuint id() const { return mHandle; }
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ rx::ProgramImpl *getImplementation() const { return mProgram; }
+
+ void attachShader(Shader *shader);
+ bool detachShader(Shader *shader);
+ int getAttachedShadersCount() const;
+
+ const Shader *getAttachedVertexShader() const { return mState.mAttachedVertexShader; }
+ const Shader *getAttachedFragmentShader() const { return mState.mAttachedFragmentShader; }
+ const Shader *getAttachedComputeShader() const { return mState.mAttachedComputeShader; }
+
+ void bindAttributeLocation(GLuint index, const char *name);
+ void bindUniformLocation(GLuint index, const char *name);
+
+ // CHROMIUM_path_rendering
+ BindingInfo getFragmentInputBindingInfo(GLint index) const;
+ void bindFragmentInputLocation(GLint index, const char *name);
+ void pathFragmentInputGen(GLint index,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs);
+
+ Error link(const ContextState &data);
+ bool isLinked() const;
+
+ Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length);
+ Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const;
+ GLint getBinaryLength() const;
+ void setBinaryRetrievableHint(bool retrievable);
+ bool getBinaryRetrievableHint() const;
+
+ int getInfoLogLength() const;
+ void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+ void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const;
+
+ GLuint getAttributeLocation(const std::string &name) const;
+ bool isAttribLocationActive(size_t attribLocation) const;
+
+ void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+ GLint getActiveAttributeCount() const;
+ GLint getActiveAttributeMaxLength() const;
+ const std::vector<sh::Attribute> &getAttributes() const { return mState.mAttributes; }
+
+ GLint getFragDataLocation(const std::string &name) const;
+
+ void getActiveUniform(GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name) const;
+ GLint getActiveUniformCount() const;
+ GLint getActiveUniformMaxLength() const;
+ GLint getActiveUniformi(GLuint index, GLenum pname) const;
+ bool isValidUniformLocation(GLint location) const;
+ bool isIgnoredUniformLocation(GLint location) const;
+ const LinkedUniform &getUniformByLocation(GLint location) const;
+
+ GLint getUniformLocation(const std::string &name) const;
+ GLuint getUniformIndex(const std::string &name) const;
+ void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
+ void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
+ void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
+ void setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
+ void setUniform1iv(GLint location, GLsizei count, const GLint *v);
+ void setUniform2iv(GLint location, GLsizei count, const GLint *v);
+ void setUniform3iv(GLint location, GLsizei count, const GLint *v);
+ void setUniform4iv(GLint location, GLsizei count, const GLint *v);
+ void setUniform1uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniform2uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniform3uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniform4uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+ void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+ void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+ void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+ void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+ void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+ void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+ void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+ void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+
+ void getUniformfv(GLint location, GLfloat *params) const;
+ void getUniformiv(GLint location, GLint *params) const;
+ void getUniformuiv(GLint location, GLuint *params) const;
+
+ void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const;
+ GLuint getActiveUniformBlockCount() const;
+ GLint getActiveUniformBlockMaxLength() const;
+
+ GLuint getUniformBlockIndex(const std::string &name) const;
+
+ void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+ GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
+
+ const UniformBlock &getUniformBlockByIndex(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;
+
+ static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
+ static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
+
+ void addRef();
+ void release();
+ unsigned int getRefCount() const;
+ void flagForDeletion();
+ bool isFlaggedForDeletion() const;
+
+ void validate(const Caps &caps);
+ bool validateSamplers(InfoLog *infoLog, const Caps &caps);
+ bool isValidated() const;
+
+ const AttributesMask &getActiveAttribLocationsMask() const
+ {
+ return mState.mActiveAttribLocationsMask;
+ }
+
+ private:
+ class Bindings final : angle::NonCopyable
+ {
+ public:
+ void bindLocation(GLuint index, const std::string &name);
+ int getBinding(const std::string &name) const;
+
+ typedef std::unordered_map<std::string, GLuint>::const_iterator const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ private:
+ std::unordered_map<std::string, GLuint> mBindings;
+ };
+
+ void unlink(bool destroy = false);
+ void resetUniformBlockBindings();
+
+ bool linkAttributes(const ContextState &data,
+ InfoLog &infoLog,
+ const Bindings &attributeBindings,
+ const Shader *vertexShader);
+ bool validateUniformBlocksCount(GLuint maxUniformBlocks,
+ const std::vector<sh::InterfaceBlock> &block,
+ const std::string &errorMessage,
+ InfoLog &infoLog) const;
+ bool validateVertexAndFragmentInterfaceBlocks(
+ const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
+ const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks,
+ InfoLog &infoLog) const;
+ bool linkUniformBlocks(InfoLog &infoLog, const Caps &caps);
+ bool linkVaryings(InfoLog &infoLog, const Shader *vertexShader, const Shader *fragmentShader) const;
+ bool validateVertexAndFragmentUniforms(InfoLog &infoLog) const;
+ bool linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps, const Bindings &uniformBindings);
+ bool indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps, const Bindings &uniformBindings);
+ bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog,
+ const sh::InterfaceBlock &vertexInterfaceBlock,
+ const sh::InterfaceBlock &fragmentInterfaceBlock) const;
+
+ static bool linkValidateVariablesBase(InfoLog &infoLog,
+ const std::string &variableName,
+ const sh::ShaderVariable &vertexVariable,
+ const sh::ShaderVariable &fragmentVariable,
+ bool validatePrecision);
+
+ static bool linkValidateVaryings(InfoLog &infoLog,
+ const std::string &varyingName,
+ const sh::Varying &vertexVarying,
+ const sh::Varying &fragmentVarying,
+ int shaderVersion);
+ bool linkValidateTransformFeedback(InfoLog &infoLog,
+ const std::vector<const sh::Varying *> &linkedVaryings,
+ const Caps &caps) const;
+
+ void gatherTransformFeedbackVaryings(const std::vector<const sh::Varying *> &varyings);
+ bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps);
+ void defineOutputVariables(Shader *fragmentShader);
+
+ std::vector<const sh::Varying *> getMergedVaryings() const;
+ void linkOutputVariables();
+
+ bool flattenUniformsAndCheckCapsForShader(const gl::Shader &shader,
+ GLuint maxUniformComponents,
+ GLuint maxTextureImageUnits,
+ const std::string &componentsErrorMessage,
+ const std::string &samplerErrorMessage,
+ std::vector<LinkedUniform> &samplerUniforms,
+ InfoLog &infoLog);
+ bool flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog);
+
+ struct VectorAndSamplerCount
+ {
+ VectorAndSamplerCount() : vectorCount(0), samplerCount(0) {}
+ VectorAndSamplerCount(const VectorAndSamplerCount &other) = default;
+ VectorAndSamplerCount &operator=(const VectorAndSamplerCount &other) = default;
+
+ VectorAndSamplerCount &operator+=(const VectorAndSamplerCount &other)
+ {
+ vectorCount += other.vectorCount;
+ samplerCount += other.samplerCount;
+ return *this;
+ }
+
+ unsigned int vectorCount;
+ unsigned int samplerCount;
+ };
+
+ VectorAndSamplerCount flattenUniform(const sh::ShaderVariable &uniform,
+ const std::string &fullName,
+ std::vector<LinkedUniform> *samplerUniforms);
+
+ void gatherInterfaceBlockInfo();
+ template <typename VarT>
+ void defineUniformBlockMembers(const std::vector<VarT> &fields,
+ const std::string &prefix,
+ int blockIndex);
+
+ void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
+
+ // 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 setUniformInternal(GLint location, GLsizei count, int vectorSize, const T *v);
+ template <size_t cols, size_t rows, typename T>
+ GLsizei setMatrixUniformInternal(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const T *v);
+
+ template <typename DestT>
+ void getUniformInternal(GLint location, DestT *dataOut) const;
+
+ ProgramState mState;
+ rx::ProgramImpl *mProgram;
+
+ bool mValidated;
+
+ Bindings mAttributeBindings;
+ Bindings mUniformBindings;
+
+ // CHROMIUM_path_rendering
+ Bindings mFragmentInputBindings;
+
+ bool mLinked;
+ bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use
+
+ unsigned int mRefCount;
+
+ ResourceManager *mResourceManager;
+ const GLuint mHandle;
+
+ InfoLog mInfoLog;
+
+ // Cache for sampler validation
+ Optional<bool> mCachedValidateSamplersResult;
+ std::vector<GLenum> mTextureUnitTypesCache;
+ RangeUI mSamplerUniformRange;
+};
+}
+
+#endif // LIBANGLE_PROGRAM_H_
diff --git a/gfx/angle/src/libANGLE/Program_unittest.cpp b/gfx/angle/src/libANGLE/Program_unittest.cpp
new file mode 100755
index 000000000..6d99f0019
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Program_unittest.cpp
@@ -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.
+//
+// Unit tests for Program and related classes.
+//
+
+#include <gtest/gtest.h>
+
+#include "libANGLE/Program.h"
+
+using namespace gl;
+
+namespace
+{
+
+// Tests that the log length properly counts the terminating \0.
+TEST(InfoLogTest, LogLengthCountsTerminator)
+{
+ InfoLog infoLog;
+ EXPECT_EQ(0u, infoLog.getLength());
+ infoLog << " ";
+
+ // " \n\0" = 3 characters
+ EXPECT_EQ(3u, infoLog.getLength());
+}
+
+// Tests that newlines get appended to the info log properly.
+TEST(InfoLogTest, AppendingNewline)
+{
+ InfoLog infoLog;
+
+ infoLog << "First" << 1 << 'x';
+ infoLog << "Second" << 2 << 'y';
+
+ std::string expected = "First1x\nSecond2y\n";
+
+ EXPECT_EQ(expected, infoLog.str());
+}
+
+} // namespace
diff --git a/gfx/angle/src/libANGLE/Query.cpp b/gfx/angle/src/libANGLE/Query.cpp
new file mode 100755
index 000000000..cd1fb5f4b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Query.cpp
@@ -0,0 +1,87 @@
+//
+// Copyright (c) 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/QueryImpl.h"
+
+namespace gl
+{
+Query::Query(rx::QueryImpl *impl, GLuint id) : RefCountObject(id), mQuery(impl), mLabel()
+{
+}
+
+Query::~Query()
+{
+ SafeDelete(mQuery);
+}
+
+void Query::setLabel(const std::string &label)
+{
+ mLabel = label;
+}
+
+const std::string &Query::getLabel() const
+{
+ return mLabel;
+}
+
+Error Query::begin()
+{
+ return mQuery->begin();
+}
+
+Error Query::end()
+{
+ return mQuery->end();
+}
+
+Error Query::queryCounter()
+{
+ return mQuery->queryCounter();
+}
+
+Error Query::getResult(GLint *params)
+{
+ return mQuery->getResult(params);
+}
+
+Error Query::getResult(GLuint *params)
+{
+ return mQuery->getResult(params);
+}
+
+Error Query::getResult(GLint64 *params)
+{
+ return mQuery->getResult(params);
+}
+
+Error Query::getResult(GLuint64 *params)
+{
+ return mQuery->getResult(params);
+}
+
+Error Query::isResultAvailable(bool *available)
+{
+ return mQuery->isResultAvailable(available);
+}
+
+GLenum Query::getType() const
+{
+ return mQuery->getType();
+}
+
+rx::QueryImpl *Query::getImplementation()
+{
+ return mQuery;
+}
+
+const rx::QueryImpl *Query::getImplementation() const
+{
+ return mQuery;
+}
+}
diff --git a/gfx/angle/src/libANGLE/Query.h b/gfx/angle/src/libANGLE/Query.h
new file mode 100755
index 000000000..5486f983e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Query.h
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 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 "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+class QueryImpl;
+}
+
+namespace gl
+{
+
+class Query final : public RefCountObject, public LabeledObject
+{
+ public:
+ Query(rx::QueryImpl *impl, GLuint id);
+ virtual ~Query();
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ Error begin();
+ Error end();
+ Error queryCounter();
+ Error getResult(GLint *params);
+ Error getResult(GLuint *params);
+ Error getResult(GLint64 *params);
+ Error getResult(GLuint64 *params);
+ Error isResultAvailable(bool *available);
+
+ GLenum getType() const;
+
+ rx::QueryImpl *getImplementation();
+ const rx::QueryImpl *getImplementation() const;
+
+ private:
+ rx::QueryImpl *mQuery;
+
+ std::string mLabel;
+};
+
+}
+
+#endif // LIBANGLE_QUERY_H_
diff --git a/gfx/angle/src/libANGLE/RefCountObject.h b/gfx/angle/src/libANGLE/RefCountObject.h
new file mode 100755
index 000000000..86e6d788b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/RefCountObject.h
@@ -0,0 +1,139 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 "common/debug.h"
+
+#include "angle_gl.h"
+
+#include <cstddef>
+
+class RefCountObject : angle::NonCopyable
+{
+ public:
+ explicit RefCountObject(GLuint id) : mId(id), mRefCount(0) {}
+
+ void addRef() const { ++mRefCount; }
+
+ void release() const
+ {
+ ASSERT(mRefCount > 0);
+
+ if (--mRefCount == 0)
+ {
+ delete this;
+ }
+ }
+
+ GLuint id() const { return mId; }
+
+ size_t getRefCount() const { return mRefCount; }
+
+ protected:
+ virtual ~RefCountObject() { ASSERT(mRefCount == 0); }
+
+ private:
+ GLuint mId;
+
+ mutable std::size_t mRefCount;
+};
+
+template <class ObjectType>
+class BindingPointer
+{
+ public:
+ BindingPointer()
+ : mObject(nullptr)
+ {
+ }
+
+ BindingPointer(const BindingPointer<ObjectType> &other)
+ : mObject(nullptr)
+ {
+ set(other.mObject);
+ }
+
+ void operator=(const BindingPointer<ObjectType> &other)
+ {
+ set(other.mObject);
+ }
+
+ virtual ~BindingPointer()
+ {
+ // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up.
+ ASSERT(mObject == nullptr);
+ }
+
+ virtual void set(ObjectType *newObject)
+ {
+ // addRef first in case newObject == mObject and this is the last reference to it.
+ if (newObject != nullptr) reinterpret_cast<const RefCountObject*>(newObject)->addRef();
+ if (mObject != nullptr) reinterpret_cast<const RefCountObject*>(mObject)->release();
+ mObject = newObject;
+ }
+
+ ObjectType *get() const { return mObject; }
+ ObjectType *operator->() const { return mObject; }
+
+ GLuint id() const { return (mObject != nullptr) ? mObject->id() : 0; }
+
+ bool operator==(const BindingPointer<ObjectType> &other) const
+ {
+ return mObject == other.mObject;
+ }
+
+ bool operator!=(const BindingPointer<ObjectType> &other) const { return !(*this == other); }
+
+ private:
+ ObjectType *mObject;
+};
+
+template <class ObjectType>
+class OffsetBindingPointer : public BindingPointer<ObjectType>
+{
+ public:
+ OffsetBindingPointer() : mOffset(0), mSize(0) { }
+
+ void set(ObjectType *newObject) override
+ {
+ BindingPointer<ObjectType>::set(newObject);
+ mOffset = 0;
+ mSize = 0;
+ }
+
+ void set(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
+ {
+ BindingPointer<ObjectType>::set(newObject);
+ mOffset = offset;
+ mSize = 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);
+ }
+
+ private:
+ GLintptr mOffset;
+ GLsizeiptr mSize;
+};
+
+#endif // LIBANGLE_REFCOUNTOBJECT_H_
diff --git a/gfx/angle/src/libANGLE/Renderbuffer.cpp b/gfx/angle/src/libANGLE/Renderbuffer.cpp
new file mode 100755
index 000000000..7b30a46be
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Renderbuffer.cpp
@@ -0,0 +1,173 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/FramebufferAttachment.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+
+namespace gl
+{
+Renderbuffer::Renderbuffer(rx::RenderbufferImpl *impl, GLuint id)
+ : egl::ImageSibling(id),
+ mRenderbuffer(impl),
+ mLabel(),
+ mWidth(0),
+ mHeight(0),
+ mFormat(GL_RGBA4),
+ mSamples(0)
+{
+}
+
+Renderbuffer::~Renderbuffer()
+{
+ SafeDelete(mRenderbuffer);
+}
+
+void Renderbuffer::setLabel(const std::string &label)
+{
+ mLabel = label;
+}
+
+const std::string &Renderbuffer::getLabel() const
+{
+ return mLabel;
+}
+
+Error Renderbuffer::setStorage(GLenum internalformat, size_t width, size_t height)
+{
+ orphanImages();
+
+ ANGLE_TRY(mRenderbuffer->setStorage(internalformat, width, height));
+
+ mWidth = static_cast<GLsizei>(width);
+ mHeight = static_cast<GLsizei>(height);
+ mFormat = Format(internalformat);
+ mSamples = 0;
+
+ mDirtyChannel.signal();
+
+ return NoError();
+}
+
+Error Renderbuffer::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
+{
+ orphanImages();
+
+ ANGLE_TRY(mRenderbuffer->setStorageMultisample(samples, internalformat, width, height));
+
+ mWidth = static_cast<GLsizei>(width);
+ mHeight = static_cast<GLsizei>(height);
+ mFormat = Format(internalformat);
+ mSamples = static_cast<GLsizei>(samples);
+
+ mDirtyChannel.signal();
+
+ return NoError();
+}
+
+Error Renderbuffer::setStorageEGLImageTarget(egl::Image *image)
+{
+ orphanImages();
+
+ ANGLE_TRY(mRenderbuffer->setStorageEGLImageTarget(image));
+
+ setTargetImage(image);
+
+ mWidth = static_cast<GLsizei>(image->getWidth());
+ mHeight = static_cast<GLsizei>(image->getHeight());
+ mFormat = Format(image->getFormat());
+ mSamples = 0;
+
+ mDirtyChannel.signal();
+
+ return NoError();
+}
+
+rx::RenderbufferImpl *Renderbuffer::getImplementation() const
+{
+ ASSERT(mRenderbuffer);
+ return mRenderbuffer;
+}
+
+GLsizei Renderbuffer::getWidth() const
+{
+ return mWidth;
+}
+
+GLsizei Renderbuffer::getHeight() const
+{
+ return mHeight;
+}
+
+const Format &Renderbuffer::getFormat() const
+{
+ return mFormat;
+}
+
+GLsizei Renderbuffer::getSamples() const
+{
+ return mSamples;
+}
+
+GLuint Renderbuffer::getRedSize() const
+{
+ return mFormat.info->redBits;
+}
+
+GLuint Renderbuffer::getGreenSize() const
+{
+ return mFormat.info->greenBits;
+}
+
+GLuint Renderbuffer::getBlueSize() const
+{
+ return mFormat.info->blueBits;
+}
+
+GLuint Renderbuffer::getAlphaSize() const
+{
+ return mFormat.info->alphaBits;
+}
+
+GLuint Renderbuffer::getDepthSize() const
+{
+ return mFormat.info->depthBits;
+}
+
+GLuint Renderbuffer::getStencilSize() const
+{
+ return mFormat.info->stencilBits;
+}
+
+void Renderbuffer::onAttach()
+{
+ addRef();
+}
+
+void Renderbuffer::onDetach()
+{
+ release();
+}
+
+GLuint Renderbuffer::getId() const
+{
+ return id();
+}
+
+Extents Renderbuffer::getAttachmentSize(const FramebufferAttachment::Target & /*target*/) const
+{
+ return Extents(mWidth, mHeight, 1);
+}
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/Renderbuffer.h b/gfx/angle/src/libANGLE/Renderbuffer.h
new file mode 100755
index 000000000..57cc08279
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Renderbuffer.h
@@ -0,0 +1,86 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 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 Renderbuffer final : public egl::ImageSibling,
+ public gl::FramebufferAttachmentObject,
+ public LabeledObject
+{
+ public:
+ Renderbuffer(rx::RenderbufferImpl *impl, GLuint id);
+ virtual ~Renderbuffer();
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ Error setStorage(GLenum internalformat, size_t width, size_t height);
+ Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height);
+ Error setStorageEGLImageTarget(egl::Image *imageTarget);
+
+ rx::RenderbufferImpl *getImplementation() const;
+
+ GLsizei getWidth() const;
+ GLsizei getHeight() const;
+ const Format &getFormat() const;
+ GLsizei getSamples() const;
+ GLuint getRedSize() const;
+ GLuint getGreenSize() const;
+ GLuint getBlueSize() const;
+ GLuint getAlphaSize() const;
+ GLuint getDepthSize() const;
+ GLuint getStencilSize() const;
+
+ // FramebufferAttachmentObject Impl
+ Extents getAttachmentSize(const FramebufferAttachment::Target &target) const override;
+ const Format &getAttachmentFormat(
+ const FramebufferAttachment::Target & /*target*/) const override
+ {
+ return getFormat();
+ }
+ GLsizei getAttachmentSamples(const FramebufferAttachment::Target &/*target*/) const override { return getSamples(); }
+
+ void onAttach() override;
+ void onDetach() override;
+ GLuint getId() const override;
+
+ private:
+ rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mRenderbuffer; }
+
+ rx::RenderbufferImpl *mRenderbuffer;
+
+ std::string mLabel;
+
+ GLsizei mWidth;
+ GLsizei mHeight;
+ Format mFormat;
+ GLsizei mSamples;
+};
+
+}
+
+#endif // LIBANGLE_RENDERBUFFER_H_
diff --git a/gfx/angle/src/libANGLE/ResourceManager.cpp b/gfx/angle/src/libANGLE/ResourceManager.cpp
new file mode 100755
index 000000000..cfb965d92
--- /dev/null
+++ b/gfx/angle/src/libANGLE/ResourceManager.cpp
@@ -0,0 +1,562 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and
+// retrieves objects which may be shared by multiple Contexts.
+
+#include "libANGLE/ResourceManager.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Path.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace gl
+{
+ResourceManager::ResourceManager() : mRefCount(1)
+{
+}
+
+ResourceManager::~ResourceManager()
+{
+ while (!mBufferMap.empty())
+ {
+ deleteBuffer(mBufferMap.begin()->first);
+ }
+
+ while (!mProgramMap.empty())
+ {
+ deleteProgram(mProgramMap.begin()->first);
+ }
+
+ while (!mShaderMap.empty())
+ {
+ deleteShader(mShaderMap.begin()->first);
+ }
+
+ while (!mRenderbufferMap.empty())
+ {
+ deleteRenderbuffer(mRenderbufferMap.begin()->first);
+ }
+
+ while (!mTextureMap.empty())
+ {
+ deleteTexture(mTextureMap.begin()->first);
+ }
+
+ while (!mSamplerMap.empty())
+ {
+ deleteSampler(mSamplerMap.begin()->first);
+ }
+
+ while (!mFenceSyncMap.empty())
+ {
+ deleteFenceSync(mFenceSyncMap.begin()->first);
+ }
+
+ for (auto it = mPathMap.begin(); it != mPathMap.end(); ++it)
+ {
+ const auto *p = it->second;
+ delete p;
+ }
+}
+
+void ResourceManager::addRef()
+{
+ mRefCount++;
+}
+
+void ResourceManager::release()
+{
+ if (--mRefCount == 0)
+ {
+ delete this;
+ }
+}
+
+// Returns an unused buffer name
+GLuint ResourceManager::createBuffer()
+{
+ GLuint handle = mBufferHandleAllocator.allocate();
+
+ mBufferMap[handle] = nullptr;
+
+ return handle;
+}
+
+// Returns an unused shader/program name
+GLuint ResourceManager::createShader(rx::GLImplFactory *factory,
+ const gl::Limitations &rendererLimitations,
+ GLenum type)
+{
+ ASSERT(type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER || type == GL_COMPUTE_SHADER);
+ GLuint handle = mProgramShaderHandleAllocator.allocate();
+
+ mShaderMap[handle] = new Shader(this, factory, rendererLimitations, type, handle);
+
+ return handle;
+}
+
+// Returns an unused program/shader name
+GLuint ResourceManager::createProgram(rx::GLImplFactory *factory)
+{
+ GLuint handle = mProgramShaderHandleAllocator.allocate();
+
+ mProgramMap[handle] = new Program(factory, this, handle);
+
+ return handle;
+}
+
+// Returns an unused texture name
+GLuint ResourceManager::createTexture()
+{
+ GLuint handle = mTextureHandleAllocator.allocate();
+
+ mTextureMap[handle] = nullptr;
+
+ return handle;
+}
+
+// Returns an unused renderbuffer name
+GLuint ResourceManager::createRenderbuffer()
+{
+ GLuint handle = mRenderbufferHandleAllocator.allocate();
+
+ mRenderbufferMap[handle] = nullptr;
+
+ return handle;
+}
+
+// Returns an unused sampler name
+GLuint ResourceManager::createSampler()
+{
+ GLuint handle = mSamplerHandleAllocator.allocate();
+
+ mSamplerMap[handle] = nullptr;
+
+ return handle;
+}
+
+// Returns the next unused fence name, and allocates the fence
+GLuint ResourceManager::createFenceSync(rx::GLImplFactory *factory)
+{
+ GLuint handle = mFenceSyncHandleAllocator.allocate();
+
+ FenceSync *fenceSync = new FenceSync(factory->createFenceSync(), handle);
+ fenceSync->addRef();
+ mFenceSyncMap[handle] = fenceSync;
+
+ return handle;
+}
+
+ErrorOrResult<GLuint> ResourceManager::createPaths(rx::GLImplFactory *factory, GLsizei range)
+{
+ // Allocate client side handles.
+ const GLuint client = mPathHandleAllocator.allocateRange(static_cast<GLuint>(range));
+ if (client == HandleRangeAllocator::kInvalidHandle)
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate path handle range.");
+
+ const auto &paths = factory->createPaths(range);
+ if (paths.empty())
+ {
+ mPathHandleAllocator.releaseRange(client, range);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate path objects.");
+ }
+
+ auto hint = mPathMap.begin();
+
+ for (GLsizei i = 0; i < range; ++i)
+ {
+ const auto impl = paths[static_cast<unsigned>(i)];
+ const auto id = client + i;
+ hint = mPathMap.insert(hint, std::make_pair(id, new Path(impl)));
+ }
+ return client;
+}
+
+void ResourceManager::deleteBuffer(GLuint buffer)
+{
+ auto bufferObject = mBufferMap.find(buffer);
+
+ if (bufferObject != mBufferMap.end())
+ {
+ mBufferHandleAllocator.release(bufferObject->first);
+ if (bufferObject->second) bufferObject->second->release();
+ mBufferMap.erase(bufferObject);
+ }
+}
+
+void ResourceManager::deleteShader(GLuint shader)
+{
+ auto shaderObject = mShaderMap.find(shader);
+
+ if (shaderObject != mShaderMap.end())
+ {
+ if (shaderObject->second->getRefCount() == 0)
+ {
+ mProgramShaderHandleAllocator.release(shaderObject->first);
+ delete shaderObject->second;
+ mShaderMap.erase(shaderObject);
+ }
+ else
+ {
+ shaderObject->second->flagForDeletion();
+ }
+ }
+}
+
+void ResourceManager::deleteProgram(GLuint program)
+{
+ auto programObject = mProgramMap.find(program);
+
+ if (programObject != mProgramMap.end())
+ {
+ if (programObject->second->getRefCount() == 0)
+ {
+ mProgramShaderHandleAllocator.release(programObject->first);
+ delete programObject->second;
+ mProgramMap.erase(programObject);
+ }
+ else
+ {
+ programObject->second->flagForDeletion();
+ }
+ }
+}
+
+void ResourceManager::deleteTexture(GLuint texture)
+{
+ auto textureObject = mTextureMap.find(texture);
+
+ if (textureObject != mTextureMap.end())
+ {
+ mTextureHandleAllocator.release(textureObject->first);
+ if (textureObject->second) textureObject->second->release();
+ mTextureMap.erase(textureObject);
+ }
+}
+
+void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
+{
+ auto renderbufferObject = mRenderbufferMap.find(renderbuffer);
+
+ if (renderbufferObject != mRenderbufferMap.end())
+ {
+ mRenderbufferHandleAllocator.release(renderbufferObject->first);
+ if (renderbufferObject->second) renderbufferObject->second->release();
+ mRenderbufferMap.erase(renderbufferObject);
+ }
+}
+
+void ResourceManager::deleteSampler(GLuint sampler)
+{
+ auto samplerObject = mSamplerMap.find(sampler);
+
+ if (samplerObject != mSamplerMap.end())
+ {
+ mSamplerHandleAllocator.release(samplerObject->first);
+ if (samplerObject->second) samplerObject->second->release();
+ mSamplerMap.erase(samplerObject);
+ }
+}
+
+void ResourceManager::deleteFenceSync(GLuint fenceSync)
+{
+ auto fenceObjectIt = mFenceSyncMap.find(fenceSync);
+
+ if (fenceObjectIt != mFenceSyncMap.end())
+ {
+ mFenceSyncHandleAllocator.release(fenceObjectIt->first);
+ if (fenceObjectIt->second) fenceObjectIt->second->release();
+ mFenceSyncMap.erase(fenceObjectIt);
+ }
+}
+
+void ResourceManager::deletePaths(GLuint first, GLsizei range)
+{
+ for (GLsizei i = 0; i < range; ++i)
+ {
+ const auto id = first + i;
+ const auto it = mPathMap.find(id);
+ if (it == mPathMap.end())
+ continue;
+ Path *p = it->second;
+ delete p;
+ mPathMap.erase(it);
+ }
+ mPathHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
+}
+
+Buffer *ResourceManager::getBuffer(unsigned int handle)
+{
+ auto buffer = mBufferMap.find(handle);
+
+ if (buffer == mBufferMap.end())
+ {
+ return nullptr;
+ }
+ else
+ {
+ return buffer->second;
+ }
+}
+
+Shader *ResourceManager::getShader(unsigned int handle) const
+{
+ auto shader = mShaderMap.find(handle);
+
+ if (shader == mShaderMap.end())
+ {
+ return nullptr;
+ }
+ else
+ {
+ return shader->second;
+ }
+}
+
+Texture *ResourceManager::getTexture(unsigned int handle)
+{
+ if (handle == 0)
+ return nullptr;
+
+ auto texture = mTextureMap.find(handle);
+
+ if (texture == mTextureMap.end())
+ {
+ return nullptr;
+ }
+ else
+ {
+ return texture->second;
+ }
+}
+
+Program *ResourceManager::getProgram(unsigned int handle) const
+{
+ auto program = mProgramMap.find(handle);
+
+ if (program == mProgramMap.end())
+ {
+ return nullptr;
+ }
+ else
+ {
+ return program->second;
+ }
+}
+
+Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
+{
+ auto renderbuffer = mRenderbufferMap.find(handle);
+
+ if (renderbuffer == mRenderbufferMap.end())
+ {
+ return nullptr;
+ }
+ else
+ {
+ return renderbuffer->second;
+ }
+}
+
+Sampler *ResourceManager::getSampler(unsigned int handle)
+{
+ auto sampler = mSamplerMap.find(handle);
+
+ if (sampler == mSamplerMap.end())
+ {
+ return nullptr;
+ }
+ else
+ {
+ return sampler->second;
+ }
+}
+
+FenceSync *ResourceManager::getFenceSync(unsigned int handle)
+{
+ auto fenceObjectIt = mFenceSyncMap.find(handle);
+
+ if (fenceObjectIt == mFenceSyncMap.end())
+ {
+ return nullptr;
+ }
+ else
+ {
+ return fenceObjectIt->second;
+ }
+}
+
+const Path *ResourceManager::getPath(GLuint handle) const
+{
+ auto it = mPathMap.find(handle);
+ if (it == std::end(mPathMap))
+ return nullptr;
+ return it->second;
+}
+
+Path *ResourceManager::getPath(GLuint handle)
+{
+ auto it = mPathMap.find(handle);
+ if (it == std::end(mPathMap))
+ return nullptr;
+
+ return it->second;
+}
+
+bool ResourceManager::hasPath(GLuint handle) const
+{
+ return mPathHandleAllocator.isUsed(handle);
+}
+
+void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
+{
+ mRenderbufferMap[handle] = buffer;
+}
+
+Buffer *ResourceManager::checkBufferAllocation(rx::GLImplFactory *factory, GLuint handle)
+{
+ if (handle == 0)
+ {
+ return nullptr;
+ }
+
+ auto bufferMapIt = mBufferMap.find(handle);
+ bool handleAllocated = (bufferMapIt != mBufferMap.end());
+
+ if (handleAllocated && bufferMapIt->second != nullptr)
+ {
+ return bufferMapIt->second;
+ }
+
+ Buffer *buffer = new Buffer(factory, handle);
+ buffer->addRef();
+
+ if (handleAllocated)
+ {
+ bufferMapIt->second = buffer;
+ }
+ else
+ {
+ mBufferHandleAllocator.reserve(handle);
+ mBufferMap[handle] = buffer;
+ }
+
+ return buffer;
+}
+
+Texture *ResourceManager::checkTextureAllocation(rx::GLImplFactory *factory,
+ GLuint handle,
+ GLenum type)
+{
+ if (handle == 0)
+ {
+ return nullptr;
+ }
+
+ auto textureMapIt = mTextureMap.find(handle);
+ bool handleAllocated = (textureMapIt != mTextureMap.end());
+
+ if (handleAllocated && textureMapIt->second != nullptr)
+ {
+ return textureMapIt->second;
+ }
+
+ Texture *texture = new Texture(factory, handle, type);
+ texture->addRef();
+
+ if (handleAllocated)
+ {
+ textureMapIt->second = texture;
+ }
+ else
+ {
+ mTextureHandleAllocator.reserve(handle);
+ mTextureMap[handle] = texture;
+ }
+
+ return texture;
+}
+
+Renderbuffer *ResourceManager::checkRenderbufferAllocation(rx::GLImplFactory *factory,
+ GLuint handle)
+{
+ if (handle == 0)
+ {
+ return nullptr;
+ }
+
+ auto renderbufferMapIt = mRenderbufferMap.find(handle);
+ bool handleAllocated = (renderbufferMapIt != mRenderbufferMap.end());
+
+ if (handleAllocated && renderbufferMapIt->second != nullptr)
+ {
+ return renderbufferMapIt->second;
+ }
+
+ Renderbuffer *renderbuffer = new Renderbuffer(factory->createRenderbuffer(), handle);
+ renderbuffer->addRef();
+
+ if (handleAllocated)
+ {
+ renderbufferMapIt->second = renderbuffer;
+ }
+ else
+ {
+ mRenderbufferHandleAllocator.reserve(handle);
+ mRenderbufferMap[handle] = renderbuffer;
+ }
+
+ return renderbuffer;
+}
+
+Sampler *ResourceManager::checkSamplerAllocation(rx::GLImplFactory *factory, GLuint samplerHandle)
+{
+ // Samplers cannot be created via Bind
+ if (samplerHandle == 0)
+ {
+ return nullptr;
+ }
+
+ Sampler *sampler = getSampler(samplerHandle);
+
+ if (!sampler)
+ {
+ sampler = new Sampler(factory, samplerHandle);
+ mSamplerMap[samplerHandle] = sampler;
+ sampler->addRef();
+ }
+
+ return sampler;
+}
+
+bool ResourceManager::isSampler(GLuint sampler)
+{
+ return mSamplerMap.find(sampler) != mSamplerMap.end();
+}
+
+bool ResourceManager::isTextureGenerated(GLuint texture) const
+{
+ return texture == 0 || mTextureMap.find(texture) != mTextureMap.end();
+}
+
+bool ResourceManager::isBufferGenerated(GLuint buffer) const
+{
+ return buffer == 0 || mBufferMap.find(buffer) != mBufferMap.end();
+}
+
+bool ResourceManager::isRenderbufferGenerated(GLuint renderbuffer) const
+{
+ return renderbuffer == 0 || mRenderbufferMap.find(renderbuffer) != mRenderbufferMap.end();
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/ResourceManager.h b/gfx/angle/src/libANGLE/ResourceManager.h
new file mode 100755
index 000000000..f6a0002ed
--- /dev/null
+++ b/gfx/angle/src/libANGLE/ResourceManager.h
@@ -0,0 +1,124 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// ResourceManager.h : Defines the ResourceManager class, which tracks objects
+// shared by multiple GL contexts.
+
+#ifndef LIBANGLE_RESOURCEMANAGER_H_
+#define LIBANGLE_RESOURCEMANAGER_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/HandleAllocator.h"
+#include "libANGLE/HandleRangeAllocator.h"
+
+namespace rx
+{
+class GLImplFactory;
+}
+
+namespace gl
+{
+class Buffer;
+class FenceSync;
+struct Limitations;
+class Path;
+class Program;
+class Renderbuffer;
+class Sampler;
+class Shader;
+class Texture;
+
+class ResourceManager : angle::NonCopyable
+{
+ public:
+ ResourceManager();
+ ~ResourceManager();
+
+ void addRef();
+ void release();
+
+ GLuint createBuffer();
+ GLuint createShader(rx::GLImplFactory *factory,
+ const gl::Limitations &rendererLimitations,
+ GLenum type);
+ GLuint createProgram(rx::GLImplFactory *factory);
+ GLuint createTexture();
+ GLuint createRenderbuffer();
+ GLuint createSampler();
+ GLuint createFenceSync(rx::GLImplFactory *factory);
+ ErrorOrResult<GLuint> createPaths(rx::GLImplFactory *factory, GLsizei range);
+
+ void deleteBuffer(GLuint buffer);
+ void deleteShader(GLuint shader);
+ void deleteProgram(GLuint program);
+ void deleteTexture(GLuint texture);
+ void deleteRenderbuffer(GLuint renderbuffer);
+ void deleteSampler(GLuint sampler);
+ void deleteFenceSync(GLuint fenceSync);
+ void deletePaths(GLuint first, GLsizei range);
+
+ Buffer *getBuffer(GLuint handle);
+ Shader *getShader(GLuint handle) const;
+ Program *getProgram(GLuint handle) const;
+ Texture *getTexture(GLuint handle);
+ Renderbuffer *getRenderbuffer(GLuint handle);
+ Sampler *getSampler(GLuint handle);
+ FenceSync *getFenceSync(GLuint handle);
+
+ // CHROMIUM_path_rendering
+ const Path *getPath(GLuint path) const;
+ Path *getPath(GLuint path);
+ bool hasPath(GLuint path) const;
+
+ void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
+
+ Buffer *checkBufferAllocation(rx::GLImplFactory *factory, GLuint handle);
+ Texture *checkTextureAllocation(rx::GLImplFactory *factory, GLuint handle, GLenum type);
+ Renderbuffer *checkRenderbufferAllocation(rx::GLImplFactory *factory, GLuint handle);
+ Sampler *checkSamplerAllocation(rx::GLImplFactory *factory, GLuint samplerHandle);
+
+ bool isSampler(GLuint sampler);
+
+ // GL_CHROMIUM_bind_generates_resource
+ bool isTextureGenerated(GLuint texture) const;
+ bool isBufferGenerated(GLuint buffer) const;
+ bool isRenderbufferGenerated(GLuint renderbuffer) const;
+
+ private:
+ void createTextureInternal(GLuint handle);
+
+ std::size_t mRefCount;
+
+ ResourceMap<Buffer> mBufferMap;
+ HandleAllocator mBufferHandleAllocator;
+
+ ResourceMap<Shader> mShaderMap;
+
+ ResourceMap<Program> mProgramMap;
+ HandleAllocator mProgramShaderHandleAllocator;
+
+ ResourceMap<Texture> mTextureMap;
+ HandleAllocator mTextureHandleAllocator;
+
+ ResourceMap<Renderbuffer> mRenderbufferMap;
+ HandleAllocator mRenderbufferHandleAllocator;
+
+ ResourceMap<Sampler> mSamplerMap;
+ HandleAllocator mSamplerHandleAllocator;
+
+ ResourceMap<FenceSync> mFenceSyncMap;
+ HandleAllocator mFenceSyncHandleAllocator;
+
+ ResourceMap<Path> mPathMap;
+ HandleRangeAllocator mPathHandleAllocator;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_RESOURCEMANAGER_H_
diff --git a/gfx/angle/src/libANGLE/ResourceManager_unittest.cpp b/gfx/angle/src/libANGLE/ResourceManager_unittest.cpp
new file mode 100755
index 000000000..a9dff145b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/ResourceManager_unittest.cpp
@@ -0,0 +1,67 @@
+//
+// 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.
+//
+// Unit tests for ResourceManager.
+//
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "libANGLE/ResourceManager.h"
+#include "tests/angle_unittests_utils.h"
+
+using namespace rx;
+using namespace gl;
+
+using ::testing::_;
+
+namespace
+{
+
+class ResourceManagerTest : public testing::Test
+{
+ protected:
+ void SetUp() override
+ {
+ mResourceManager = new ResourceManager();
+ }
+
+ void TearDown() override
+ {
+ SafeDelete(mResourceManager);
+ }
+
+ MockGLFactory mMockFactory;
+ ResourceManager *mResourceManager;
+};
+
+TEST_F(ResourceManagerTest, ReallocateBoundTexture)
+{
+ EXPECT_CALL(mMockFactory, createTexture(_)).Times(1).RetiresOnSaturation();
+
+ mResourceManager->checkTextureAllocation(&mMockFactory, 1, GL_TEXTURE_2D);
+ GLuint newTexture = mResourceManager->createTexture();
+ EXPECT_NE(1u, newTexture);
+}
+
+TEST_F(ResourceManagerTest, ReallocateBoundBuffer)
+{
+ EXPECT_CALL(mMockFactory, createBuffer(_)).Times(1).RetiresOnSaturation();
+
+ mResourceManager->checkBufferAllocation(&mMockFactory, 1);
+ GLuint newBuffer = mResourceManager->createBuffer();
+ EXPECT_NE(1u, newBuffer);
+}
+
+TEST_F(ResourceManagerTest, ReallocateBoundRenderbuffer)
+{
+ EXPECT_CALL(mMockFactory, createRenderbuffer()).Times(1).RetiresOnSaturation();
+
+ mResourceManager->checkRenderbufferAllocation(&mMockFactory, 1);
+ GLuint newRenderbuffer = mResourceManager->createRenderbuffer();
+ EXPECT_NE(1u, newRenderbuffer);
+}
+
+} // anonymous namespace
diff --git a/gfx/angle/src/libANGLE/Sampler.cpp b/gfx/angle/src/libANGLE/Sampler.cpp
new file mode 100755
index 000000000..369c3cbaa
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Sampler.cpp
@@ -0,0 +1,158 @@
+//
+// Copyright (c) 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, GLuint id)
+ : RefCountObject(id), mImpl(factory->createSampler()), mLabel(), mSamplerState()
+{
+}
+
+Sampler::~Sampler()
+{
+ SafeDelete(mImpl);
+}
+
+void Sampler::setLabel(const std::string &label)
+{
+ mLabel = label;
+}
+
+const std::string &Sampler::getLabel() const
+{
+ return mLabel;
+}
+
+void Sampler::setMinFilter(GLenum minFilter)
+{
+ mSamplerState.minFilter = minFilter;
+}
+
+GLenum Sampler::getMinFilter() const
+{
+ return mSamplerState.minFilter;
+}
+
+void Sampler::setMagFilter(GLenum magFilter)
+{
+ mSamplerState.magFilter = magFilter;
+}
+
+GLenum Sampler::getMagFilter() const
+{
+ return mSamplerState.magFilter;
+}
+
+void Sampler::setWrapS(GLenum wrapS)
+{
+ mSamplerState.wrapS = wrapS;
+}
+
+GLenum Sampler::getWrapS() const
+{
+ return mSamplerState.wrapS;
+}
+
+void Sampler::setWrapT(GLenum wrapT)
+{
+ mSamplerState.wrapT = wrapT;
+}
+
+GLenum Sampler::getWrapT() const
+{
+ return mSamplerState.wrapT;
+}
+
+void Sampler::setWrapR(GLenum wrapR)
+{
+ mSamplerState.wrapR = wrapR;
+}
+
+GLenum Sampler::getWrapR() const
+{
+ return mSamplerState.wrapR;
+}
+
+void Sampler::setMaxAnisotropy(float maxAnisotropy)
+{
+ mSamplerState.maxAnisotropy = maxAnisotropy;
+}
+
+float Sampler::getMaxAnisotropy() const
+{
+ return mSamplerState.maxAnisotropy;
+}
+
+void Sampler::setMinLod(GLfloat minLod)
+{
+ mSamplerState.minLod = minLod;
+}
+
+GLfloat Sampler::getMinLod() const
+{
+ return mSamplerState.minLod;
+}
+
+void Sampler::setMaxLod(GLfloat maxLod)
+{
+ mSamplerState.maxLod = maxLod;
+}
+
+GLfloat Sampler::getMaxLod() const
+{
+ return mSamplerState.maxLod;
+}
+
+void Sampler::setCompareMode(GLenum compareMode)
+{
+ mSamplerState.compareMode = compareMode;
+}
+
+GLenum Sampler::getCompareMode() const
+{
+ return mSamplerState.compareMode;
+}
+
+void Sampler::setCompareFunc(GLenum compareFunc)
+{
+ mSamplerState.compareFunc = compareFunc;
+}
+
+GLenum Sampler::getCompareFunc() const
+{
+ return mSamplerState.compareFunc;
+}
+
+void Sampler::setSRGBDecode(GLenum sRGBDecode)
+{
+ mSamplerState.sRGBDecode = sRGBDecode;
+}
+
+GLenum Sampler::getSRGBDecode() const
+{
+ return mSamplerState.sRGBDecode;
+}
+
+const SamplerState &Sampler::getSamplerState() const
+{
+ return mSamplerState;
+}
+
+rx::SamplerImpl *Sampler::getImplementation() const
+{
+ return mImpl;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/Sampler.h b/gfx/angle/src/libANGLE/Sampler.h
new file mode 100755
index 000000000..156d61f66
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Sampler.h
@@ -0,0 +1,82 @@
+//
+// Copyright (c) 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/angletypes.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class GLImplFactory;
+class SamplerImpl;
+}
+
+namespace gl
+{
+
+class Sampler final : public RefCountObject, public LabeledObject
+{
+ public:
+ Sampler(rx::GLImplFactory *factory, GLuint id);
+ ~Sampler() override;
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ void setMinFilter(GLenum minFilter);
+ GLenum getMinFilter() const;
+
+ void setMagFilter(GLenum magFilter);
+ GLenum getMagFilter() const;
+
+ void setWrapS(GLenum wrapS);
+ GLenum getWrapS() const;
+
+ void setWrapT(GLenum wrapT);
+ GLenum getWrapT() const;
+
+ void setWrapR(GLenum wrapR);
+ GLenum getWrapR() const;
+
+ void setMaxAnisotropy(float maxAnisotropy);
+ float getMaxAnisotropy() const;
+
+ void setMinLod(GLfloat minLod);
+ GLfloat getMinLod() const;
+
+ void setMaxLod(GLfloat maxLod);
+ GLfloat getMaxLod() const;
+
+ void setCompareMode(GLenum compareMode);
+ GLenum getCompareMode() const;
+
+ void setCompareFunc(GLenum compareFunc);
+ GLenum getCompareFunc() const;
+
+ void setSRGBDecode(GLenum sRGBDecode);
+ GLenum getSRGBDecode() const;
+
+ const SamplerState &getSamplerState() const;
+
+ rx::SamplerImpl *getImplementation() const;
+
+ private:
+ rx::SamplerImpl *mImpl;
+
+ std::string mLabel;
+
+ SamplerState mSamplerState;
+};
+
+}
+
+#endif // LIBANGLE_SAMPLER_H_
diff --git a/gfx/angle/src/libANGLE/Shader.cpp b/gfx/angle/src/libANGLE/Shader.cpp
new file mode 100755
index 000000000..a4c68950b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Shader.cpp
@@ -0,0 +1,432 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 <sstream>
+
+#include "common/utilities.h"
+#include "GLSLANG/ShaderLang.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/ShaderImpl.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/Context.h"
+
+namespace gl
+{
+
+namespace
+{
+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.staticUse)
+ {
+ result.push_back(var);
+ }
+ }
+ return result;
+}
+
+template <typename VarT>
+const std::vector<VarT> &GetShaderVariables(const std::vector<VarT> *variableList)
+{
+ ASSERT(variableList);
+ return *variableList;
+}
+
+} // 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.arraySize > y.arraySize;
+ }
+
+ // Special case for handling structs: we sort these to the end of the list
+ if (x.type == GL_STRUCT_ANGLEX)
+ {
+ return false;
+ }
+
+ if (y.type == GL_STRUCT_ANGLEX)
+ {
+ return true;
+ }
+
+ return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
+}
+
+ShaderState::ShaderState(GLenum shaderType) : mLabel(), mShaderType(shaderType), mShaderVersion(100)
+{
+ mLocalSize.fill(-1);
+}
+
+ShaderState::~ShaderState()
+{
+}
+
+Shader::Shader(ResourceManager *manager,
+ rx::GLImplFactory *implFactory,
+ const gl::Limitations &rendererLimitations,
+ GLenum type,
+ GLuint handle)
+ : mState(type),
+ mImplementation(implFactory->createShader(mState)),
+ mRendererLimitations(rendererLimitations),
+ mHandle(handle),
+ mType(type),
+ mRefCount(0),
+ mDeleteStatus(false),
+ mCompiled(false),
+ mResourceManager(manager)
+{
+ ASSERT(mImplementation);
+}
+
+Shader::~Shader()
+{
+ SafeDelete(mImplementation);
+}
+
+void Shader::setLabel(const std::string &label)
+{
+ mState.mLabel = label;
+}
+
+const std::string &Shader::getLabel() const
+{
+ return mState.mLabel;
+}
+
+GLuint 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
+{
+ if (mInfoLog.empty())
+ {
+ return 0;
+ }
+
+ return (static_cast<int>(mInfoLog.length()) + 1);
+}
+
+void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
+{
+ 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
+{
+ if (mState.mTranslatedSource.empty())
+ {
+ return 0;
+ }
+
+ return (static_cast<int>(mState.mTranslatedSource.length()) + 1);
+}
+
+int Shader::getTranslatedSourceWithDebugInfoLength() const
+{
+ const std::string &debugInfo = mImplementation->getDebugInfo();
+ if (debugInfo.empty())
+ {
+ return 0;
+ }
+
+ return (static_cast<int>(debugInfo.length()) + 1);
+}
+
+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(GLsizei bufSize, GLsizei *length, char *buffer) const
+{
+ getSourceImpl(mState.mTranslatedSource, bufSize, length, buffer);
+}
+
+void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const
+{
+ const std::string &debugInfo = mImplementation->getDebugInfo();
+ getSourceImpl(debugInfo, bufSize, length, buffer);
+}
+
+void Shader::compile(const Context *context)
+{
+ mState.mTranslatedSource.clear();
+ mInfoLog.clear();
+ mState.mShaderVersion = 100;
+ mState.mVaryings.clear();
+ mState.mUniforms.clear();
+ mState.mInterfaceBlocks.clear();
+ mState.mActiveAttributes.clear();
+ mState.mActiveOutputVariables.clear();
+
+ Compiler *compiler = context->getCompiler();
+ ShHandle compilerHandle = compiler->getCompilerHandle(mState.mShaderType);
+
+ std::stringstream sourceStream;
+
+ std::string sourcePath;
+ ShCompileOptions additionalOptions =
+ mImplementation->prepareSourceAndReturnOptions(&sourceStream, &sourcePath);
+ ShCompileOptions compileOptions = (SH_OBJECT_CODE | SH_VARIABLES | additionalOptions);
+
+ // Add default options to WebGL shaders to prevent unexpected behavior during compilation.
+ if (context->getExtensions().webglCompatibility)
+ {
+ compileOptions |= SH_LIMIT_CALL_STACK_DEPTH;
+ compileOptions |= SH_LIMIT_EXPRESSION_COMPLEXITY;
+ compileOptions |= SH_ENFORCE_PACKING_RESTRICTIONS;
+ }
+
+ // Some targets (eg 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)
+ {
+ compileOptions |= SH_VALIDATE_LOOP_INDEXING;
+ }
+
+ std::string sourceString = sourceStream.str();
+ std::vector<const char *> sourceCStrings;
+
+ if (!sourcePath.empty())
+ {
+ sourceCStrings.push_back(sourcePath.c_str());
+ }
+
+ sourceCStrings.push_back(sourceString.c_str());
+
+ bool result =
+ sh::Compile(compilerHandle, &sourceCStrings[0], sourceCStrings.size(), compileOptions);
+
+ if (!result)
+ {
+ mInfoLog = sh::GetInfoLog(compilerHandle);
+ TRACE("\n%s", mInfoLog.c_str());
+ mCompiled = false;
+ return;
+ }
+
+ mState.mTranslatedSource = sh::GetObjectCode(compilerHandle);
+
+#ifndef 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";
+
+ size_t curPos = 0;
+ while (curPos != std::string::npos)
+ {
+ size_t nextLine = mState.mSource.find("\n", curPos);
+ size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);
+
+ shaderStream << "// " << mState.mSource.substr(curPos, len);
+
+ curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
+ }
+ shaderStream << "\n\n";
+ shaderStream << mState.mTranslatedSource;
+ mState.mTranslatedSource = shaderStream.str();
+#endif
+
+ // Gather the shader information
+ mState.mShaderVersion = sh::GetShaderVersion(compilerHandle);
+
+ mState.mVaryings = GetShaderVariables(sh::GetVaryings(compilerHandle));
+ mState.mUniforms = GetShaderVariables(sh::GetUniforms(compilerHandle));
+ mState.mInterfaceBlocks = GetShaderVariables(sh::GetInterfaceBlocks(compilerHandle));
+
+ switch (mState.mShaderType)
+ {
+ case GL_COMPUTE_SHADER:
+ {
+ mState.mLocalSize = sh::GetComputeShaderLocalGroupSize(compilerHandle);
+ break;
+ }
+ case GL_VERTEX_SHADER:
+ {
+ mState.mActiveAttributes = GetActiveShaderVariables(sh::GetAttributes(compilerHandle));
+ break;
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
+ std::sort(mState.mVaryings.begin(), mState.mVaryings.end(), CompareShaderVar);
+ mState.mActiveOutputVariables =
+ GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ ASSERT(!mState.mTranslatedSource.empty());
+
+ mCompiled = mImplementation->postTranslateCompile(compiler, &mInfoLog);
+}
+
+void Shader::addRef()
+{
+ mRefCount++;
+}
+
+void Shader::release()
+{
+ mRefCount--;
+
+ if (mRefCount == 0 && mDeleteStatus)
+ {
+ mResourceManager->deleteShader(mHandle);
+ }
+}
+
+unsigned int Shader::getRefCount() const
+{
+ return mRefCount;
+}
+
+bool Shader::isFlaggedForDeletion() const
+{
+ return mDeleteStatus;
+}
+
+void Shader::flagForDeletion()
+{
+ mDeleteStatus = true;
+}
+
+int Shader::getShaderVersion() const
+{
+ return mState.mShaderVersion;
+}
+
+const std::vector<sh::Varying> &Shader::getVaryings() const
+{
+ return mState.getVaryings();
+}
+
+const std::vector<sh::Uniform> &Shader::getUniforms() const
+{
+ return mState.getUniforms();
+}
+
+const std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() const
+{
+ return mState.getInterfaceBlocks();
+}
+
+const std::vector<sh::Attribute> &Shader::getActiveAttributes() const
+{
+ return mState.getActiveAttributes();
+}
+
+const std::vector<sh::OutputVariable> &Shader::getActiveOutputVariables() const
+{
+ return mState.getActiveOutputVariables();
+}
+
+int Shader::getSemanticIndex(const std::string &attributeName) const
+{
+ if (!attributeName.empty())
+ {
+ const auto &activeAttributes = mState.getActiveAttributes();
+
+ int semanticIndex = 0;
+ for (size_t attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
+ {
+ const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
+
+ if (attribute.name == attributeName)
+ {
+ return semanticIndex;
+ }
+
+ semanticIndex += gl::VariableRegisterCount(attribute.type);
+ }
+ }
+
+ return -1;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/Shader.h b/gfx/angle/src/libANGLE/Shader.h
new file mode 100755
index 000000000..ee42a80a3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Shader.h
@@ -0,0 +1,154 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 <string>
+#include <list>
+#include <vector>
+
+#include "angle_gl.h"
+#include <GLSLANG/ShaderLang.h>
+
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Debug.h"
+
+namespace rx
+{
+class GLImplFactory;
+class ShaderImpl;
+class ShaderSh;
+}
+
+namespace gl
+{
+class Compiler;
+class ContextState;
+struct Limitations;
+class ResourceManager;
+class Context;
+
+class ShaderState final : angle::NonCopyable
+{
+ public:
+ ShaderState(GLenum shaderType);
+ ~ShaderState();
+
+ const std::string &getLabel() const { return mLabel; }
+
+ const std::string &getSource() const { return mSource; }
+ const std::string &getTranslatedSource() const { return mTranslatedSource; }
+
+ GLenum getShaderType() const { return mShaderType; }
+ int getShaderVersion() const { return mShaderVersion; }
+
+ const std::vector<sh::Varying> &getVaryings() const { return mVaryings; }
+ const std::vector<sh::Uniform> &getUniforms() const { return mUniforms; }
+ const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return mInterfaceBlocks; }
+ const std::vector<sh::Attribute> &getActiveAttributes() const { return mActiveAttributes; }
+ const std::vector<sh::OutputVariable> &getActiveOutputVariables() const
+ {
+ return mActiveOutputVariables;
+ }
+
+ private:
+ friend class Shader;
+
+ std::string mLabel;
+
+ GLenum mShaderType;
+ int mShaderVersion;
+ std::string mTranslatedSource;
+ std::string mSource;
+
+ sh::WorkGroupSize mLocalSize;
+
+ std::vector<sh::Varying> mVaryings;
+ std::vector<sh::Uniform> mUniforms;
+ std::vector<sh::InterfaceBlock> mInterfaceBlocks;
+ std::vector<sh::Attribute> mActiveAttributes;
+ std::vector<sh::OutputVariable> mActiveOutputVariables;
+};
+
+class Shader final : angle::NonCopyable, public LabeledObject
+{
+ public:
+ Shader(ResourceManager *manager,
+ rx::GLImplFactory *implFactory,
+ const gl::Limitations &rendererLimitations,
+ GLenum type,
+ GLuint handle);
+
+ virtual ~Shader();
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ GLenum getType() const { return mType; }
+ GLuint getHandle() const;
+
+ rx::ShaderImpl *getImplementation() const { return mImplementation; }
+
+ void deleteSource();
+ void setSource(GLsizei count, const char *const *string, const GLint *length);
+ int getInfoLogLength() const;
+ void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+ int getSourceLength() const;
+ void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
+ int getTranslatedSourceLength() const;
+ int getTranslatedSourceWithDebugInfoLength() const;
+ const std::string &getTranslatedSource() const { return mState.getTranslatedSource(); }
+ void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
+ void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const;
+
+ void compile(const Context *context);
+ bool isCompiled() const { return mCompiled; }
+
+ void addRef();
+ void release();
+ unsigned int getRefCount() const;
+ bool isFlaggedForDeletion() const;
+ void flagForDeletion();
+
+ int getShaderVersion() const;
+
+ const std::vector<sh::Varying> &getVaryings() const;
+ const std::vector<sh::Uniform> &getUniforms() const;
+ const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const;
+ const std::vector<sh::Attribute> &getActiveAttributes() const;
+ const std::vector<sh::OutputVariable> &getActiveOutputVariables() const;
+
+ int getSemanticIndex(const std::string &attributeName) const;
+
+ const sh::WorkGroupSize &getWorkGroupSize() const { return mState.mLocalSize; }
+
+ private:
+ static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer);
+
+ ShaderState mState;
+ rx::ShaderImpl *mImplementation;
+ const gl::Limitations &mRendererLimitations;
+ const GLuint mHandle;
+ const GLenum 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
+ bool mCompiled; // Indicates if this shader has been successfully compiled
+ std::string mInfoLog;
+
+ ResourceManager *mResourceManager;
+};
+
+bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y);
+}
+
+#endif // LIBANGLE_SHADER_H_
diff --git a/gfx/angle/src/libANGLE/State.cpp b/gfx/angle/src/libANGLE/State.cpp
new file mode 100755
index 000000000..a56bb1c5d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/State.cpp
@@ -0,0 +1,2014 @@
+//
+// Copyright (c) 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 <limits>
+#include <string.h>
+
+#include "common/BitSetIterator.h"
+#include "common/matrix_utils.h"
+#include "common/mathutil.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+
+namespace
+{
+
+GLenum ActiveQueryType(const GLenum type)
+{
+ return (type == GL_ANY_SAMPLES_PASSED_CONSERVATIVE) ? GL_ANY_SAMPLES_PASSED : type;
+}
+
+} // anonymous namepace
+
+namespace gl
+{
+
+State::State()
+ : mMaxDrawBuffers(0),
+ mMaxCombinedTextureImageUnits(0),
+ mDepthClearValue(0),
+ mStencilClearValue(0),
+ mScissorTest(false),
+ mSampleCoverage(false),
+ mSampleCoverageValue(0),
+ mSampleCoverageInvert(false),
+ mStencilRef(0),
+ mStencilBackRef(0),
+ mLineWidth(0),
+ mGenerateMipmapHint(GL_NONE),
+ mFragmentShaderDerivativeHint(GL_NONE),
+ mBindGeneratesResource(true),
+ mNearZ(0),
+ mFarZ(0),
+ mReadFramebuffer(nullptr),
+ mDrawFramebuffer(nullptr),
+ mProgram(nullptr),
+ mVertexArray(nullptr),
+ mActiveSampler(0),
+ mPrimitiveRestart(false),
+ mMultiSampling(false),
+ mSampleAlphaToOne(false),
+ mFramebufferSRGB(true)
+{
+}
+
+State::~State()
+{
+ reset();
+}
+
+void State::initialize(const Caps &caps,
+ const Extensions &extensions,
+ const Version &clientVersion,
+ bool debug,
+ bool bindGeneratesResource)
+{
+ mMaxDrawBuffers = caps.maxDrawBuffers;
+ mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
+
+ setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f);
+
+ mDepthClearValue = 1.0f;
+ mStencilClearValue = 0;
+
+ mRasterizer.rasterizerDiscard = false;
+ mRasterizer.cullFace = false;
+ mRasterizer.cullMode = GL_BACK;
+ mRasterizer.frontFace = GL_CCW;
+ mRasterizer.polygonOffsetFill = false;
+ mRasterizer.polygonOffsetFactor = 0.0f;
+ mRasterizer.polygonOffsetUnits = 0.0f;
+ mRasterizer.pointDrawMode = false;
+ mRasterizer.multiSample = false;
+ mScissorTest = false;
+ mScissor.x = 0;
+ mScissor.y = 0;
+ mScissor.width = 0;
+ mScissor.height = 0;
+
+ mBlend.blend = false;
+ mBlend.sourceBlendRGB = GL_ONE;
+ mBlend.sourceBlendAlpha = GL_ONE;
+ mBlend.destBlendRGB = GL_ZERO;
+ mBlend.destBlendAlpha = GL_ZERO;
+ mBlend.blendEquationRGB = GL_FUNC_ADD;
+ mBlend.blendEquationAlpha = GL_FUNC_ADD;
+ mBlend.sampleAlphaToCoverage = false;
+ mBlend.dither = true;
+
+ mBlendColor.red = 0;
+ mBlendColor.green = 0;
+ mBlendColor.blue = 0;
+ mBlendColor.alpha = 0;
+
+ mDepthStencil.depthTest = false;
+ mDepthStencil.depthFunc = GL_LESS;
+ mDepthStencil.depthMask = true;
+ mDepthStencil.stencilTest = false;
+ mDepthStencil.stencilFunc = GL_ALWAYS;
+ mDepthStencil.stencilMask = static_cast<GLuint>(-1);
+ mDepthStencil.stencilWritemask = static_cast<GLuint>(-1);
+ mDepthStencil.stencilBackFunc = GL_ALWAYS;
+ mDepthStencil.stencilBackMask = static_cast<GLuint>(-1);
+ mDepthStencil.stencilBackWritemask = static_cast<GLuint>(-1);
+ mDepthStencil.stencilFail = GL_KEEP;
+ mDepthStencil.stencilPassDepthFail = GL_KEEP;
+ mDepthStencil.stencilPassDepthPass = GL_KEEP;
+ mDepthStencil.stencilBackFail = GL_KEEP;
+ mDepthStencil.stencilBackPassDepthFail = GL_KEEP;
+ mDepthStencil.stencilBackPassDepthPass = GL_KEEP;
+
+ mStencilRef = 0;
+ mStencilBackRef = 0;
+
+ mSampleCoverage = false;
+ mSampleCoverageValue = 1.0f;
+ mSampleCoverageInvert = false;
+ mGenerateMipmapHint = GL_DONT_CARE;
+ mFragmentShaderDerivativeHint = GL_DONT_CARE;
+
+ mBindGeneratesResource = bindGeneratesResource;
+
+ mLineWidth = 1.0f;
+
+ mViewport.x = 0;
+ mViewport.y = 0;
+ mViewport.width = 0;
+ mViewport.height = 0;
+ mNearZ = 0.0f;
+ mFarZ = 1.0f;
+
+ mBlend.colorMaskRed = true;
+ mBlend.colorMaskGreen = true;
+ mBlend.colorMaskBlue = true;
+ mBlend.colorMaskAlpha = true;
+
+ mActiveSampler = 0;
+
+ mVertexAttribCurrentValues.resize(caps.maxVertexAttributes);
+
+ mUniformBuffers.resize(caps.maxCombinedUniformBlocks);
+
+ mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits);
+ mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits);
+ if (clientVersion >= Version(3, 0))
+ {
+ // TODO: These could also be enabled via extension
+ mSamplerTextures[GL_TEXTURE_2D_ARRAY].resize(caps.maxCombinedTextureImageUnits);
+ mSamplerTextures[GL_TEXTURE_3D].resize(caps.maxCombinedTextureImageUnits);
+ }
+ if (extensions.eglImageExternal || extensions.eglStreamConsumerExternal)
+ {
+ mSamplerTextures[GL_TEXTURE_EXTERNAL_OES].resize(caps.maxCombinedTextureImageUnits);
+ }
+
+ mSamplers.resize(caps.maxCombinedTextureImageUnits);
+
+ mActiveQueries[GL_ANY_SAMPLES_PASSED].set(nullptr);
+ mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(nullptr);
+ mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(nullptr);
+ mActiveQueries[GL_TIME_ELAPSED_EXT].set(nullptr);
+ mActiveQueries[GL_COMMANDS_COMPLETED_CHROMIUM].set(nullptr);
+
+ mProgram = nullptr;
+
+ mReadFramebuffer = nullptr;
+ mDrawFramebuffer = nullptr;
+
+ mPrimitiveRestart = false;
+
+ mDebug.setOutputEnabled(debug);
+ mDebug.setMaxLoggedMessages(extensions.maxDebugLoggedMessages);
+
+ if (extensions.framebufferMultisample)
+ {
+ mMultiSampling = true;
+ mSampleAlphaToOne = false;
+ }
+
+ mCoverageModulation = GL_NONE;
+
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
+ mPathStencilFunc = GL_ALWAYS;
+ mPathStencilRef = 0;
+ mPathStencilMask = std::numeric_limits<GLuint>::max();
+}
+
+void State::reset()
+{
+ for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++)
+ {
+ TextureBindingVector &textureVector = bindingVec->second;
+ for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
+ {
+ textureVector[textureIdx].set(NULL);
+ }
+ }
+ for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++)
+ {
+ mSamplers[samplerIdx].set(NULL);
+ }
+
+ mArrayBuffer.set(NULL);
+ mRenderbuffer.set(NULL);
+
+ if (mProgram)
+ {
+ mProgram->release();
+ }
+ mProgram = NULL;
+
+ mTransformFeedback.set(NULL);
+
+ for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++)
+ {
+ i->second.set(NULL);
+ }
+
+ mGenericUniformBuffer.set(NULL);
+ for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr)
+ {
+ bufItr->set(NULL);
+ }
+
+ mCopyReadBuffer.set(NULL);
+ mCopyWriteBuffer.set(NULL);
+
+ mPack.pixelBuffer.set(NULL);
+ mUnpack.pixelBuffer.set(NULL);
+
+ mProgram = NULL;
+
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
+ mPathStencilFunc = GL_ALWAYS;
+ mPathStencilRef = 0;
+ mPathStencilMask = std::numeric_limits<GLuint>::max();
+
+ // TODO(jmadill): Is this necessary?
+ setAllDirtyBits();
+}
+
+const RasterizerState &State::getRasterizerState() const
+{
+ return mRasterizer;
+}
+
+const BlendState &State::getBlendState() const
+{
+ return mBlend;
+}
+
+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)
+{
+ mBlend.colorMaskRed = red;
+ mBlend.colorMaskGreen = green;
+ mBlend.colorMaskBlue = blue;
+ mBlend.colorMaskAlpha = alpha;
+ mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+}
+
+void State::setDepthMask(bool mask)
+{
+ mDepthStencil.depthMask = mask;
+ mDirtyBits.set(DIRTY_BIT_DEPTH_MASK);
+}
+
+bool State::isRasterizerDiscardEnabled() const
+{
+ return mRasterizer.rasterizerDiscard;
+}
+
+void State::setRasterizerDiscard(bool enabled)
+{
+ mRasterizer.rasterizerDiscard = enabled;
+ mDirtyBits.set(DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
+}
+
+bool State::isCullFaceEnabled() const
+{
+ return mRasterizer.cullFace;
+}
+
+void State::setCullFace(bool enabled)
+{
+ mRasterizer.cullFace = enabled;
+ mDirtyBits.set(DIRTY_BIT_CULL_FACE_ENABLED);
+}
+
+void State::setCullMode(GLenum mode)
+{
+ mRasterizer.cullMode = mode;
+ mDirtyBits.set(DIRTY_BIT_CULL_FACE);
+}
+
+void State::setFrontFace(GLenum front)
+{
+ mRasterizer.frontFace = front;
+ mDirtyBits.set(DIRTY_BIT_FRONT_FACE);
+}
+
+bool State::isDepthTestEnabled() const
+{
+ return mDepthStencil.depthTest;
+}
+
+void State::setDepthTest(bool enabled)
+{
+ mDepthStencil.depthTest = enabled;
+ mDirtyBits.set(DIRTY_BIT_DEPTH_TEST_ENABLED);
+}
+
+void State::setDepthFunc(GLenum depthFunc)
+{
+ mDepthStencil.depthFunc = depthFunc;
+ mDirtyBits.set(DIRTY_BIT_DEPTH_FUNC);
+}
+
+void State::setDepthRange(float zNear, float zFar)
+{
+ mNearZ = zNear;
+ mFarZ = zFar;
+ mDirtyBits.set(DIRTY_BIT_DEPTH_RANGE);
+}
+
+float State::getNearPlane() const
+{
+ return mNearZ;
+}
+
+float State::getFarPlane() const
+{
+ return mFarZ;
+}
+
+bool State::isBlendEnabled() const
+{
+ return mBlend.blend;
+}
+
+void State::setBlend(bool enabled)
+{
+ mBlend.blend = enabled;
+ mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+}
+
+void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
+{
+ mBlend.sourceBlendRGB = sourceRGB;
+ mBlend.destBlendRGB = destRGB;
+ mBlend.sourceBlendAlpha = sourceAlpha;
+ mBlend.destBlendAlpha = destAlpha;
+ mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS);
+}
+
+void State::setBlendColor(float red, float green, float blue, float 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)
+{
+ mBlend.blendEquationRGB = rgbEquation;
+ mBlend.blendEquationAlpha = alphaEquation;
+ mDirtyBits.set(DIRTY_BIT_BLEND_EQUATIONS);
+}
+
+const ColorF &State::getBlendColor() const
+{
+ return mBlendColor;
+}
+
+bool State::isStencilTestEnabled() const
+{
+ return mDepthStencil.stencilTest;
+}
+
+void State::setStencilTest(bool enabled)
+{
+ mDepthStencil.stencilTest = enabled;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED);
+}
+
+void State::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
+{
+ mDepthStencil.stencilFunc = stencilFunc;
+ mStencilRef = (stencilRef > 0) ? stencilRef : 0;
+ mDepthStencil.stencilMask = stencilMask;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+}
+
+void State::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
+{
+ mDepthStencil.stencilBackFunc = stencilBackFunc;
+ mStencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
+ mDepthStencil.stencilBackMask = stencilBackMask;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+}
+
+void State::setStencilWritemask(GLuint stencilWritemask)
+{
+ mDepthStencil.stencilWritemask = stencilWritemask;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+}
+
+void State::setStencilBackWritemask(GLuint stencilBackWritemask)
+{
+ mDepthStencil.stencilBackWritemask = stencilBackWritemask;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+}
+
+void State::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum 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)
+{
+ mDepthStencil.stencilBackFail = stencilBackFail;
+ mDepthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail;
+ mDepthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
+}
+
+GLint State::getStencilRef() const
+{
+ return mStencilRef;
+}
+
+GLint State::getStencilBackRef() const
+{
+ return mStencilBackRef;
+}
+
+bool State::isPolygonOffsetFillEnabled() const
+{
+ return mRasterizer.polygonOffsetFill;
+}
+
+void State::setPolygonOffsetFill(bool 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);
+}
+
+bool State::isSampleAlphaToCoverageEnabled() const
+{
+ return mBlend.sampleAlphaToCoverage;
+}
+
+void State::setSampleAlphaToCoverage(bool enabled)
+{
+ mBlend.sampleAlphaToCoverage = enabled;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
+}
+
+bool State::isSampleCoverageEnabled() const
+{
+ return mSampleCoverage;
+}
+
+void State::setSampleCoverage(bool 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);
+}
+
+GLclampf State::getSampleCoverageValue() const
+{
+ return mSampleCoverageValue;
+}
+
+bool State::getSampleCoverageInvert() const
+{
+ return mSampleCoverageInvert;
+}
+
+void State::setSampleAlphaToOne(bool enabled)
+{
+ mSampleAlphaToOne = enabled;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
+}
+
+bool State::isSampleAlphaToOneEnabled() const
+{
+ return mSampleAlphaToOne;
+}
+
+void State::setMultisampling(bool enabled)
+{
+ mMultiSampling = enabled;
+ mDirtyBits.set(DIRTY_BIT_MULTISAMPLING);
+}
+
+bool State::isMultisamplingEnabled() const
+{
+ return mMultiSampling;
+}
+
+bool State::isScissorTestEnabled() const
+{
+ return mScissorTest;
+}
+
+void State::setScissorTest(bool enabled)
+{
+ mScissorTest = enabled;
+ mDirtyBits.set(DIRTY_BIT_SCISSOR_TEST_ENABLED);
+}
+
+void State::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ mScissor.x = x;
+ mScissor.y = y;
+ mScissor.width = width;
+ mScissor.height = height;
+ mDirtyBits.set(DIRTY_BIT_SCISSOR);
+}
+
+const Rectangle &State::getScissor() const
+{
+ return mScissor;
+}
+
+bool State::isDitherEnabled() const
+{
+ return mBlend.dither;
+}
+
+void State::setDither(bool enabled)
+{
+ mBlend.dither = enabled;
+ mDirtyBits.set(DIRTY_BIT_DITHER_ENABLED);
+}
+
+bool State::isPrimitiveRestartEnabled() const
+{
+ return mPrimitiveRestart;
+}
+
+void State::setPrimitiveRestart(bool enabled)
+{
+ mPrimitiveRestart = enabled;
+ mDirtyBits.set(DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
+}
+
+void State::setEnableFeature(GLenum feature, bool enabled)
+{
+ switch (feature)
+ {
+ case GL_MULTISAMPLE_EXT: setMultisampling(enabled); break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT: setSampleAlphaToOne(enabled); break;
+ case GL_CULL_FACE: setCullFace(enabled); break;
+ case GL_POLYGON_OFFSET_FILL: setPolygonOffsetFill(enabled); break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE: setSampleAlphaToCoverage(enabled); break;
+ case GL_SAMPLE_COVERAGE: setSampleCoverage(enabled); break;
+ case GL_SCISSOR_TEST: setScissorTest(enabled); break;
+ case GL_STENCIL_TEST: setStencilTest(enabled); break;
+ case GL_DEPTH_TEST: setDepthTest(enabled); break;
+ case GL_BLEND: setBlend(enabled); break;
+ case GL_DITHER: setDither(enabled); break;
+ case GL_PRIMITIVE_RESTART_FIXED_INDEX: setPrimitiveRestart(enabled); break;
+ case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break;
+ case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+ mDebug.setOutputSynchronous(enabled);
+ break;
+ case GL_DEBUG_OUTPUT:
+ mDebug.setOutputEnabled(enabled);
+ break;
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ setFramebufferSRGB(enabled);
+ 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_PRIMITIVE_RESTART_FIXED_INDEX: return isPrimitiveRestartEnabled();
+ case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled();
+ 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_FRAMEBUFFER_SRGB_EXT:
+ return getFramebufferSRGB();
+ default: UNREACHABLE(); return false;
+ }
+}
+
+void State::setLineWidth(GLfloat width)
+{
+ mLineWidth = width;
+ mDirtyBits.set(DIRTY_BIT_LINE_WIDTH);
+}
+
+float State::getLineWidth() const
+{
+ return mLineWidth;
+}
+
+void State::setGenerateMipmapHint(GLenum hint)
+{
+ mGenerateMipmapHint = hint;
+ mDirtyBits.set(DIRTY_BIT_GENERATE_MIPMAP_HINT);
+}
+
+void State::setFragmentShaderDerivativeHint(GLenum hint)
+{
+ mFragmentShaderDerivativeHint = hint;
+ mDirtyBits.set(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.
+}
+
+bool State::isBindGeneratesResourceEnabled() const
+{
+ return mBindGeneratesResource;
+}
+
+void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ mViewport.x = x;
+ mViewport.y = y;
+ mViewport.width = width;
+ mViewport.height = height;
+ mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+}
+
+const Rectangle &State::getViewport() const
+{
+ return mViewport;
+}
+
+void State::setActiveSampler(unsigned int active)
+{
+ mActiveSampler = active;
+}
+
+unsigned int State::getActiveSampler() const
+{
+ return static_cast<unsigned int>(mActiveSampler);
+}
+
+void State::setSamplerTexture(GLenum type, Texture *texture)
+{
+ mSamplerTextures[type][mActiveSampler].set(texture);
+}
+
+Texture *State::getTargetTexture(GLenum target) const
+{
+ return getSamplerTexture(static_cast<unsigned int>(mActiveSampler), target);
+}
+
+Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const
+{
+ const auto it = mSamplerTextures.find(type);
+ ASSERT(it != mSamplerTextures.end());
+ ASSERT(sampler < it->second.size());
+ return it->second[sampler].get();
+}
+
+GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const
+{
+ const auto it = mSamplerTextures.find(type);
+ ASSERT(it != mSamplerTextures.end());
+ ASSERT(sampler < it->second.size());
+ return it->second[sampler].id();
+}
+
+void State::detachTexture(const TextureMap &zeroTextures, GLuint 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 (auto &bindingVec : mSamplerTextures)
+ {
+ GLenum textureType = bindingVec.first;
+ TextureBindingVector &textureVector = bindingVec.second;
+ for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
+ {
+ BindingPointer<Texture> &binding = textureVector[textureIdx];
+ if (binding.id() == texture)
+ {
+ auto it = zeroTextures.find(textureType);
+ ASSERT(it != zeroTextures.end());
+ // Zero textures are the "default" textures instead of NULL
+ binding.set(it->second.get());
+ }
+ }
+ }
+
+ // [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(texture);
+ }
+
+ if (mDrawFramebuffer)
+ {
+ mDrawFramebuffer->detachTexture(texture);
+ }
+}
+
+void State::initializeZeroTextures(const TextureMap &zeroTextures)
+{
+ for (const auto &zeroTexture : zeroTextures)
+ {
+ auto &samplerTextureArray = mSamplerTextures[zeroTexture.first];
+
+ for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit)
+ {
+ samplerTextureArray[textureUnit].set(zeroTexture.second.get());
+ }
+ }
+}
+
+void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler)
+{
+ mSamplers[textureUnit].set(sampler);
+}
+
+GLuint State::getSamplerId(GLuint textureUnit) const
+{
+ ASSERT(textureUnit < mSamplers.size());
+ return mSamplers[textureUnit].id();
+}
+
+Sampler *State::getSampler(GLuint textureUnit) const
+{
+ return mSamplers[textureUnit].get();
+}
+
+void State::detachSampler(GLuint 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 textureUnit = 0; textureUnit < mSamplers.size(); textureUnit++)
+ {
+ BindingPointer<Sampler> &samplerBinding = mSamplers[textureUnit];
+ if (samplerBinding.id() == sampler)
+ {
+ samplerBinding.set(NULL);
+ }
+ }
+}
+
+void State::setRenderbufferBinding(Renderbuffer *renderbuffer)
+{
+ mRenderbuffer.set(renderbuffer);
+}
+
+GLuint State::getRenderbufferId() const
+{
+ return mRenderbuffer.id();
+}
+
+Renderbuffer *State::getCurrentRenderbuffer() const
+{
+ return mRenderbuffer.get();
+}
+
+void State::detachRenderbuffer(GLuint 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)
+ {
+ mRenderbuffer.set(NULL);
+ }
+
+ // [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(renderbuffer);
+ }
+
+ if (drawFramebuffer && drawFramebuffer != readFramebuffer)
+ {
+ drawFramebuffer->detachRenderbuffer(renderbuffer);
+ }
+
+}
+
+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->hasAnyDirtyBit())
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+ }
+}
+
+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 NULL;
+ }
+}
+
+Framebuffer *State::getReadFramebuffer() const
+{
+ return mReadFramebuffer;
+}
+
+Framebuffer *State::getDrawFramebuffer() const
+{
+ return mDrawFramebuffer;
+}
+
+bool State::removeReadFramebufferBinding(GLuint framebuffer)
+{
+ if (mReadFramebuffer != nullptr &&
+ mReadFramebuffer->id() == framebuffer)
+ {
+ setReadFramebufferBinding(nullptr);
+ return true;
+ }
+
+ return false;
+}
+
+bool State::removeDrawFramebufferBinding(GLuint framebuffer)
+{
+ if (mReadFramebuffer != nullptr &&
+ mDrawFramebuffer->id() == framebuffer)
+ {
+ setDrawFramebufferBinding(nullptr);
+ return true;
+ }
+
+ return false;
+}
+
+void State::setVertexArrayBinding(VertexArray *vertexArray)
+{
+ mVertexArray = vertexArray;
+ mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING);
+
+ if (mVertexArray && mVertexArray->hasAnyDirtyBit())
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ }
+}
+
+GLuint State::getVertexArrayId() const
+{
+ ASSERT(mVertexArray != NULL);
+ return mVertexArray->id();
+}
+
+VertexArray *State::getVertexArray() const
+{
+ ASSERT(mVertexArray != NULL);
+ return mVertexArray;
+}
+
+bool State::removeVertexArrayBinding(GLuint vertexArray)
+{
+ if (mVertexArray->id() == vertexArray)
+ {
+ mVertexArray = NULL;
+ mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ return true;
+ }
+
+ return false;
+}
+
+void State::setProgram(Program *newProgram)
+{
+ if (mProgram != newProgram)
+ {
+ if (mProgram)
+ {
+ mProgram->release();
+ }
+
+ mProgram = newProgram;
+
+ if (mProgram)
+ {
+ newProgram->addRef();
+ }
+ }
+}
+
+Program *State::getProgram() const
+{
+ return mProgram;
+}
+
+void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback)
+{
+ mTransformFeedback.set(transformFeedback);
+}
+
+TransformFeedback *State::getCurrentTransformFeedback() const
+{
+ return mTransformFeedback.get();
+}
+
+bool State::isTransformFeedbackActiveUnpaused() const
+{
+ gl::TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
+ return curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused();
+}
+
+bool State::removeTransformFeedbackBinding(GLuint transformFeedback)
+{
+ if (mTransformFeedback.id() == transformFeedback)
+ {
+ mTransformFeedback.set(nullptr);
+ return true;
+ }
+
+ return false;
+}
+
+bool State::isQueryActive(const GLenum type) const
+{
+ for (auto &iter : mActiveQueries)
+ {
+ const Query *query = iter.second.get();
+ if (query != nullptr && ActiveQueryType(query->getType()) == ActiveQueryType(type))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool State::isQueryActive(Query *query) const
+{
+ for (auto &iter : mActiveQueries)
+ {
+ if (iter.second.get() == query)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void State::setActiveQuery(GLenum target, Query *query)
+{
+ mActiveQueries[target].set(query);
+}
+
+GLuint State::getActiveQueryId(GLenum target) const
+{
+ const Query *query = getActiveQuery(target);
+ return (query ? query->id() : 0u);
+}
+
+Query *State::getActiveQuery(GLenum target) const
+{
+ const auto it = mActiveQueries.find(target);
+
+ // All query types should already exist in the activeQueries map
+ ASSERT(it != mActiveQueries.end());
+
+ return it->second.get();
+}
+
+void State::setArrayBufferBinding(Buffer *buffer)
+{
+ mArrayBuffer.set(buffer);
+}
+
+GLuint State::getArrayBufferId() const
+{
+ return mArrayBuffer.id();
+}
+
+void State::setGenericUniformBufferBinding(Buffer *buffer)
+{
+ mGenericUniformBuffer.set(buffer);
+}
+
+void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size)
+{
+ mUniformBuffers[index].set(buffer, offset, size);
+}
+
+const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index) const
+{
+ ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+ return mUniformBuffers[index];
+}
+
+void State::setCopyReadBufferBinding(Buffer *buffer)
+{
+ mCopyReadBuffer.set(buffer);
+}
+
+void State::setCopyWriteBufferBinding(Buffer *buffer)
+{
+ mCopyWriteBuffer.set(buffer);
+}
+
+void State::setPixelPackBufferBinding(Buffer *buffer)
+{
+ mPack.pixelBuffer.set(buffer);
+ mDirtyBits.set(DIRTY_BIT_PACK_BUFFER_BINDING);
+}
+
+void State::setPixelUnpackBufferBinding(Buffer *buffer)
+{
+ mUnpack.pixelBuffer.set(buffer);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_BUFFER_BINDING);
+}
+
+Buffer *State::getTargetBuffer(GLenum target) const
+{
+ switch (target)
+ {
+ case GL_ARRAY_BUFFER: return mArrayBuffer.get();
+ case GL_COPY_READ_BUFFER: return mCopyReadBuffer.get();
+ case GL_COPY_WRITE_BUFFER: return mCopyWriteBuffer.get();
+ case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer().get();
+ case GL_PIXEL_PACK_BUFFER: return mPack.pixelBuffer.get();
+ case GL_PIXEL_UNPACK_BUFFER: return mUnpack.pixelBuffer.get();
+ case GL_TRANSFORM_FEEDBACK_BUFFER: return mTransformFeedback->getGenericBuffer().get();
+ case GL_UNIFORM_BUFFER: return mGenericUniformBuffer.get();
+ default: UNREACHABLE(); return NULL;
+ }
+}
+
+void State::detachBuffer(GLuint bufferName)
+{
+ BindingPointer<Buffer> *buffers[] = {&mArrayBuffer, &mCopyReadBuffer,
+ &mCopyWriteBuffer, &mPack.pixelBuffer,
+ &mUnpack.pixelBuffer, &mGenericUniformBuffer};
+ for (auto buffer : buffers)
+ {
+ if (buffer->id() == bufferName)
+ {
+ buffer->set(nullptr);
+ }
+ }
+
+ TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
+ if (curTransformFeedback)
+ {
+ curTransformFeedback->detachBuffer(bufferName);
+ }
+
+ getVertexArray()->detachBuffer(bufferName);
+}
+
+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_VALUE_0 + index);
+}
+
+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_VALUE_0 + index);
+}
+
+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_VALUE_0 + index);
+}
+
+void State::setVertexAttribState(unsigned int attribNum,
+ Buffer *boundBuffer,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLsizei stride,
+ const void *pointer)
+{
+ getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexAttribDivisor(GLuint index, GLuint divisor)
+{
+ getVertexArray()->setVertexAttribDivisor(index, divisor);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const
+{
+ ASSERT(static_cast<size_t>(attribNum) < mVertexAttribCurrentValues.size());
+ return mVertexAttribCurrentValues[attribNum];
+}
+
+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_ALIGNMENT);
+}
+
+GLint State::getPackAlignment() const
+{
+ return mPack.alignment;
+}
+
+void State::setPackReverseRowOrder(bool reverseRowOrder)
+{
+ mPack.reverseRowOrder = reverseRowOrder;
+ mDirtyBits.set(DIRTY_BIT_PACK_REVERSE_ROW_ORDER);
+}
+
+bool State::getPackReverseRowOrder() const
+{
+ return mPack.reverseRowOrder;
+}
+
+void State::setPackRowLength(GLint rowLength)
+{
+ mPack.rowLength = rowLength;
+ mDirtyBits.set(DIRTY_BIT_PACK_ROW_LENGTH);
+}
+
+GLint State::getPackRowLength() const
+{
+ return mPack.rowLength;
+}
+
+void State::setPackSkipRows(GLint skipRows)
+{
+ mPack.skipRows = skipRows;
+ mDirtyBits.set(DIRTY_BIT_PACK_SKIP_ROWS);
+}
+
+GLint State::getPackSkipRows() const
+{
+ return mPack.skipRows;
+}
+
+void State::setPackSkipPixels(GLint skipPixels)
+{
+ mPack.skipPixels = skipPixels;
+ mDirtyBits.set(DIRTY_BIT_PACK_SKIP_PIXELS);
+}
+
+GLint State::getPackSkipPixels() const
+{
+ return mPack.skipPixels;
+}
+
+const PixelPackState &State::getPackState() const
+{
+ return mPack;
+}
+
+PixelPackState &State::getPackState()
+{
+ return mPack;
+}
+
+void State::setUnpackAlignment(GLint alignment)
+{
+ mUnpack.alignment = alignment;
+ mDirtyBits.set(DIRTY_BIT_UNPACK_ALIGNMENT);
+}
+
+GLint State::getUnpackAlignment() const
+{
+ return mUnpack.alignment;
+}
+
+void State::setUnpackRowLength(GLint rowLength)
+{
+ mUnpack.rowLength = rowLength;
+ mDirtyBits.set(DIRTY_BIT_UNPACK_ROW_LENGTH);
+}
+
+GLint State::getUnpackRowLength() const
+{
+ return mUnpack.rowLength;
+}
+
+void State::setUnpackImageHeight(GLint imageHeight)
+{
+ mUnpack.imageHeight = imageHeight;
+ mDirtyBits.set(DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
+}
+
+GLint State::getUnpackImageHeight() const
+{
+ return mUnpack.imageHeight;
+}
+
+void State::setUnpackSkipImages(GLint skipImages)
+{
+ mUnpack.skipImages = skipImages;
+ mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_IMAGES);
+}
+
+GLint State::getUnpackSkipImages() const
+{
+ return mUnpack.skipImages;
+}
+
+void State::setUnpackSkipRows(GLint skipRows)
+{
+ mUnpack.skipRows = skipRows;
+ mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_ROWS);
+}
+
+GLint State::getUnpackSkipRows() const
+{
+ return mUnpack.skipRows;
+}
+
+void State::setUnpackSkipPixels(GLint skipPixels)
+{
+ mUnpack.skipPixels = skipPixels;
+ mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_PIXELS);
+}
+
+GLint State::getUnpackSkipPixels() const
+{
+ return mUnpack.skipPixels;
+}
+
+const PixelUnpackState &State::getUnpackState() const
+{
+ return mUnpack;
+}
+
+PixelUnpackState &State::getUnpackState()
+{
+ return mUnpack;
+}
+
+const Debug &State::getDebug() const
+{
+ return mDebug;
+}
+
+Debug &State::getDebug()
+{
+ return mDebug;
+}
+
+void State::setCoverageModulation(GLenum components)
+{
+ mCoverageModulation = components;
+ mDirtyBits.set(DIRTY_BIT_COVERAGE_MODULATION);
+}
+
+GLenum State::getCoverageModulation() const
+{
+ return mCoverageModulation;
+}
+
+void State::loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix)
+{
+ if (matrixMode == GL_PATH_MODELVIEW_CHROMIUM)
+ {
+ memcpy(mPathMatrixMV, matrix, 16 * sizeof(GLfloat));
+ mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_MATRIX_MV);
+ }
+ else if (matrixMode == GL_PATH_PROJECTION_CHROMIUM)
+ {
+ memcpy(mPathMatrixProj, matrix, 16 * sizeof(GLfloat));
+ mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+}
+
+const GLfloat *State::getPathRenderingMatrix(GLenum which) const
+{
+ if (which == GL_PATH_MODELVIEW_MATRIX_CHROMIUM)
+ {
+ return mPathMatrixMV;
+ }
+ else if (which == GL_PATH_PROJECTION_MATRIX_CHROMIUM)
+ {
+ return mPathMatrixProj;
+ }
+
+ UNREACHABLE();
+ return nullptr;
+}
+
+void State::setPathStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ mPathStencilFunc = func;
+ mPathStencilRef = ref;
+ mPathStencilMask = mask;
+ mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_STENCIL_STATE);
+}
+
+GLenum State::getPathStencilFunc() const
+{
+ return mPathStencilFunc;
+}
+
+GLint State::getPathStencilRef() const
+{
+ return mPathStencilRef;
+}
+
+GLuint State::getPathStencilMask() const
+{
+ return mPathStencilMask;
+}
+
+void State::setFramebufferSRGB(bool sRGB)
+{
+ mFramebufferSRGB = sRGB;
+ mDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_SRGB);
+}
+
+bool State::getFramebufferSRGB() const
+{
+ return mFramebufferSRGB;
+}
+
+void State::getBooleanv(GLenum pname, GLboolean *params)
+{
+ switch (pname)
+ {
+ case GL_SAMPLE_COVERAGE_INVERT: *params = mSampleCoverageInvert; break;
+ case GL_DEPTH_WRITEMASK: *params = mDepthStencil.depthMask; break;
+ case GL_COLOR_WRITEMASK:
+ params[0] = mBlend.colorMaskRed;
+ params[1] = mBlend.colorMaskGreen;
+ params[2] = mBlend.colorMaskBlue;
+ params[3] = mBlend.colorMaskAlpha;
+ 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 = mBlend.sampleAlphaToCoverage; break;
+ case GL_SAMPLE_COVERAGE: *params = mSampleCoverage; 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: *params = mBlend.blend; break;
+ case GL_DITHER: *params = mBlend.dither; 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_FRAMEBUFFER_SRGB_EXT:
+ *params = getFramebufferSRGB() ? GL_TRUE : GL_FALSE;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void State::getFloatv(GLenum pname, GLfloat *params)
+{
+ // 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);
+ case GL_COVERAGE_MODULATION_CHROMIUM:
+ params[0] = static_cast<GLfloat>(mCoverageModulation);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void State::getIntegerv(const ContextState &data, GLenum pname, GLint *params)
+{
+ if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
+ {
+ unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT);
+ ASSERT(colorAttachment < mMaxDrawBuffers);
+ Framebuffer *framebuffer = mDrawFramebuffer;
+ *params = framebuffer->getDrawBufferState(colorAttachment);
+ return;
+ }
+
+ // 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 = mArrayBuffer.id(); break;
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getVertexArray()->getElementArrayBuffer().id(); break;
+ //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
+ case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mDrawFramebuffer->id(); break;
+ case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mReadFramebuffer->id(); break;
+ case GL_RENDERBUFFER_BINDING: *params = mRenderbuffer.id(); break;
+ case GL_VERTEX_ARRAY_BINDING: *params = mVertexArray->id(); break;
+ case GL_CURRENT_PROGRAM: *params = mProgram ? mProgram->id() : 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_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 = clampToInt(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 = clampToInt(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: *params = mBlend.sourceBlendRGB; break;
+ case GL_BLEND_SRC_ALPHA: *params = mBlend.sourceBlendAlpha; break;
+ case GL_BLEND_DST_RGB: *params = mBlend.destBlendRGB; break;
+ case GL_BLEND_DST_ALPHA: *params = mBlend.destBlendAlpha; break;
+ case GL_BLEND_EQUATION_RGB: *params = mBlend.blendEquationRGB; break;
+ case GL_BLEND_EQUATION_ALPHA: *params = mBlend.blendEquationAlpha; break;
+ case GL_STENCIL_WRITEMASK: *params = clampToInt(mDepthStencil.stencilWritemask); break;
+ case GL_STENCIL_BACK_WRITEMASK: *params = clampToInt(mDepthStencil.stencilBackWritemask); break;
+ case GL_STENCIL_CLEAR_VALUE: *params = mStencilClearValue; break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = mReadFramebuffer->getImplementationColorReadType(); break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = mReadFramebuffer->getImplementationColorReadFormat(); break;
+ case GL_SAMPLE_BUFFERS:
+ case GL_SAMPLES:
+ {
+ gl::Framebuffer *framebuffer = mDrawFramebuffer;
+ if (framebuffer->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
+ {
+ switch (pname)
+ {
+ case GL_SAMPLE_BUFFERS:
+ if (framebuffer->getSamples(data) != 0)
+ {
+ *params = 1;
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+ case GL_SAMPLES:
+ *params = framebuffer->getSamples(data);
+ 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 = 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:
+ {
+ gl::Framebuffer *framebuffer = getDrawFramebuffer();
+ const gl::FramebufferAttachment *colorbuffer = framebuffer->getFirstColorbuffer();
+
+ 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 gl::Framebuffer *framebuffer = getDrawFramebuffer();
+ const gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer();
+
+ if (depthbuffer)
+ {
+ *params = depthbuffer->getDepthSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ break;
+ case GL_STENCIL_BITS:
+ {
+ const gl::Framebuffer *framebuffer = getDrawFramebuffer();
+ const gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer();
+
+ if (stencilbuffer)
+ {
+ *params = stencilbuffer->getStencilSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_2D);
+ break;
+ case GL_TEXTURE_BINDING_CUBE_MAP:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params =
+ getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_CUBE_MAP);
+ break;
+ case GL_TEXTURE_BINDING_3D:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_3D);
+ break;
+ case GL_TEXTURE_BINDING_2D_ARRAY:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params =
+ getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_2D_ARRAY);
+ break;
+ case GL_TEXTURE_BINDING_EXTERNAL_OES:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ GL_TEXTURE_EXTERNAL_OES);
+ break;
+ case GL_UNIFORM_BUFFER_BINDING:
+ *params = mGenericUniformBuffer.id();
+ break;
+ case GL_TRANSFORM_FEEDBACK_BINDING:
+ *params = mTransformFeedback.id();
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ *params = mTransformFeedback->getGenericBuffer().id();
+ break;
+ case GL_COPY_READ_BUFFER_BINDING:
+ *params = mCopyReadBuffer.id();
+ break;
+ case GL_COPY_WRITE_BUFFER_BINDING:
+ *params = mCopyWriteBuffer.id();
+ break;
+ case GL_PIXEL_PACK_BUFFER_BINDING:
+ *params = mPack.pixelBuffer.id();
+ break;
+ case GL_PIXEL_UNPACK_BUFFER_BINDING:
+ *params = mUnpack.pixelBuffer.id();
+ break;
+ case GL_READ_BUFFER:
+ *params = mReadFramebuffer->getReadBufferState();
+ break;
+ case GL_SAMPLER_BINDING:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params = getSamplerId(static_cast<GLuint>(mActiveSampler));
+ 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);
+ case GL_COVERAGE_MODULATION_CHROMIUM:
+ *params = static_cast<GLint>(mCoverageModulation);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void State::getPointerv(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;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void State::getIntegeri_v(GLenum target, GLuint index, GLint *data)
+{
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount())
+ {
+ *data = mTransformFeedback->getIndexedBuffer(index).id();
+ }
+ break;
+ case GL_UNIFORM_BUFFER_BINDING:
+ if (static_cast<size_t>(index) < mUniformBuffers.size())
+ {
+ *data = mUniformBuffers[index].id();
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void State::getInteger64i_v(GLenum target, GLuint index, GLint64 *data)
+{
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount())
+ {
+ *data = mTransformFeedback->getIndexedBuffer(index).getOffset();
+ }
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount())
+ {
+ *data = mTransformFeedback->getIndexedBuffer(index).getSize();
+ }
+ break;
+ case GL_UNIFORM_BUFFER_START:
+ if (static_cast<size_t>(index) < mUniformBuffers.size())
+ {
+ *data = mUniformBuffers[index].getOffset();
+ }
+ break;
+ case GL_UNIFORM_BUFFER_SIZE:
+ if (static_cast<size_t>(index) < mUniformBuffers.size())
+ {
+ *data = mUniformBuffers[index].getSize();
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void State::getBooleani_v(GLenum target, GLuint index, GLboolean *data)
+{
+ UNREACHABLE();
+}
+
+bool State::hasMappedBuffer(GLenum target) const
+{
+ if (target == GL_ARRAY_BUFFER)
+ {
+ const VertexArray *vao = getVertexArray();
+ const auto &vertexAttribs = vao->getVertexAttributes();
+ size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
+ for (size_t attribIndex = 0; attribIndex < maxEnabledAttrib; attribIndex++)
+ {
+ const gl::VertexAttribute &vertexAttrib = vertexAttribs[attribIndex];
+ gl::Buffer *boundBuffer = vertexAttrib.buffer.get();
+ if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped())
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ else
+ {
+ Buffer *buffer = getTargetBuffer(target);
+ return (buffer && buffer->isMapped());
+ }
+}
+
+void State::syncDirtyObjects()
+{
+ if (!mDirtyObjects.any())
+ return;
+
+ syncDirtyObjects(mDirtyObjects);
+}
+
+void State::syncDirtyObjects(const DirtyObjects &bitset)
+{
+ for (auto dirtyObject : angle::IterateBitSet(bitset))
+ {
+ switch (dirtyObject)
+ {
+ case DIRTY_OBJECT_READ_FRAMEBUFFER:
+ ASSERT(mReadFramebuffer);
+ mReadFramebuffer->syncState();
+ break;
+ case DIRTY_OBJECT_DRAW_FRAMEBUFFER:
+ ASSERT(mDrawFramebuffer);
+ mDrawFramebuffer->syncState();
+ break;
+ case DIRTY_OBJECT_VERTEX_ARRAY:
+ ASSERT(mVertexArray);
+ mVertexArray->syncImplState();
+ break;
+ case DIRTY_OBJECT_PROGRAM:
+ // TODO(jmadill): implement this
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+
+ mDirtyObjects &= ~bitset;
+}
+
+void State::syncDirtyObject(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_PROGRAM:
+ localSet.set(DIRTY_OBJECT_PROGRAM);
+ break;
+ }
+
+ syncDirtyObjects(localSet);
+}
+
+void State::setObjectDirty(GLenum target)
+{
+ switch (target)
+ {
+ case GL_READ_FRAMEBUFFER:
+ mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+ break;
+ case GL_DRAW_FRAMEBUFFER:
+ mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+ break;
+ case GL_FRAMEBUFFER:
+ mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+ mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+ break;
+ case GL_VERTEX_ARRAY:
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ break;
+ case GL_PROGRAM:
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM);
+ break;
+ }
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/State.h b/gfx/angle/src/libANGLE/State.h
new file mode 100755
index 000000000..160a7abd8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/State.h
@@ -0,0 +1,497 @@
+//
+// Copyright (c) 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/angleutils.h"
+#include "common/Color.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Program.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/VertexAttribute.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+class Query;
+class VertexArray;
+class Context;
+struct Caps;
+
+typedef std::map<GLenum, BindingPointer<Texture>> TextureMap;
+
+class State : angle::NonCopyable
+{
+ public:
+ State();
+ ~State();
+
+ void initialize(const Caps &caps,
+ const Extensions &extensions,
+ const Version &clientVersion,
+ bool debug,
+ bool bindGeneratesResource);
+ void reset();
+
+ // State chunk getters
+ const RasterizerState &getRasterizerState() const;
+ const BlendState &getBlendState() const;
+ 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 setDepthMask(bool mask);
+
+ // Discard toggle & query
+ bool isRasterizerDiscardEnabled() const;
+ void setRasterizerDiscard(bool enabled);
+
+ // Primitive restart
+ bool isPrimitiveRestartEnabled() const;
+ void setPrimitiveRestart(bool enabled);
+
+ // Face culling state manipulation
+ bool isCullFaceEnabled() const;
+ void setCullFace(bool enabled);
+ void setCullMode(GLenum mode);
+ void setFrontFace(GLenum front);
+
+ // Depth test state manipulation
+ bool isDepthTestEnabled() const;
+ void setDepthTest(bool enabled);
+ void setDepthFunc(GLenum depthFunc);
+ void setDepthRange(float zNear, float zFar);
+ float getNearPlane() const;
+ float getFarPlane() const;
+
+ // Blend state manipulation
+ bool isBlendEnabled() const;
+ void setBlend(bool enabled);
+ void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);
+ void setBlendColor(float red, float green, float blue, float alpha);
+ void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation);
+ const ColorF &getBlendColor() const;
+
+ // Stencil state maniupulation
+ bool isStencilTestEnabled() const;
+ 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;
+ GLint getStencilBackRef() const;
+
+ // Depth bias/polygon offset state manipulation
+ bool isPolygonOffsetFillEnabled() const;
+ void setPolygonOffsetFill(bool enabled);
+ void setPolygonOffsetParams(GLfloat factor, GLfloat units);
+
+ // Multisample coverage state manipulation
+ bool isSampleAlphaToCoverageEnabled() const;
+ void setSampleAlphaToCoverage(bool enabled);
+ bool isSampleCoverageEnabled() const;
+ void setSampleCoverage(bool enabled);
+ void setSampleCoverageParams(GLclampf value, bool invert);
+ GLclampf getSampleCoverageValue() const;
+ bool getSampleCoverageInvert() const;
+
+ // Multisampling/alpha to one manipulation.
+ void setSampleAlphaToOne(bool enabled);
+ bool isSampleAlphaToOneEnabled() const;
+ void setMultisampling(bool enabled);
+ bool isMultisamplingEnabled() const;
+
+ // Scissor test state toggle & query
+ bool isScissorTestEnabled() const;
+ void setScissorTest(bool enabled);
+ void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height);
+ const Rectangle &getScissor() const;
+
+ // Dither state toggle & query
+ bool isDitherEnabled() const;
+ void setDither(bool enabled);
+
+ // Generic state toggle & query
+ void setEnableFeature(GLenum feature, bool enabled);
+ bool getEnableFeature(GLenum feature) const;
+
+ // Line width state setter
+ void setLineWidth(GLfloat width);
+ float getLineWidth() const;
+
+ // Hint setters
+ void setGenerateMipmapHint(GLenum hint);
+ void setFragmentShaderDerivativeHint(GLenum hint);
+
+ // GL_CHROMIUM_bind_generates_resource
+ bool isBindGeneratesResourceEnabled() const;
+
+ // Viewport state setter/getter
+ void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
+ const Rectangle &getViewport() const;
+
+ // Texture binding & active texture unit manipulation
+ void setActiveSampler(unsigned int active);
+ unsigned int getActiveSampler() const;
+ void setSamplerTexture(GLenum type, Texture *texture);
+ Texture *getTargetTexture(GLenum target) const;
+ Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
+ GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const;
+ void detachTexture(const TextureMap &zeroTextures, GLuint texture);
+ void initializeZeroTextures(const TextureMap &zeroTextures);
+
+ // Sampler object binding manipulation
+ void setSamplerBinding(GLuint textureUnit, Sampler *sampler);
+ GLuint getSamplerId(GLuint textureUnit) const;
+ Sampler *getSampler(GLuint textureUnit) const;
+ void detachSampler(GLuint sampler);
+
+ // Renderbuffer binding manipulation
+ void setRenderbufferBinding(Renderbuffer *renderbuffer);
+ GLuint getRenderbufferId() const;
+ Renderbuffer *getCurrentRenderbuffer() const;
+ void detachRenderbuffer(GLuint renderbuffer);
+
+ // Framebuffer binding manipulation
+ void setReadFramebufferBinding(Framebuffer *framebuffer);
+ void setDrawFramebufferBinding(Framebuffer *framebuffer);
+ Framebuffer *getTargetFramebuffer(GLenum target) const;
+ Framebuffer *getReadFramebuffer() const;
+ Framebuffer *getDrawFramebuffer() const;
+ bool removeReadFramebufferBinding(GLuint framebuffer);
+ bool removeDrawFramebufferBinding(GLuint framebuffer);
+
+ // Vertex array object binding manipulation
+ void setVertexArrayBinding(VertexArray *vertexArray);
+ GLuint getVertexArrayId() const;
+ VertexArray *getVertexArray() const;
+ bool removeVertexArrayBinding(GLuint vertexArray);
+
+ // Program binding manipulation
+ void setProgram(Program *newProgram);
+ Program *getProgram() const;
+
+ // Transform feedback object (not buffer) binding manipulation
+ void setTransformFeedbackBinding(TransformFeedback *transformFeedback);
+ TransformFeedback *getCurrentTransformFeedback() const;
+ bool isTransformFeedbackActiveUnpaused() const;
+ bool removeTransformFeedbackBinding(GLuint transformFeedback);
+
+ // Query binding manipulation
+ bool isQueryActive(const GLenum type) const;
+ bool isQueryActive(Query *query) const;
+ void setActiveQuery(GLenum target, Query *query);
+ GLuint getActiveQueryId(GLenum target) const;
+ Query *getActiveQuery(GLenum target) const;
+
+ //// Typed buffer binding point manipulation ////
+ // GL_ARRAY_BUFFER
+ void setArrayBufferBinding(Buffer *buffer);
+ GLuint getArrayBufferId() const;
+
+ // GL_UNIFORM_BUFFER - Both indexed and generic targets
+ void setGenericUniformBufferBinding(Buffer *buffer);
+ void setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size);
+ const OffsetBindingPointer<Buffer> &getIndexedUniformBuffer(size_t index) const;
+
+ // GL_COPY_[READ/WRITE]_BUFFER
+ void setCopyReadBufferBinding(Buffer *buffer);
+ void setCopyWriteBufferBinding(Buffer *buffer);
+
+ // GL_PIXEL[PACK/UNPACK]_BUFFER
+ void setPixelPackBufferBinding(Buffer *buffer);
+ void setPixelUnpackBufferBinding(Buffer *buffer);
+
+ // Retrieve typed buffer by target (non-indexed)
+ Buffer *getTargetBuffer(GLenum target) const;
+ // Detach a buffer from all bindings
+ void detachBuffer(GLuint bufferName);
+
+ // 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]);
+ void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type,
+ bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
+ void setVertexAttribDivisor(GLuint index, GLuint divisor);
+ const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const;
+ const void *getVertexAttribPointer(unsigned int attribNum) const;
+
+ // Pixel pack state manipulation
+ void setPackAlignment(GLint alignment);
+ GLint getPackAlignment() const;
+ void setPackReverseRowOrder(bool reverseRowOrder);
+ bool getPackReverseRowOrder() const;
+ void setPackRowLength(GLint rowLength);
+ GLint getPackRowLength() const;
+ void setPackSkipRows(GLint skipRows);
+ GLint getPackSkipRows() const;
+ void setPackSkipPixels(GLint skipPixels);
+ GLint getPackSkipPixels() const;
+ const PixelPackState &getPackState() const;
+ PixelPackState &getPackState();
+
+ // Pixel unpack state manipulation
+ void setUnpackAlignment(GLint alignment);
+ GLint getUnpackAlignment() const;
+ void setUnpackRowLength(GLint rowLength);
+ GLint getUnpackRowLength() const;
+ void setUnpackImageHeight(GLint imageHeight);
+ GLint getUnpackImageHeight() const;
+ void setUnpackSkipImages(GLint skipImages);
+ GLint getUnpackSkipImages() const;
+ void setUnpackSkipRows(GLint skipRows);
+ GLint getUnpackSkipRows() const;
+ void setUnpackSkipPixels(GLint skipPixels);
+ GLint getUnpackSkipPixels() const;
+ const PixelUnpackState &getUnpackState() const;
+ PixelUnpackState &getUnpackState();
+
+ // Debug state
+ const Debug &getDebug() const;
+ Debug &getDebug();
+
+ // CHROMIUM_framebuffer_mixed_samples coverage modulation
+ void setCoverageModulation(GLenum components);
+ GLenum getCoverageModulation() const;
+
+ // CHROMIUM_path_rendering
+ void loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix);
+ const GLfloat *getPathRenderingMatrix(GLenum which) const;
+ void setPathStencilFunc(GLenum func, GLint ref, GLuint mask);
+
+ GLenum getPathStencilFunc() const;
+ GLint getPathStencilRef() const;
+ GLuint getPathStencilMask() const;
+
+ // GL_EXT_sRGB_write_control
+ void setFramebufferSRGB(bool sRGB);
+ bool getFramebufferSRGB() const;
+
+ // State query functions
+ void getBooleanv(GLenum pname, GLboolean *params);
+ void getFloatv(GLenum pname, GLfloat *params);
+ void getIntegerv(const ContextState &data, GLenum pname, GLint *params);
+ void getPointerv(GLenum pname, void **params) const;
+ void getIntegeri_v(GLenum target, GLuint index, GLint *data);
+ void getInteger64i_v(GLenum target, GLuint index, GLint64 *data);
+ void getBooleani_v(GLenum target, GLuint index, GLboolean *data);
+
+ bool hasMappedBuffer(GLenum target) const;
+
+ enum DirtyBitType
+ {
+ 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_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_ALIGNMENT,
+ DIRTY_BIT_UNPACK_ROW_LENGTH,
+ DIRTY_BIT_UNPACK_IMAGE_HEIGHT,
+ DIRTY_BIT_UNPACK_SKIP_IMAGES,
+ DIRTY_BIT_UNPACK_SKIP_ROWS,
+ DIRTY_BIT_UNPACK_SKIP_PIXELS,
+ DIRTY_BIT_UNPACK_BUFFER_BINDING,
+ DIRTY_BIT_PACK_ALIGNMENT,
+ DIRTY_BIT_PACK_REVERSE_ROW_ORDER,
+ DIRTY_BIT_PACK_ROW_LENGTH,
+ DIRTY_BIT_PACK_SKIP_ROWS,
+ DIRTY_BIT_PACK_SKIP_PIXELS,
+ DIRTY_BIT_PACK_BUFFER_BINDING,
+ DIRTY_BIT_DITHER_ENABLED,
+ DIRTY_BIT_GENERATE_MIPMAP_HINT,
+ DIRTY_BIT_SHADER_DERIVATIVE_HINT,
+ DIRTY_BIT_READ_FRAMEBUFFER_BINDING,
+ DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING,
+ DIRTY_BIT_RENDERBUFFER_BINDING,
+ DIRTY_BIT_VERTEX_ARRAY_BINDING,
+ DIRTY_BIT_PROGRAM_BINDING,
+ DIRTY_BIT_MULTISAMPLING,
+ DIRTY_BIT_SAMPLE_ALPHA_TO_ONE,
+ DIRTY_BIT_COVERAGE_MODULATION, // CHROMIUM_framebuffer_mixed_samples
+ DIRTY_BIT_PATH_RENDERING_MATRIX_MV, // CHROMIUM_path_rendering path model view matrix
+ DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ, // CHROMIUM_path_rendering path projection matrix
+ DIRTY_BIT_PATH_RENDERING_STENCIL_STATE,
+ DIRTY_BIT_FRAMEBUFFER_SRGB, // GL_EXT_sRGB_write_control
+ DIRTY_BIT_CURRENT_VALUE_0,
+ DIRTY_BIT_CURRENT_VALUE_MAX = DIRTY_BIT_CURRENT_VALUE_0 + MAX_VERTEX_ATTRIBS,
+ DIRTY_BIT_INVALID = DIRTY_BIT_CURRENT_VALUE_MAX,
+ DIRTY_BIT_MAX = DIRTY_BIT_INVALID,
+ };
+
+ // TODO(jmadill): Consider storing dirty objects in a list instead of by binding.
+ enum DirtyObjectType
+ {
+ DIRTY_OBJECT_READ_FRAMEBUFFER,
+ DIRTY_OBJECT_DRAW_FRAMEBUFFER,
+ DIRTY_OBJECT_VERTEX_ARRAY,
+ DIRTY_OBJECT_PROGRAM,
+ DIRTY_OBJECT_UNKNOWN,
+ DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN,
+ };
+
+ typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
+ const DirtyBits &getDirtyBits() const { return mDirtyBits; }
+ void clearDirtyBits() { mDirtyBits.reset(); }
+ void clearDirtyBits(const DirtyBits &bitset) { mDirtyBits &= ~bitset; }
+ void setAllDirtyBits() { mDirtyBits.set(); }
+
+ typedef std::bitset<DIRTY_OBJECT_MAX> DirtyObjects;
+ void clearDirtyObjects() { mDirtyObjects.reset(); }
+ void setAllDirtyObjects() { mDirtyObjects.set(); }
+ void syncDirtyObjects();
+ void syncDirtyObjects(const DirtyObjects &bitset);
+ void syncDirtyObject(GLenum target);
+ void setObjectDirty(GLenum target);
+
+ private:
+ // Cached values from Context's caps
+ GLuint mMaxDrawBuffers;
+ GLuint mMaxCombinedTextureImageUnits;
+
+ ColorF mColorClearValue;
+ GLclampf mDepthClearValue;
+ int mStencilClearValue;
+
+ RasterizerState mRasterizer;
+ bool mScissorTest;
+ Rectangle mScissor;
+
+ BlendState mBlend;
+ ColorF mBlendColor;
+ bool mSampleCoverage;
+ GLclampf mSampleCoverageValue;
+ bool mSampleCoverageInvert;
+
+ DepthStencilState mDepthStencil;
+ GLint mStencilRef;
+ GLint mStencilBackRef;
+
+ GLfloat mLineWidth;
+
+ GLenum mGenerateMipmapHint;
+ GLenum mFragmentShaderDerivativeHint;
+
+ bool mBindGeneratesResource;
+
+ Rectangle mViewport;
+ float mNearZ;
+ float mFarZ;
+
+ BindingPointer<Buffer> mArrayBuffer;
+ Framebuffer *mReadFramebuffer;
+ Framebuffer *mDrawFramebuffer;
+ BindingPointer<Renderbuffer> mRenderbuffer;
+ Program *mProgram;
+
+ typedef std::vector<VertexAttribCurrentValueData> VertexAttribVector;
+ VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib
+ VertexArray *mVertexArray;
+
+ // Texture and sampler bindings
+ size_t mActiveSampler; // Active texture unit selector - GL_TEXTURE0
+
+ typedef std::vector<BindingPointer<Texture>> TextureBindingVector;
+ typedef std::map<GLenum, TextureBindingVector> TextureBindingMap;
+ TextureBindingMap mSamplerTextures;
+
+ typedef std::vector<BindingPointer<Sampler>> SamplerBindingVector;
+ SamplerBindingVector mSamplers;
+
+ typedef std::map<GLenum, BindingPointer<Query>> ActiveQueryMap;
+ ActiveQueryMap mActiveQueries;
+
+ BindingPointer<Buffer> mGenericUniformBuffer;
+ typedef std::vector<OffsetBindingPointer<Buffer>> BufferVector;
+ BufferVector mUniformBuffers;
+
+ BindingPointer<TransformFeedback> mTransformFeedback;
+
+ BindingPointer<Buffer> mCopyReadBuffer;
+ BindingPointer<Buffer> mCopyWriteBuffer;
+
+ PixelUnpackState mUnpack;
+ PixelPackState mPack;
+
+ bool mPrimitiveRestart;
+
+ Debug mDebug;
+
+ bool mMultiSampling;
+ bool mSampleAlphaToOne;
+
+ GLenum mCoverageModulation;
+
+ // CHROMIUM_path_rendering
+ GLfloat mPathMatrixMV[16];
+ GLfloat mPathMatrixProj[16];
+ GLenum mPathStencilFunc;
+ GLint mPathStencilRef;
+ GLuint mPathStencilMask;
+
+ // GL_EXT_sRGB_write_control
+ bool mFramebufferSRGB;
+
+ DirtyBits mDirtyBits;
+ DirtyObjects mDirtyObjects;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_STATE_H_
diff --git a/gfx/angle/src/libANGLE/Stream.cpp b/gfx/angle/src/libANGLE/Stream.cpp
new file mode 100755
index 000000000..8cf078c21
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Stream.cpp
@@ -0,0 +1,271 @@
+//
+// Copyright (c) 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 <platform/Platform.h>
+#include <EGL/eglext.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)
+ : 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::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->getGLState();
+ EGLenum bufferType = attributes.getAsInt(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
+ if (bufferType == EGL_RGB_BUFFER)
+ {
+ mPlanes[0].texture = glState.getTargetTexture(GL_TEXTURE_EXTERNAL_OES);
+ 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_TEXTURE_EXTERNAL_OES);
+ 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 Error(EGL_SUCCESS);
+}
+
+Error Stream::createProducerD3D11TextureNV12(const AttributeMap &attributes)
+{
+ ASSERT(mState == EGL_STREAM_STATE_CONNECTING_KHR);
+ ASSERT(mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::NoProducer);
+ ASSERT(mPlaneCount == 2);
+
+ mProducerImplementation = mDisplay->getImplementation()->createStreamProducerD3DTextureNV12(
+ mConsumerType, attributes);
+ mProducerType = ProducerType::D3D11TextureNV12;
+ mState = EGL_STREAM_STATE_EMPTY_KHR;
+
+ return Error(EGL_SUCCESS);
+}
+
+// Called when the consumer of this stream starts using the stream
+Error Stream::consumerAcquire()
+{
+ 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::D3D11TextureNV12);
+
+ 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)
+ {
+ mPlanes[i].texture->acquireImageFromStream(
+ mProducerImplementation->getGLFrameDescription(i));
+ }
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error Stream::consumerRelease()
+{
+ 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::D3D11TextureNV12);
+
+ // Release the images
+ for (int i = 0; i < mPlaneCount; i++)
+ {
+ if (mPlanes[i].texture != nullptr)
+ {
+ mPlanes[i].texture->releaseImageFromStream();
+ }
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+bool Stream::isConsumerBoundToContext(const gl::Context *context) const
+{
+ ASSERT(context != nullptr);
+ return (context == mContext);
+}
+
+Error Stream::validateD3D11NV12Texture(void *texture) const
+{
+ ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+ mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
+ ASSERT(mProducerImplementation != nullptr);
+
+ return mProducerImplementation->validateD3DNV12Texture(texture);
+}
+
+Error Stream::postD3D11NV12Texture(void *texture, const AttributeMap &attributes)
+{
+ ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+ mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
+
+ mProducerImplementation->postD3DNV12Texture(texture, attributes);
+ mProducerFrame++;
+
+ mState = EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR;
+
+ return Error(EGL_SUCCESS);
+}
+
+// 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/src/libANGLE/Stream.h b/gfx/angle/src/libANGLE/Stream.h
new file mode 100755
index 000000000..799e32690
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Stream.h
@@ -0,0 +1,142 @@
+//
+// Copyright (c) 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"
+
+namespace rx
+{
+class StreamProducerImpl;
+}
+
+namespace gl
+{
+class Context;
+class Texture;
+}
+
+namespace egl
+{
+class Display;
+class Error;
+
+class Stream final : angle::NonCopyable
+{
+ public:
+ Stream(Display *display, const AttributeMap &attribs);
+ ~Stream();
+
+ enum class ConsumerType
+ {
+ NoConsumer,
+ GLTextureRGB,
+ GLTextureYUV,
+ };
+
+ enum class ProducerType
+ {
+ NoProducer,
+ D3D11TextureNV12,
+ };
+
+ // 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 createProducerD3D11TextureNV12(const AttributeMap &attributes);
+
+ // Consumer methods
+ Error consumerAcquire();
+ Error consumerRelease();
+
+ // 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 validateD3D11NV12Texture(void *texture) const;
+ Error postD3D11NV12Texture(void *texture, const AttributeMap &attributes);
+
+ private:
+ // 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/src/libANGLE/Surface.cpp b/gfx/angle/src/libANGLE/Surface.cpp
new file mode 100755
index 000000000..43e71df31
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Surface.cpp
@@ -0,0 +1,336 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 <iostream>
+
+#include "libANGLE/Config.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+
+namespace egl
+{
+
+SurfaceState::SurfaceState() : defaultFramebuffer(nullptr)
+{
+}
+
+Surface::Surface(EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes)
+ : FramebufferAttachmentObject(),
+ mImplementation(nullptr),
+ mCurrentCount(0),
+ mDestroyed(false),
+ mType(surfaceType),
+ mConfig(config),
+ mPostSubBufferRequested(false),
+ mFixedSize(false),
+ mFixedWidth(0),
+ mFixedHeight(0),
+ mTextureFormat(EGL_NO_TEXTURE),
+ mTextureTarget(EGL_NO_TEXTURE),
+ // FIXME: Determine actual pixel aspect ratio
+ mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
+ mRenderBuffer(EGL_BACK_BUFFER),
+ mSwapBehavior(EGL_NONE),
+ mOrientation(0),
+ mTexture(),
+ mBackFormat(config->renderTargetFormat),
+ mDSFormat(config->depthStencilFormat)
+{
+ mPostSubBufferRequested = (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
+ mFlexibleSurfaceCompatibilityRequested =
+ (attributes.get(EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_FALSE) == EGL_TRUE);
+
+ mDirectComposition = (attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
+
+ 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 = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE));
+ mTextureTarget = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
+ }
+
+ mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
+}
+
+Surface::~Surface()
+{
+ if (mTexture.get())
+ {
+ if (mImplementation)
+ {
+ mImplementation->releaseTexImage(EGL_BACK_BUFFER);
+ }
+ mTexture->releaseTexImageFromSurface();
+ mTexture.set(nullptr);
+ }
+
+ SafeDelete(mState.defaultFramebuffer);
+ SafeDelete(mImplementation);
+}
+
+Error Surface::initialize()
+{
+ ANGLE_TRY(mImplementation->initialize());
+
+ // Initialized here since impl is nullptr in the constructor.
+ // Must happen after implementation initialize for Android.
+ mSwapBehavior = mImplementation->getSwapBehavior();
+
+ // Must happen after implementation initialize for OSX.
+ mState.defaultFramebuffer = createDefaultFramebuffer();
+ ASSERT(mState.defaultFramebuffer != nullptr);
+
+ return Error(EGL_SUCCESS);
+}
+
+void Surface::setIsCurrent(bool isCurrent)
+{
+ if (isCurrent)
+ {
+ mCurrentCount++;
+ }
+ else
+ {
+ ASSERT(mCurrentCount > 0);
+ mCurrentCount--;
+ if (mCurrentCount == 0 && mDestroyed)
+ {
+ delete this;
+ }
+ }
+}
+
+void Surface::onDestroy()
+{
+ mDestroyed = true;
+ if (mCurrentCount == 0)
+ {
+ delete this;
+ }
+}
+
+EGLint Surface::getType() const
+{
+ return mType;
+}
+
+Error Surface::swap()
+{
+ return mImplementation->swap();
+}
+
+Error Surface::swapWithDamage(EGLint *rects, EGLint n_rects)
+{
+ return mImplementation->swapWithDamage(rects, n_rects);
+}
+
+Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ return mImplementation->postSubBuffer(x, y, width, height);
+}
+
+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);
+}
+
+const Config *Surface::getConfig() const
+{
+ return mConfig;
+}
+
+EGLint Surface::getPixelAspectRatio() const
+{
+ return mPixelAspectRatio;
+}
+
+EGLenum Surface::getRenderBuffer() const
+{
+ return mRenderBuffer;
+}
+
+EGLenum Surface::getSwapBehavior() const
+{
+ return mSwapBehavior;
+}
+
+EGLenum Surface::getTextureFormat() const
+{
+ return mTextureFormat;
+}
+
+EGLenum Surface::getTextureTarget() const
+{
+ return mTextureTarget;
+}
+
+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();
+}
+
+Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ ASSERT(!mTexture.get());
+ ANGLE_TRY(mImplementation->bindTexImage(texture, buffer));
+
+ texture->bindTexImageFromSurface(this);
+ mTexture.set(texture);
+
+ return Error(EGL_SUCCESS);
+}
+
+Error Surface::releaseTexImage(EGLint buffer)
+{
+ ANGLE_TRY(mImplementation->releaseTexImage(buffer));
+
+ ASSERT(mTexture.get());
+ mTexture->releaseTexImageFromSurface();
+ mTexture.set(nullptr);
+
+ return Error(EGL_SUCCESS);
+}
+
+void Surface::releaseTexImageFromTexture()
+{
+ ASSERT(mTexture.get());
+ mTexture.set(nullptr);
+}
+
+gl::Extents Surface::getAttachmentSize(const gl::FramebufferAttachment::Target & /*target*/) const
+{
+ return gl::Extents(getWidth(), getHeight(), 1);
+}
+
+const gl::Format &Surface::getAttachmentFormat(
+ const gl::FramebufferAttachment::Target &target) const
+{
+ return (target.binding() == GL_BACK ? mBackFormat : mDSFormat);
+}
+
+GLsizei Surface::getAttachmentSamples(const gl::FramebufferAttachment::Target &target) const
+{
+ return getConfig()->samples;
+}
+
+GLuint Surface::getId() const
+{
+ UNREACHABLE();
+ return 0;
+}
+
+gl::Framebuffer *Surface::createDefaultFramebuffer()
+{
+ gl::Framebuffer *framebuffer = new gl::Framebuffer(mImplementation);
+
+ GLenum drawBufferState = GL_BACK;
+ framebuffer->setDrawBuffers(1, &drawBufferState);
+ framebuffer->setReadBuffer(GL_BACK);
+
+ framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(),
+ this);
+
+ if (mConfig->depthSize > 0)
+ {
+ framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(),
+ this);
+ }
+
+ if (mConfig->stencilSize > 0)
+ {
+ framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_STENCIL,
+ gl::ImageIndex::MakeInvalid(), this);
+ }
+
+ return framebuffer;
+}
+
+WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
+ const egl::Config *config,
+ EGLNativeWindowType window,
+ const AttributeMap &attribs)
+ : Surface(EGL_WINDOW_BIT, config, attribs)
+{
+ mImplementation = implFactory->createWindowSurface(mState, config, window, attribs);
+}
+
+WindowSurface::~WindowSurface()
+{
+}
+
+PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ const AttributeMap &attribs)
+ : Surface(EGL_PBUFFER_BIT, config, attribs)
+{
+ mImplementation = implFactory->createPbufferSurface(mState, config, attribs);
+}
+
+PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs)
+ : Surface(EGL_PBUFFER_BIT, config, attribs)
+{
+ mImplementation =
+ implFactory->createPbufferFromClientBuffer(mState, config, buftype, clientBuffer, attribs);
+}
+
+PbufferSurface::~PbufferSurface()
+{
+}
+
+PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ NativePixmapType nativePixmap,
+ const AttributeMap &attribs)
+ : Surface(EGL_PIXMAP_BIT, config, attribs)
+{
+ mImplementation = implFactory->createPixmapSurface(mState, config, nativePixmap, attribs);
+}
+
+PixmapSurface::~PixmapSurface()
+{
+}
+
+} // namespace egl
diff --git a/gfx/angle/src/libANGLE/Surface.h b/gfx/angle/src/libANGLE/Surface.h
new file mode 100755
index 000000000..fc6cc6ae7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Surface.h
@@ -0,0 +1,183 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 <EGL/egl.h>
+
+#include "common/angleutils.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 Framebuffer;
+class Texture;
+}
+
+namespace rx
+{
+class EGLImplFactory;
+}
+
+namespace egl
+{
+class AttributeMap;
+class Display;
+struct Config;
+
+struct SurfaceState final : angle::NonCopyable
+{
+ SurfaceState();
+
+ gl::Framebuffer *defaultFramebuffer;
+};
+
+class Surface : public gl::FramebufferAttachmentObject
+{
+ public:
+ virtual ~Surface();
+
+ rx::SurfaceImpl *getImplementation() const { return mImplementation; }
+
+ EGLint getType() const;
+
+ Error initialize();
+ Error swap();
+ Error swapWithDamage(EGLint *rects, EGLint n_rects);
+ Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
+ Error querySurfacePointerANGLE(EGLint attribute, void **value);
+ Error bindTexImage(gl::Texture *texture, EGLint buffer);
+ Error releaseTexImage(EGLint buffer);
+
+ EGLint isPostSubBufferSupported() const;
+
+ void setSwapInterval(EGLint interval);
+ void setIsCurrent(bool isCurrent);
+ void onDestroy();
+
+ const Config *getConfig() const;
+
+ // width and height can change with client window resizing
+ EGLint getWidth() const;
+ EGLint getHeight() const;
+ EGLint getPixelAspectRatio() const;
+ EGLenum getRenderBuffer() const;
+ EGLenum getSwapBehavior() const;
+ EGLenum getTextureFormat() const;
+ EGLenum getTextureTarget() const;
+
+ gl::Texture *getBoundTexture() const { return mTexture.get(); }
+ gl::Framebuffer *getDefaultFramebuffer() { return mState.defaultFramebuffer; }
+
+ EGLint isFixedSize() const;
+
+ // FramebufferAttachmentObject implementation
+ gl::Extents getAttachmentSize(const gl::FramebufferAttachment::Target &target) const override;
+ const gl::Format &getAttachmentFormat(
+ const gl::FramebufferAttachment::Target &target) const override;
+ GLsizei getAttachmentSamples(const gl::FramebufferAttachment::Target &target) const override;
+
+ void onAttach() override {}
+ void onDetach() override {}
+ GLuint getId() const override;
+
+ bool flexibleSurfaceCompatibilityRequested() const
+ {
+ return mFlexibleSurfaceCompatibilityRequested;
+ }
+ EGLint getOrientation() const { return mOrientation; }
+
+ bool directComposition() const { return mDirectComposition; }
+
+ protected:
+ Surface(EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes);
+ rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mImplementation; }
+
+ gl::Framebuffer *createDefaultFramebuffer();
+
+ // ANGLE-only method, used internally
+ friend class gl::Texture;
+ void releaseTexImageFromTexture();
+
+ SurfaceState mState;
+ rx::SurfaceImpl *mImplementation;
+ int mCurrentCount;
+ bool mDestroyed;
+
+ EGLint mType;
+
+ const egl::Config *mConfig;
+
+ bool mPostSubBufferRequested;
+ bool mFlexibleSurfaceCompatibilityRequested;
+
+ bool mFixedSize;
+ size_t mFixedWidth;
+ size_t mFixedHeight;
+
+ bool mDirectComposition;
+
+ EGLenum mTextureFormat;
+ EGLenum mTextureTarget;
+
+ EGLint mPixelAspectRatio; // Display aspect ratio
+ EGLenum mRenderBuffer; // Render buffer
+ EGLenum mSwapBehavior; // Buffer swap behavior
+
+ EGLint mOrientation;
+
+ BindingPointer<gl::Texture> mTexture;
+
+ gl::Format mBackFormat;
+ gl::Format mDSFormat;
+};
+
+class WindowSurface final : public Surface
+{
+ public:
+ WindowSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ EGLNativeWindowType window,
+ const AttributeMap &attribs);
+ ~WindowSurface() override;
+};
+
+class PbufferSurface final : public Surface
+{
+ public:
+ PbufferSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ const AttributeMap &attribs);
+ PbufferSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs);
+ ~PbufferSurface() override;
+};
+
+class PixmapSurface final : public Surface
+{
+ public:
+ PixmapSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ NativePixmapType nativePixmap,
+ const AttributeMap &attribs);
+ ~PixmapSurface() override;
+};
+
+} // namespace egl
+
+#endif // LIBANGLE_SURFACE_H_
diff --git a/gfx/angle/src/libANGLE/Surface_unittest.cpp b/gfx/angle/src/libANGLE/Surface_unittest.cpp
new file mode 100755
index 000000000..7f361eedd
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Surface_unittest.cpp
@@ -0,0 +1,72 @@
+//
+// Copyright (c) 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 "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/FramebufferImpl_mock.h"
+#include "libANGLE/renderer/SurfaceImpl.h"
+#include "tests/angle_unittests_utils.h"
+
+using namespace rx;
+using namespace testing;
+
+namespace
+{
+
+class MockSurfaceImpl : public rx::SurfaceImpl
+{
+ public:
+ MockSurfaceImpl() : SurfaceImpl(mockState) {}
+ virtual ~MockSurfaceImpl() { destroy(); }
+
+ MOCK_METHOD0(initialize, egl::Error());
+ MOCK_METHOD1(createDefaultFramebuffer, rx::FramebufferImpl *(const gl::FramebufferState &data));
+ MOCK_METHOD0(swap, egl::Error());
+ MOCK_METHOD2(swapWithDamage, egl::Error(EGLint *, EGLint));
+ MOCK_METHOD4(postSubBuffer, egl::Error(EGLint, EGLint, EGLint, EGLint));
+ MOCK_METHOD2(querySurfacePointerANGLE, egl::Error(EGLint, void**));
+ MOCK_METHOD2(bindTexImage, egl::Error(gl::Texture*, EGLint));
+ MOCK_METHOD1(releaseTexImage, egl::Error(EGLint));
+ MOCK_METHOD1(setSwapInterval, void(EGLint));
+ MOCK_CONST_METHOD0(getWidth, EGLint());
+ MOCK_CONST_METHOD0(getHeight, EGLint());
+ MOCK_CONST_METHOD0(isPostSubBufferSupported, EGLint(void));
+ MOCK_CONST_METHOD0(getSwapBehavior, EGLint(void));
+ MOCK_METHOD2(getAttachmentRenderTarget, gl::Error(const gl::FramebufferAttachment::Target &, rx::FramebufferAttachmentRenderTarget **));
+
+ MOCK_METHOD0(destroy, void());
+
+ egl::SurfaceState mockState;
+};
+
+TEST(SurfaceTest, DestructionDeletesImpl)
+{
+ NiceMock<MockEGLFactory> factory;
+
+ MockSurfaceImpl *impl = new MockSurfaceImpl;
+ EXPECT_CALL(factory, createWindowSurface(_, _, _, _)).WillOnce(Return(impl));
+
+ egl::Config config;
+ egl::Surface *surface = new egl::WindowSurface(
+ &factory, &config, static_cast<EGLNativeWindowType>(0), egl::AttributeMap());
+
+ EXPECT_CALL(*impl, destroy()).Times(1).RetiresOnSaturation();
+
+ surface->onDestroy();
+
+ // Only needed because the mock is leaked if bugs are present,
+ // which logs an error, but does not cause the test to fail.
+ // Ordinarily mocks are verified when destroyed.
+ Mock::VerifyAndClear(impl);
+}
+
+} // namespace
diff --git a/gfx/angle/src/libANGLE/Texture.cpp b/gfx/angle/src/libANGLE/Texture.cpp
new file mode 100755
index 000000000..edba11bd4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Texture.cpp
@@ -0,0 +1,1153 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/ContextState.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace gl
+{
+
+namespace
+{
+bool IsPointSampled(const gl::SamplerState &samplerState)
+{
+ return (samplerState.magFilter == GL_NEAREST &&
+ (samplerState.minFilter == GL_NEAREST ||
+ samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
+}
+
+size_t GetImageDescIndex(GLenum target, size_t level)
+{
+ return IsCubeMapTextureTarget(target) ? ((level * 6) + CubeMapTextureTargetToLayerIndex(target))
+ : level;
+}
+} // namespace
+
+bool IsMipmapFiltered(const gl::SamplerState &samplerState)
+{
+ switch (samplerState.minFilter)
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ return false;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ return true;
+ default: UNREACHABLE();
+ return false;
+ }
+}
+
+SwizzleState::SwizzleState()
+ : swizzleRed(GL_INVALID_INDEX),
+ swizzleGreen(GL_INVALID_INDEX),
+ swizzleBlue(GL_INVALID_INDEX),
+ swizzleAlpha(GL_INVALID_INDEX)
+{
+}
+
+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(GLenum target)
+ : mTarget(target),
+ mSwizzleState(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA),
+ mSamplerState(SamplerState::CreateDefaultForTarget(target)),
+ mBaseLevel(0),
+ mMaxLevel(1000),
+ mImmutableFormat(false),
+ mImmutableLevels(0),
+ mUsage(GL_NONE),
+ mImageDescs((IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1) *
+ (target == GL_TEXTURE_CUBE_MAP ? 6 : 1)),
+ mCompletenessCache()
+{
+}
+
+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>(gl::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 (mTarget == GL_TEXTURE_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;
+ mCompletenessCache.cacheValid = false;
+ return true;
+ }
+ return false;
+}
+
+void TextureState::setMaxLevel(GLuint maxLevel)
+{
+ if (mMaxLevel != maxLevel)
+ {
+ mMaxLevel = maxLevel;
+ mCompletenessCache.cacheValid = false;
+ }
+}
+
+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool TextureState::isCubeComplete() const
+{
+ ASSERT(mTarget == GL_TEXTURE_CUBE_MAP);
+
+ const ImageDesc &baseImageDesc = getImageDesc(FirstCubeMapTextureTarget, 0);
+ if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height)
+ {
+ return false;
+ }
+
+ for (GLenum face = FirstCubeMapTextureTarget + 1; face <= LastCubeMapTextureTarget; face++)
+ {
+ const ImageDesc &faceImageDesc = getImageDesc(face, 0);
+ if (faceImageDesc.size.width != baseImageDesc.size.width ||
+ faceImageDesc.size.height != baseImageDesc.size.height ||
+ !Format::SameSized(faceImageDesc.format, baseImageDesc.format))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool TextureState::isSamplerComplete(const SamplerState &samplerState,
+ const ContextState &data) const
+{
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+ const TextureCaps &textureCaps = data.getTextureCap(baseImageDesc.format.asSized());
+ if (!mCompletenessCache.cacheValid || mCompletenessCache.samplerState != samplerState ||
+ mCompletenessCache.filterable != textureCaps.filterable ||
+ mCompletenessCache.clientVersion != data.getClientMajorVersion() ||
+ mCompletenessCache.supportsNPOT != data.getExtensions().textureNPOT)
+ {
+ mCompletenessCache.cacheValid = true;
+ mCompletenessCache.samplerState = samplerState;
+ mCompletenessCache.filterable = textureCaps.filterable;
+ mCompletenessCache.clientVersion = data.getClientMajorVersion();
+ mCompletenessCache.supportsNPOT = data.getExtensions().textureNPOT;
+ mCompletenessCache.samplerComplete = computeSamplerCompleteness(samplerState, data);
+ }
+ return mCompletenessCache.samplerComplete;
+}
+
+bool TextureState::computeSamplerCompleteness(const SamplerState &samplerState,
+ const ContextState &data) const
+{
+ if (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 < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS || mImmutableFormat);
+
+ if (mTarget == GL_TEXTURE_CUBE_MAP && baseImageDesc.size.width != baseImageDesc.size.height)
+ {
+ return false;
+ }
+
+ const TextureCaps &textureCaps = data.getTextureCap(baseImageDesc.format.asSized());
+ if (!textureCaps.filterable && !IsPointSampled(samplerState))
+ {
+ return false;
+ }
+ bool npotSupport = data.getExtensions().textureNPOT || data.getClientMajorVersion() >= 3;
+ if (!npotSupport)
+ {
+ if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.width)) ||
+ (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.height)))
+ {
+ return false;
+ }
+ }
+
+ if (IsMipmapFiltered(samplerState))
+ {
+ if (!npotSupport)
+ {
+ if (!gl::isPow2(baseImageDesc.size.width) || !gl::isPow2(baseImageDesc.size.height))
+ {
+ return false;
+ }
+ }
+
+ if (!computeMipmapCompleteness())
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (mTarget == GL_TEXTURE_CUBE_MAP && !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, 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 (mTarget == GL_TEXTURE_EXTERNAL_OES)
+ {
+ if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE)
+ {
+ return false;
+ }
+
+ if (samplerState.minFilter != GL_LINEAR && samplerState.minFilter != GL_NEAREST)
+ {
+ 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 (baseImageDesc.format.info->depthBits > 0 && data.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.compareMode == GL_NONE && baseImageDesc.format.sized)
+ {
+ if ((samplerState.minFilter != GL_NEAREST &&
+ samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
+ samplerState.magFilter != GL_NEAREST)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool TextureState::computeMipmapCompleteness() const
+{
+ const GLuint maxLevel = getMipmapMaxLevel();
+
+ for (GLuint level = getEffectiveBaseLevel(); level <= maxLevel; level++)
+ {
+ if (mTarget == GL_TEXTURE_CUBE_MAP)
+ {
+ for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
+ {
+ if (!computeLevelCompleteness(face, level))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if (!computeLevelCompleteness(mTarget, level))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool TextureState::computeLevelCompleteness(GLenum 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 (mTarget == GL_TEXTURE_3D)
+ {
+ if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> relativeLevel))
+ {
+ return false;
+ }
+ }
+ else if (mTarget == GL_TEXTURE_2D_ARRAY)
+ {
+ if (levelImageDesc.size.depth != baseImageDesc.size.depth)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+GLenum TextureState::getBaseImageTarget() const
+{
+ return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget;
+}
+
+ImageDesc::ImageDesc() : ImageDesc(Extents(0, 0, 0), Format::Invalid())
+{
+}
+
+ImageDesc::ImageDesc(const Extents &size, const Format &format) : size(size), format(format)
+{
+}
+
+const ImageDesc &TextureState::getImageDesc(GLenum target, size_t level) const
+{
+ size_t descIndex = GetImageDescIndex(target, level);
+ ASSERT(descIndex < mImageDescs.size());
+ return mImageDescs[descIndex];
+}
+
+void TextureState::setImageDesc(GLenum target, size_t level, const ImageDesc &desc)
+{
+ size_t descIndex = GetImageDescIndex(target, level);
+ ASSERT(descIndex < mImageDescs.size());
+ mImageDescs[descIndex] = desc;
+ mCompletenessCache.cacheValid = false;
+}
+
+void TextureState::setImageDescChain(GLuint baseLevel,
+ GLuint maxLevel,
+ Extents baseSize,
+ const Format &format)
+{
+ 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),
+ (mTarget == GL_TEXTURE_2D_ARRAY)
+ ? baseSize.depth
+ : std::max<int>(baseSize.depth >> relativeLevel, 1));
+ ImageDesc levelInfo(levelSize, format);
+
+ if (mTarget == GL_TEXTURE_CUBE_MAP)
+ {
+ for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
+ {
+ setImageDesc(face, level, levelInfo);
+ }
+ }
+ else
+ {
+ setImageDesc(mTarget, level, levelInfo);
+ }
+ }
+}
+
+void TextureState::clearImageDesc(GLenum target, size_t level)
+{
+ setImageDesc(target, level, ImageDesc());
+}
+
+void TextureState::clearImageDescs()
+{
+ for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++)
+ {
+ mImageDescs[descIndex] = ImageDesc();
+ }
+ mCompletenessCache.cacheValid = false;
+}
+
+TextureState::SamplerCompletenessCache::SamplerCompletenessCache()
+ : cacheValid(false),
+ samplerState(),
+ filterable(false),
+ clientVersion(0),
+ supportsNPOT(false),
+ samplerComplete(false)
+{
+}
+
+Texture::Texture(rx::GLImplFactory *factory, GLuint id, GLenum target)
+ : egl::ImageSibling(id),
+ mState(target),
+ mTexture(factory->createTexture(mState)),
+ mLabel(),
+ mBoundSurface(nullptr),
+ mBoundStream(nullptr)
+{
+}
+
+Texture::~Texture()
+{
+ if (mBoundSurface)
+ {
+ mBoundSurface->releaseTexImage(EGL_BACK_BUFFER);
+ mBoundSurface = nullptr;
+ }
+ if (mBoundStream)
+ {
+ mBoundStream->releaseTextures();
+ mBoundStream = nullptr;
+ }
+ SafeDelete(mTexture);
+}
+
+void Texture::setLabel(const std::string &label)
+{
+ mLabel = label;
+ mDirtyBits.set(DIRTY_BIT_LABEL);
+}
+
+const std::string &Texture::getLabel() const
+{
+ return mLabel;
+}
+
+GLenum Texture::getTarget() const
+{
+ return mState.mTarget;
+}
+
+void Texture::setSwizzleRed(GLenum swizzleRed)
+{
+ mState.mSwizzleState.swizzleRed = swizzleRed;
+ mDirtyBits.set(DIRTY_BIT_SWIZZLE_RED);
+}
+
+GLenum Texture::getSwizzleRed() const
+{
+ return mState.mSwizzleState.swizzleRed;
+}
+
+void Texture::setSwizzleGreen(GLenum swizzleGreen)
+{
+ mState.mSwizzleState.swizzleGreen = swizzleGreen;
+ mDirtyBits.set(DIRTY_BIT_SWIZZLE_GREEN);
+}
+
+GLenum Texture::getSwizzleGreen() const
+{
+ return mState.mSwizzleState.swizzleGreen;
+}
+
+void Texture::setSwizzleBlue(GLenum swizzleBlue)
+{
+ mState.mSwizzleState.swizzleBlue = swizzleBlue;
+ mDirtyBits.set(DIRTY_BIT_SWIZZLE_BLUE);
+}
+
+GLenum Texture::getSwizzleBlue() const
+{
+ return mState.mSwizzleState.swizzleBlue;
+}
+
+void Texture::setSwizzleAlpha(GLenum swizzleAlpha)
+{
+ mState.mSwizzleState.swizzleAlpha = swizzleAlpha;
+ mDirtyBits.set(DIRTY_BIT_SWIZZLE_ALPHA);
+}
+
+GLenum Texture::getSwizzleAlpha() const
+{
+ return mState.mSwizzleState.swizzleAlpha;
+}
+
+void Texture::setMinFilter(GLenum minFilter)
+{
+ mState.mSamplerState.minFilter = minFilter;
+ mDirtyBits.set(DIRTY_BIT_MIN_FILTER);
+}
+
+GLenum Texture::getMinFilter() const
+{
+ return mState.mSamplerState.minFilter;
+}
+
+void Texture::setMagFilter(GLenum magFilter)
+{
+ mState.mSamplerState.magFilter = magFilter;
+ mDirtyBits.set(DIRTY_BIT_MAG_FILTER);
+}
+
+GLenum Texture::getMagFilter() const
+{
+ return mState.mSamplerState.magFilter;
+}
+
+void Texture::setWrapS(GLenum wrapS)
+{
+ mState.mSamplerState.wrapS = wrapS;
+ mDirtyBits.set(DIRTY_BIT_WRAP_S);
+}
+
+GLenum Texture::getWrapS() const
+{
+ return mState.mSamplerState.wrapS;
+}
+
+void Texture::setWrapT(GLenum wrapT)
+{
+ mState.mSamplerState.wrapT = wrapT;
+ mDirtyBits.set(DIRTY_BIT_WRAP_T);
+}
+
+GLenum Texture::getWrapT() const
+{
+ return mState.mSamplerState.wrapT;
+}
+
+void Texture::setWrapR(GLenum wrapR)
+{
+ mState.mSamplerState.wrapR = wrapR;
+ mDirtyBits.set(DIRTY_BIT_WRAP_R);
+}
+
+GLenum Texture::getWrapR() const
+{
+ return mState.mSamplerState.wrapR;
+}
+
+void Texture::setMaxAnisotropy(float maxAnisotropy)
+{
+ mState.mSamplerState.maxAnisotropy = maxAnisotropy;
+ mDirtyBits.set(DIRTY_BIT_MAX_ANISOTROPY);
+}
+
+float Texture::getMaxAnisotropy() const
+{
+ return mState.mSamplerState.maxAnisotropy;
+}
+
+void Texture::setMinLod(GLfloat minLod)
+{
+ mState.mSamplerState.minLod = minLod;
+ mDirtyBits.set(DIRTY_BIT_MIN_LOD);
+}
+
+GLfloat Texture::getMinLod() const
+{
+ return mState.mSamplerState.minLod;
+}
+
+void Texture::setMaxLod(GLfloat maxLod)
+{
+ mState.mSamplerState.maxLod = maxLod;
+ mDirtyBits.set(DIRTY_BIT_MAX_LOD);
+}
+
+GLfloat Texture::getMaxLod() const
+{
+ return mState.mSamplerState.maxLod;
+}
+
+void Texture::setCompareMode(GLenum compareMode)
+{
+ mState.mSamplerState.compareMode = compareMode;
+ mDirtyBits.set(DIRTY_BIT_COMPARE_MODE);
+}
+
+GLenum Texture::getCompareMode() const
+{
+ return mState.mSamplerState.compareMode;
+}
+
+void Texture::setCompareFunc(GLenum compareFunc)
+{
+ mState.mSamplerState.compareFunc = compareFunc;
+ mDirtyBits.set(DIRTY_BIT_COMPARE_FUNC);
+}
+
+GLenum Texture::getCompareFunc() const
+{
+ return mState.mSamplerState.compareFunc;
+}
+
+void Texture::setSRGBDecode(GLenum sRGBDecode)
+{
+ mState.mSamplerState.sRGBDecode = sRGBDecode;
+ mDirtyBits.set(DIRTY_BIT_SRGB_DECODE);
+}
+
+GLenum Texture::getSRGBDecode() const
+{
+ return mState.mSamplerState.sRGBDecode;
+}
+
+const SamplerState &Texture::getSamplerState() const
+{
+ return mState.mSamplerState;
+}
+
+void Texture::setBaseLevel(GLuint baseLevel)
+{
+ if (mState.setBaseLevel(baseLevel))
+ {
+ mTexture->setBaseLevel(mState.getEffectiveBaseLevel());
+ mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
+ }
+}
+
+GLuint Texture::getBaseLevel() const
+{
+ return mState.mBaseLevel;
+}
+
+void Texture::setMaxLevel(GLuint maxLevel)
+{
+ mState.setMaxLevel(maxLevel);
+ mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
+}
+
+GLuint Texture::getMaxLevel() const
+{
+ return mState.mMaxLevel;
+}
+
+bool Texture::getImmutableFormat() const
+{
+ return mState.mImmutableFormat;
+}
+
+GLuint Texture::getImmutableLevels() const
+{
+ return mState.mImmutableLevels;
+}
+
+void Texture::setUsage(GLenum usage)
+{
+ mState.mUsage = usage;
+ mDirtyBits.set(DIRTY_BIT_USAGE);
+}
+
+GLenum Texture::getUsage() const
+{
+ return mState.mUsage;
+}
+
+const TextureState &Texture::getTextureState() const
+{
+ return mState;
+}
+
+size_t Texture::getWidth(GLenum target, size_t level) const
+{
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return mState.getImageDesc(target, level).size.width;
+}
+
+size_t Texture::getHeight(GLenum target, size_t level) const
+{
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return mState.getImageDesc(target, level).size.height;
+}
+
+size_t Texture::getDepth(GLenum target, size_t level) const
+{
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return mState.getImageDesc(target, level).size.depth;
+}
+
+const Format &Texture::getFormat(GLenum target, size_t level) const
+{
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return mState.getImageDesc(target, level).format;
+}
+
+bool Texture::isMipmapComplete() const
+{
+ return mState.computeMipmapCompleteness();
+}
+
+egl::Surface *Texture::getBoundSurface() const
+{
+ return mBoundSurface;
+}
+
+egl::Stream *Texture::getBoundStream() const
+{
+ return mBoundStream;
+}
+
+Error Texture::setImage(const PixelUnpackState &unpackState,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const Extents &size,
+ GLenum format,
+ GLenum type,
+ const uint8_t *pixels)
+{
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ releaseTexImageInternal();
+ orphanImages();
+
+ ANGLE_TRY(
+ mTexture->setImage(target, level, internalFormat, size, format, type, unpackState, pixels));
+
+ mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat, format, type)));
+ mDirtyChannel.signal();
+
+ return NoError();
+}
+
+Error Texture::setSubImage(const PixelUnpackState &unpackState,
+ GLenum target,
+ size_t level,
+ const Box &area,
+ GLenum format,
+ GLenum type,
+ const uint8_t *pixels)
+{
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return mTexture->setSubImage(target, level, area, format, type, unpackState, pixels);
+}
+
+Error Texture::setCompressedImage(const PixelUnpackState &unpackState,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const Extents &size,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ releaseTexImageInternal();
+ orphanImages();
+
+ ANGLE_TRY(mTexture->setCompressedImage(target, level, internalFormat, size, unpackState,
+ imageSize, pixels));
+
+ mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat)));
+ mDirtyChannel.signal();
+
+ return NoError();
+}
+
+Error Texture::setCompressedSubImage(const PixelUnpackState &unpackState,
+ GLenum target,
+ size_t level,
+ const Box &area,
+ GLenum format,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+ return mTexture->setCompressedSubImage(target, level, area, format, unpackState, imageSize,
+ pixels);
+}
+
+Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat,
+ const Framebuffer *source)
+{
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ releaseTexImageInternal();
+ orphanImages();
+
+ ANGLE_TRY(mTexture->copyImage(target, level, sourceArea, internalFormat, source));
+
+ const GLenum sizedFormat = GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE);
+ mState.setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
+ Format(sizedFormat)));
+ mDirtyChannel.signal();
+
+ return NoError();
+}
+
+Error Texture::copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea,
+ const Framebuffer *source)
+{
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+ return mTexture->copySubImage(target, level, destOffset, sourceArea, source);
+}
+
+Error Texture::copyTexture(GLenum internalFormat,
+ GLenum type,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const Texture *source)
+{
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ releaseTexImageInternal();
+ orphanImages();
+
+ ANGLE_TRY(mTexture->copyTexture(internalFormat, type, unpackFlipY, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha, source));
+
+ const auto &sourceDesc = source->mState.getImageDesc(source->getTarget(), 0);
+ const GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
+ mState.setImageDesc(getTarget(), 0, ImageDesc(sourceDesc.size, Format(sizedFormat)));
+ mDirtyChannel.signal();
+
+ return NoError();
+}
+
+Error Texture::copySubTexture(const Offset &destOffset,
+ const Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const Texture *source)
+{
+ return mTexture->copySubTexture(destOffset, sourceArea, unpackFlipY, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha, source);
+}
+
+Error Texture::copyCompressedTexture(const Texture *source)
+{
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ releaseTexImageInternal();
+ orphanImages();
+
+ ANGLE_TRY(mTexture->copyCompressedTexture(source));
+
+ ASSERT(source->getTarget() != GL_TEXTURE_CUBE_MAP && getTarget() != GL_TEXTURE_CUBE_MAP);
+ const auto &sourceDesc = source->mState.getImageDesc(source->getTarget(), 0);
+ mState.setImageDesc(getTarget(), 0, sourceDesc);
+
+ return NoError();
+}
+
+Error Texture::setStorage(GLenum target, GLsizei levels, GLenum internalFormat, const Extents &size)
+{
+ ASSERT(target == mState.mTarget);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ releaseTexImageInternal();
+ orphanImages();
+
+ ANGLE_TRY(mTexture->setStorage(target, levels, internalFormat, size));
+
+ mState.mImmutableFormat = true;
+ mState.mImmutableLevels = static_cast<GLuint>(levels);
+ mState.clearImageDescs();
+ mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat));
+
+ // 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);
+
+ mDirtyChannel.signal();
+
+ return NoError();
+}
+
+Error Texture::generateMipmap()
+{
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ releaseTexImageInternal();
+
+ // EGL_KHR_gl_image states that images are only orphaned when generating mipmaps if the texture
+ // is not mip complete.
+ if (!isMipmapComplete())
+ {
+ orphanImages();
+ }
+
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+
+ if (maxLevel > baseLevel)
+ {
+ syncImplState();
+ ANGLE_TRY(mTexture->generateMipmap());
+
+ const ImageDesc &baseImageInfo =
+ mState.getImageDesc(mState.getBaseImageTarget(), baseLevel);
+ mState.setImageDescChain(baseLevel, maxLevel, baseImageInfo.size, baseImageInfo.format);
+ }
+
+ mDirtyChannel.signal();
+
+ return NoError();
+}
+
+void Texture::bindTexImageFromSurface(egl::Surface *surface)
+{
+ ASSERT(surface);
+
+ if (mBoundSurface)
+ {
+ releaseTexImageFromSurface();
+ }
+
+ mTexture->bindTexImage(surface);
+ mBoundSurface = surface;
+
+ // Set the image info to the size and format of the surface
+ ASSERT(mState.mTarget == GL_TEXTURE_2D);
+ Extents size(surface->getWidth(), surface->getHeight(), 1);
+ ImageDesc desc(size, Format(surface->getConfig()->renderTargetFormat));
+ mState.setImageDesc(mState.mTarget, 0, desc);
+ mDirtyChannel.signal();
+}
+
+void Texture::releaseTexImageFromSurface()
+{
+ ASSERT(mBoundSurface);
+ mBoundSurface = nullptr;
+ mTexture->releaseTexImage();
+
+ // Erase the image info for level 0
+ ASSERT(mState.mTarget == GL_TEXTURE_2D);
+ mState.clearImageDesc(mState.mTarget, 0);
+ mDirtyChannel.signal();
+}
+
+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.mTarget == GL_TEXTURE_EXTERNAL_OES);
+}
+
+void Texture::releaseStream()
+{
+ ASSERT(mBoundStream);
+ mBoundStream = nullptr;
+}
+
+void Texture::acquireImageFromStream(const egl::Stream::GLTextureDescription &desc)
+{
+ ASSERT(mBoundStream != nullptr);
+ mTexture->setImageExternal(mState.mTarget, mBoundStream, desc);
+
+ Extents size(desc.width, desc.height, 1);
+ mState.setImageDesc(mState.mTarget, 0, ImageDesc(size, Format(desc.internalFormat)));
+ mDirtyChannel.signal();
+}
+
+void Texture::releaseImageFromStream()
+{
+ ASSERT(mBoundStream != nullptr);
+ mTexture->setImageExternal(mState.mTarget, nullptr, egl::Stream::GLTextureDescription());
+
+ // Set to incomplete
+ mState.clearImageDesc(mState.mTarget, 0);
+ mDirtyChannel.signal();
+}
+
+void Texture::releaseTexImageInternal()
+{
+ if (mBoundSurface)
+ {
+ // Notify the surface
+ mBoundSurface->releaseTexImageFromTexture();
+
+ // Then, call the same method as from the surface
+ releaseTexImageFromSurface();
+ }
+}
+
+Error Texture::setEGLImageTarget(GLenum target, egl::Image *imageTarget)
+{
+ ASSERT(target == mState.mTarget);
+ ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ releaseTexImageInternal();
+ orphanImages();
+
+ ANGLE_TRY(mTexture->setEGLImageTarget(target, imageTarget));
+
+ setTargetImage(imageTarget);
+
+ Extents size(static_cast<int>(imageTarget->getWidth()),
+ static_cast<int>(imageTarget->getHeight()), 1);
+
+ mState.clearImageDescs();
+ mState.setImageDesc(target, 0, ImageDesc(size, imageTarget->getFormat()));
+ mDirtyChannel.signal();
+
+ return NoError();
+}
+
+Extents Texture::getAttachmentSize(const gl::FramebufferAttachment::Target &target) const
+{
+ return mState.getImageDesc(target.textureIndex().type, target.textureIndex().mipIndex).size;
+}
+
+const Format &Texture::getAttachmentFormat(const gl::FramebufferAttachment::Target &target) const
+{
+ return getFormat(target.textureIndex().type, target.textureIndex().mipIndex);
+}
+
+GLsizei Texture::getAttachmentSamples(const gl::FramebufferAttachment::Target &/*target*/) const
+{
+ // Multisample textures not currently supported
+ return 0;
+}
+
+void Texture::onAttach()
+{
+ addRef();
+}
+
+void Texture::onDetach()
+{
+ release();
+}
+
+GLuint Texture::getId() const
+{
+ return id();
+}
+
+void Texture::syncImplState()
+{
+ mTexture->syncState(mDirtyBits);
+ mDirtyBits.reset();
+}
+
+rx::FramebufferAttachmentObjectImpl *Texture::getAttachmentImpl() const
+{
+ return mTexture;
+}
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/Texture.h b/gfx/angle/src/libANGLE/Texture.h
new file mode 100755
index 000000000..583a69a7b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Texture.h
@@ -0,0 +1,398 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 <vector>
+#include <map>
+
+#include "angle_gl.h"
+#include "common/debug.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+
+namespace egl
+{
+class Surface;
+class Stream;
+}
+
+namespace rx
+{
+class GLImplFactory;
+class TextureImpl;
+class TextureGL;
+}
+
+namespace gl
+{
+class ContextState;
+class Framebuffer;
+class Texture;
+
+bool IsMipmapFiltered(const SamplerState &samplerState);
+
+struct ImageDesc final
+{
+ ImageDesc();
+ ImageDesc(const Extents &size, const Format &format);
+
+ ImageDesc(const ImageDesc &other) = default;
+ ImageDesc &operator=(const ImageDesc &other) = default;
+
+ Extents size;
+ Format format;
+};
+
+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.
+struct TextureState final : public angle::NonCopyable
+{
+ TextureState(GLenum target);
+
+ 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);
+ void setMaxLevel(GLuint maxLevel);
+
+ bool isCubeComplete() const;
+ bool isSamplerComplete(const SamplerState &samplerState, const ContextState &data) const;
+
+ const ImageDesc &getImageDesc(GLenum target, size_t level) const;
+
+ GLenum getTarget() const { return mTarget; }
+ const SwizzleState &getSwizzleState() const { return mSwizzleState; }
+ const SamplerState &getSamplerState() const { return mSamplerState; }
+ GLenum getUsage() const { return mUsage; }
+
+ private:
+ // Texture needs access to the ImageDesc functions.
+ friend class Texture;
+ // TODO(jmadill): Remove TextureGL from friends.
+ friend class rx::TextureGL;
+ friend bool operator==(const TextureState &a, const TextureState &b);
+
+ bool computeSamplerCompleteness(const SamplerState &samplerState,
+ const ContextState &data) const;
+ bool computeMipmapCompleteness() const;
+ bool computeLevelCompleteness(GLenum target, size_t level) const;
+
+ GLenum getBaseImageTarget() const;
+
+ void setImageDesc(GLenum target, size_t level, const ImageDesc &desc);
+ void setImageDescChain(GLuint baselevel,
+ GLuint maxLevel,
+ Extents baseSize,
+ const Format &format);
+ void clearImageDesc(GLenum target, size_t level);
+ void clearImageDescs();
+
+ const GLenum mTarget;
+
+ SwizzleState mSwizzleState;
+
+ SamplerState mSamplerState;
+
+ GLuint mBaseLevel;
+ GLuint mMaxLevel;
+
+ bool mImmutableFormat;
+ GLuint mImmutableLevels;
+
+ // From GL_ANGLE_texture_usage
+ GLenum mUsage;
+
+ std::vector<ImageDesc> mImageDescs;
+
+ struct SamplerCompletenessCache
+ {
+ SamplerCompletenessCache();
+
+ bool cacheValid;
+
+ // All values that affect sampler completeness that are not stored within
+ // the texture itself
+ SamplerState samplerState;
+ bool filterable;
+ GLint clientVersion;
+ bool supportsNPOT;
+
+ // Result of the sampler completeness with the above parameters
+ bool samplerComplete;
+ };
+ mutable SamplerCompletenessCache mCompletenessCache;
+};
+
+bool operator==(const TextureState &a, const TextureState &b);
+bool operator!=(const TextureState &a, const TextureState &b);
+
+class Texture final : public egl::ImageSibling,
+ public FramebufferAttachmentObject,
+ public LabeledObject
+{
+ public:
+ Texture(rx::GLImplFactory *factory, GLuint id, GLenum target);
+ ~Texture() override;
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ GLenum getTarget() const;
+
+ void setSwizzleRed(GLenum swizzleRed);
+ GLenum getSwizzleRed() const;
+
+ void setSwizzleGreen(GLenum swizzleGreen);
+ GLenum getSwizzleGreen() const;
+
+ void setSwizzleBlue(GLenum swizzleBlue);
+ GLenum getSwizzleBlue() const;
+
+ void setSwizzleAlpha(GLenum swizzleAlpha);
+ GLenum getSwizzleAlpha() const;
+
+ void setMinFilter(GLenum minFilter);
+ GLenum getMinFilter() const;
+
+ void setMagFilter(GLenum magFilter);
+ GLenum getMagFilter() const;
+
+ void setWrapS(GLenum wrapS);
+ GLenum getWrapS() const;
+
+ void setWrapT(GLenum wrapT);
+ GLenum getWrapT() const;
+
+ void setWrapR(GLenum wrapR);
+ GLenum getWrapR() const;
+
+ void setMaxAnisotropy(float maxAnisotropy);
+ float getMaxAnisotropy() const;
+
+ void setMinLod(GLfloat minLod);
+ GLfloat getMinLod() const;
+
+ void setMaxLod(GLfloat maxLod);
+ GLfloat getMaxLod() const;
+
+ void setCompareMode(GLenum compareMode);
+ GLenum getCompareMode() const;
+
+ void setCompareFunc(GLenum compareFunc);
+ GLenum getCompareFunc() const;
+
+ void setSRGBDecode(GLenum sRGBDecode);
+ GLenum getSRGBDecode() const;
+
+ const SamplerState &getSamplerState() const;
+
+ void setBaseLevel(GLuint baseLevel);
+ GLuint getBaseLevel() const;
+
+ void setMaxLevel(GLuint maxLevel);
+ GLuint getMaxLevel() const;
+
+ bool getImmutableFormat() const;
+
+ GLuint getImmutableLevels() const;
+
+ void setUsage(GLenum usage);
+ GLenum getUsage() const;
+
+ const TextureState &getTextureState() const;
+
+ size_t getWidth(GLenum target, size_t level) const;
+ size_t getHeight(GLenum target, size_t level) const;
+ size_t getDepth(GLenum target, size_t level) const;
+ const Format &getFormat(GLenum target, size_t level) const;
+
+ bool isMipmapComplete() const;
+
+ Error setImage(const PixelUnpackState &unpackState,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const Extents &size,
+ GLenum format,
+ GLenum type,
+ const uint8_t *pixels);
+ Error setSubImage(const PixelUnpackState &unpackState,
+ GLenum target,
+ size_t level,
+ const Box &area,
+ GLenum format,
+ GLenum type,
+ const uint8_t *pixels);
+
+ Error setCompressedImage(const PixelUnpackState &unpackState,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const Extents &size,
+ size_t imageSize,
+ const uint8_t *pixels);
+ Error setCompressedSubImage(const PixelUnpackState &unpackState,
+ GLenum target,
+ size_t level,
+ const Box &area,
+ GLenum format,
+ size_t imageSize,
+ const uint8_t *pixels);
+
+ Error copyImage(GLenum target,
+ size_t level,
+ const Rectangle &sourceArea,
+ GLenum internalFormat,
+ const Framebuffer *source);
+ Error copySubImage(GLenum target,
+ size_t level,
+ const Offset &destOffset,
+ const Rectangle &sourceArea,
+ const Framebuffer *source);
+
+ Error copyTexture(GLenum internalFormat,
+ GLenum type,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const Texture *source);
+ Error copySubTexture(const Offset &destOffset,
+ const Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const Texture *source);
+ Error copyCompressedTexture(const Texture *source);
+
+ Error setStorage(GLenum target, GLsizei levels, GLenum internalFormat, const Extents &size);
+
+ Error setEGLImageTarget(GLenum target, egl::Image *imageTarget);
+
+ Error generateMipmap();
+
+ egl::Surface *getBoundSurface() const;
+ egl::Stream *getBoundStream() const;
+
+ rx::TextureImpl *getImplementation() const { return mTexture; }
+
+ // FramebufferAttachmentObject implementation
+ Extents getAttachmentSize(const FramebufferAttachment::Target &target) const override;
+ const Format &getAttachmentFormat(const FramebufferAttachment::Target &target) const override;
+ GLsizei getAttachmentSamples(const FramebufferAttachment::Target &target) const override;
+
+ void onAttach() override;
+ void onDetach() override;
+ GLuint getId() const override;
+
+ 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,
+
+ // 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,
+
+ // Misc
+ DIRTY_BIT_LABEL,
+ DIRTY_BIT_USAGE,
+
+ DIRTY_BIT_COUNT,
+ };
+ using DirtyBits = std::bitset<DIRTY_BIT_COUNT>;
+
+ void syncImplState();
+ bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
+ private:
+ rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
+
+ // ANGLE-only method, used internally
+ friend class egl::Surface;
+ void bindTexImageFromSurface(egl::Surface *surface);
+ void releaseTexImageFromSurface();
+
+ // ANGLE-only methods, used internally
+ friend class egl::Stream;
+ void bindStream(egl::Stream *stream);
+ void releaseStream();
+ void acquireImageFromStream(const egl::Stream::GLTextureDescription &desc);
+ void releaseImageFromStream();
+
+ TextureState mState;
+ DirtyBits mDirtyBits;
+ rx::TextureImpl *mTexture;
+
+ std::string mLabel;
+
+ void releaseTexImageInternal();
+
+ egl::Surface *mBoundSurface;
+ egl::Stream *mBoundStream;
+};
+
+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);
+}
+}
+
+#endif // LIBANGLE_TEXTURE_H_
diff --git a/gfx/angle/src/libANGLE/Thread.cpp b/gfx/angle/src/libANGLE/Thread.cpp
new file mode 100644
index 000000000..1abf449ce
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Thread.cpp
@@ -0,0 +1,88 @@
+//
+// Copyright(c) 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/Error.h"
+
+namespace egl
+{
+Thread::Thread()
+ : mError(EGL_SUCCESS),
+ mAPI(EGL_OPENGL_ES_API),
+ mDisplay(static_cast<egl::Display *>(EGL_NO_DISPLAY)),
+ mDrawSurface(static_cast<egl::Surface *>(EGL_NO_SURFACE)),
+ mReadSurface(static_cast<egl::Surface *>(EGL_NO_SURFACE)),
+ mContext(static_cast<gl::Context *>(EGL_NO_CONTEXT))
+{
+}
+
+void Thread::setError(const Error &error)
+{
+ mError = error.getCode();
+}
+
+EGLint Thread::getError() const
+{
+ return mError;
+}
+
+void Thread::setAPI(EGLenum api)
+{
+ mAPI = api;
+}
+
+EGLenum Thread::getAPI() const
+{
+ return mAPI;
+}
+
+void Thread::setCurrent(Display *display,
+ Surface *drawSurface,
+ Surface *readSurface,
+ gl::Context *context)
+{
+ mDisplay = display;
+ mDrawSurface = drawSurface;
+ mReadSurface = readSurface;
+ mContext = context;
+}
+
+Display *Thread::getDisplay() const
+{
+ return mDisplay;
+}
+
+Surface *Thread::getDrawSurface() const
+{
+ return mDrawSurface;
+}
+
+Surface *Thread::getReadSurface() const
+{
+ return mReadSurface;
+}
+
+gl::Context *Thread::getContext() const
+{
+ return mContext;
+}
+
+gl::Context *Thread::getValidContext() const
+{
+ if (mContext && mContext->isContextLost())
+ {
+ mContext->handleError(gl::Error(GL_OUT_OF_MEMORY, "Context has been lost."));
+ return nullptr;
+ }
+
+ return mContext;
+}
+
+} // namespace egl
diff --git a/gfx/angle/src/libANGLE/Thread.h b/gfx/angle/src/libANGLE/Thread.h
new file mode 100644
index 000000000..7a67dc62b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Thread.h
@@ -0,0 +1,57 @@
+//
+// Copyright(c) 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>
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace egl
+{
+class Error;
+class Display;
+class Surface;
+
+class Thread
+{
+ public:
+ Thread();
+
+ void setError(const Error &error);
+ EGLint getError() const;
+
+ void setAPI(EGLenum api);
+ EGLenum getAPI() const;
+
+ void setCurrent(Display *display,
+ Surface *drawSurface,
+ Surface *readSurface,
+ gl::Context *context);
+ Display *getDisplay() const;
+ Surface *getDrawSurface() const;
+ Surface *getReadSurface() const;
+ gl::Context *getContext() const;
+ gl::Context *getValidContext() const;
+
+ private:
+ EGLint mError;
+ EGLenum mAPI;
+ egl::Display *mDisplay;
+ egl::Surface *mDrawSurface;
+ egl::Surface *mReadSurface;
+ gl::Context *mContext;
+};
+
+} // namespace egl
+
+#endif // LIBANGLE_THREAD_H_
diff --git a/gfx/angle/src/libANGLE/TransformFeedback.cpp b/gfx/angle/src/libANGLE/TransformFeedback.cpp
new file mode 100755
index 000000000..293c91b31
--- /dev/null
+++ b/gfx/angle/src/libANGLE/TransformFeedback.cpp
@@ -0,0 +1,206 @@
+//
+// Copyright (c) 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 "libANGLE/Buffer.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace gl
+{
+
+TransformFeedbackState::TransformFeedbackState(size_t maxIndexedBuffers)
+ : mLabel(),
+ mActive(false),
+ mPrimitiveMode(GL_NONE),
+ mPaused(false),
+ mProgram(nullptr),
+ mGenericBuffer(),
+ mIndexedBuffers(maxIndexedBuffers)
+{
+}
+
+const BindingPointer<Buffer> &TransformFeedbackState::getGenericBuffer() const
+{
+ return mGenericBuffer;
+}
+
+const OffsetBindingPointer<Buffer> &TransformFeedbackState::getIndexedBuffer(size_t idx) const
+{
+ return mIndexedBuffers[idx];
+}
+
+const std::vector<OffsetBindingPointer<Buffer>> &TransformFeedbackState::getIndexedBuffers() const
+{
+ return mIndexedBuffers;
+}
+
+TransformFeedback::TransformFeedback(rx::GLImplFactory *implFactory, GLuint id, const Caps &caps)
+ : RefCountObject(id),
+ mState(caps.maxTransformFeedbackSeparateAttributes),
+ mImplementation(implFactory->createTransformFeedback(mState))
+{
+ ASSERT(mImplementation != nullptr);
+}
+
+TransformFeedback::~TransformFeedback()
+{
+ if (mState.mProgram)
+ {
+ mState.mProgram->release();
+ mState.mProgram = nullptr;
+ }
+ mState.mGenericBuffer.set(nullptr);
+ for (size_t i = 0; i < mState.mIndexedBuffers.size(); i++)
+ {
+ mState.mIndexedBuffers[i].set(nullptr);
+ }
+
+ SafeDelete(mImplementation);
+}
+
+void TransformFeedback::setLabel(const std::string &label)
+{
+ mState.mLabel = label;
+}
+
+const std::string &TransformFeedback::getLabel() const
+{
+ return mState.mLabel;
+}
+
+void TransformFeedback::begin(GLenum primitiveMode, Program *program)
+{
+ mState.mActive = true;
+ mState.mPrimitiveMode = primitiveMode;
+ mState.mPaused = false;
+ mImplementation->begin(primitiveMode);
+ bindProgram(program);
+}
+
+void TransformFeedback::end()
+{
+ mState.mActive = false;
+ mState.mPrimitiveMode = GL_NONE;
+ mState.mPaused = false;
+ mImplementation->end();
+ if (mState.mProgram)
+ {
+ mState.mProgram->release();
+ mState.mProgram = nullptr;
+ }
+}
+
+void TransformFeedback::pause()
+{
+ mState.mPaused = true;
+ mImplementation->pause();
+}
+
+void TransformFeedback::resume()
+{
+ mState.mPaused = false;
+ mImplementation->resume();
+}
+
+bool TransformFeedback::isActive() const
+{
+ return mState.mActive;
+}
+
+bool TransformFeedback::isPaused() const
+{
+ return mState.mPaused;
+}
+
+GLenum TransformFeedback::getPrimitiveMode() const
+{
+ return mState.mPrimitiveMode;
+}
+
+void TransformFeedback::bindProgram(Program *program)
+{
+ if (mState.mProgram != program)
+ {
+ if (mState.mProgram != nullptr)
+ {
+ mState.mProgram->release();
+ }
+ mState.mProgram = program;
+ if (mState.mProgram != nullptr)
+ {
+ mState.mProgram->addRef();
+ }
+ }
+}
+
+bool TransformFeedback::hasBoundProgram(GLuint program) const
+{
+ return mState.mProgram != nullptr && mState.mProgram->id() == program;
+}
+
+void TransformFeedback::bindGenericBuffer(Buffer *buffer)
+{
+ mState.mGenericBuffer.set(buffer);
+ mImplementation->bindGenericBuffer(mState.mGenericBuffer);
+}
+
+void TransformFeedback::detachBuffer(GLuint bufferName)
+{
+ for (size_t index = 0; index < mState.mIndexedBuffers.size(); index++)
+ {
+ if (mState.mIndexedBuffers[index].id() == bufferName)
+ {
+ mState.mIndexedBuffers[index].set(nullptr);
+ mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]);
+ }
+ }
+
+ if (mState.mGenericBuffer.id() == bufferName)
+ {
+ mState.mGenericBuffer.set(nullptr);
+ mImplementation->bindGenericBuffer(mState.mGenericBuffer);
+ }
+}
+
+const BindingPointer<Buffer> &TransformFeedback::getGenericBuffer() const
+{
+ return mState.mGenericBuffer;
+}
+
+void TransformFeedback::bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size)
+{
+ ASSERT(index < mState.mIndexedBuffers.size());
+ mState.mIndexedBuffers[index].set(buffer, offset, size);
+ mImplementation->bindIndexedBuffer(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();
+}
+
+rx::TransformFeedbackImpl *TransformFeedback::getImplementation()
+{
+ return mImplementation;
+}
+
+const rx::TransformFeedbackImpl *TransformFeedback::getImplementation() const
+{
+ return mImplementation;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/TransformFeedback.h b/gfx/angle/src/libANGLE/TransformFeedback.h
new file mode 100755
index 000000000..5b1eb34bf
--- /dev/null
+++ b/gfx/angle/src/libANGLE/TransformFeedback.h
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 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/angleutils.h"
+#include "libANGLE/Debug.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+class GLImplFactory;
+class TransformFeedbackImpl;
+}
+
+namespace gl
+{
+class Buffer;
+struct Caps;
+class Program;
+
+class TransformFeedbackState final : public angle::NonCopyable
+{
+ public:
+ TransformFeedbackState(size_t maxIndexedBuffers);
+
+ const BindingPointer<Buffer> &getGenericBuffer() const;
+ const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t idx) const;
+ const std::vector<OffsetBindingPointer<Buffer>> &getIndexedBuffers() const;
+
+ private:
+ friend class TransformFeedback;
+
+ std::string mLabel;
+
+ bool mActive;
+ GLenum mPrimitiveMode;
+ bool mPaused;
+
+ Program *mProgram;
+
+ BindingPointer<Buffer> mGenericBuffer;
+ std::vector<OffsetBindingPointer<Buffer>> mIndexedBuffers;
+};
+
+class TransformFeedback final : public RefCountObject, public LabeledObject
+{
+ public:
+ TransformFeedback(rx::GLImplFactory *implFactory, GLuint id, const Caps &caps);
+ virtual ~TransformFeedback();
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ void begin(GLenum primitiveMode, Program *program);
+ void end();
+ void pause();
+ void resume();
+
+ bool isActive() const;
+ bool isPaused() const;
+ GLenum getPrimitiveMode() const;
+
+ bool hasBoundProgram(GLuint program) const;
+
+ void bindGenericBuffer(Buffer *buffer);
+ const BindingPointer<Buffer> &getGenericBuffer() const;
+
+ void bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size);
+ const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t index) const;
+ size_t getIndexedBufferCount() const;
+
+ void detachBuffer(GLuint bufferName);
+
+ rx::TransformFeedbackImpl *getImplementation();
+ const rx::TransformFeedbackImpl *getImplementation() const;
+
+ private:
+ void bindProgram(Program *program);
+
+ TransformFeedbackState mState;
+ rx::TransformFeedbackImpl* mImplementation;
+};
+
+}
+
+#endif // LIBANGLE_TRANSFORM_FEEDBACK_H_
diff --git a/gfx/angle/src/libANGLE/TransformFeedback_unittest.cpp b/gfx/angle/src/libANGLE/TransformFeedback_unittest.cpp
new file mode 100755
index 000000000..aa464d105
--- /dev/null
+++ b/gfx/angle/src/libANGLE/TransformFeedback_unittest.cpp
@@ -0,0 +1,148 @@
+//
+// Copyright (c) 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 "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/renderer/BufferImpl_mock.h"
+#include "libANGLE/renderer/TransformFeedbackImpl_mock.h"
+#include "tests/angle_unittests_utils.h"
+
+using ::testing::_;
+using ::testing::get;
+using ::testing::Return;
+using ::testing::SetArgumentPointee;
+
+namespace
+{
+
+ACTION(CreateMockTransformFeedbackImpl)
+{
+ return new rx::MockTransformFeedbackImpl(arg0);
+}
+
+class TransformFeedbackTest : public testing::Test
+{
+ protected:
+ TransformFeedbackTest() : mImpl(nullptr), mFeedback(nullptr) {}
+
+ void SetUp() override
+ {
+ EXPECT_CALL(mMockFactory, createTransformFeedback(_))
+ .WillOnce(CreateMockTransformFeedbackImpl())
+ .RetiresOnSaturation();
+
+ // Set a reasonable number of tf attributes
+ mCaps.maxTransformFeedbackSeparateAttributes = 8;
+
+ mFeedback = new gl::TransformFeedback(&mMockFactory, 1, mCaps);
+ mFeedback->addRef();
+
+ mImpl = rx::GetImplAs<rx::MockTransformFeedbackImpl>(mFeedback);
+ EXPECT_CALL(*mImpl, destructor());
+ }
+
+ void TearDown() override
+ {
+ if (mFeedback)
+ {
+ mFeedback->release();
+ }
+
+ // Only needed because the mock is leaked if bugs are present,
+ // which logs an error, but does not cause the test to fail.
+ // Ordinarily mocks are verified when destroyed.
+ testing::Mock::VerifyAndClear(mImpl);
+ }
+
+ rx::MockGLFactory mMockFactory;
+ rx::MockTransformFeedbackImpl* mImpl;
+ gl::TransformFeedback* mFeedback;
+ gl::Caps mCaps;
+};
+
+TEST_F(TransformFeedbackTest, SideEffectsOfStartAndStop)
+{
+ testing::InSequence seq;
+
+ EXPECT_FALSE(mFeedback->isActive());
+ EXPECT_CALL(*mImpl, begin(GL_TRIANGLES));
+ mFeedback->begin(GL_TRIANGLES, nullptr);
+ EXPECT_TRUE(mFeedback->isActive());
+ EXPECT_EQ(static_cast<GLenum>(GL_TRIANGLES), mFeedback->getPrimitiveMode());
+ EXPECT_CALL(*mImpl, end());
+ mFeedback->end();
+ EXPECT_FALSE(mFeedback->isActive());
+}
+
+TEST_F(TransformFeedbackTest, SideEffectsOfPauseAndResume)
+{
+ testing::InSequence seq;
+
+ EXPECT_FALSE(mFeedback->isActive());
+ EXPECT_CALL(*mImpl, begin(GL_TRIANGLES));
+ mFeedback->begin(GL_TRIANGLES, nullptr);
+ EXPECT_FALSE(mFeedback->isPaused());
+ EXPECT_CALL(*mImpl, pause());
+ mFeedback->pause();
+ EXPECT_TRUE(mFeedback->isPaused());
+ EXPECT_CALL(*mImpl, resume());
+ mFeedback->resume();
+ EXPECT_FALSE(mFeedback->isPaused());
+ EXPECT_CALL(*mImpl, end());
+ mFeedback->end();
+}
+
+TEST_F(TransformFeedbackTest, BufferBinding)
+{
+ rx::MockBufferImpl *bufferImpl = new rx::MockBufferImpl;
+ EXPECT_CALL(*bufferImpl, destructor()).Times(1).RetiresOnSaturation();
+
+ rx::MockGLFactory mockGLFactory;
+ EXPECT_CALL(mockGLFactory, createBuffer(_))
+ .Times(1)
+ .WillOnce(Return(bufferImpl))
+ .RetiresOnSaturation();
+
+ gl::Buffer *buffer = new gl::Buffer(&mockGLFactory, 1);
+
+ static const size_t bindIndex = 0;
+
+ EXPECT_EQ(mFeedback->getIndexedBufferCount(), mCaps.maxTransformFeedbackSeparateAttributes);
+
+ EXPECT_CALL(*mImpl, bindGenericBuffer(_));
+ mFeedback->bindGenericBuffer(buffer);
+ EXPECT_EQ(mFeedback->getGenericBuffer().get(), buffer);
+
+ EXPECT_CALL(*mImpl, bindIndexedBuffer(_, _));
+ mFeedback->bindIndexedBuffer(bindIndex, buffer, 0, 1);
+ for (size_t i = 0; i < mFeedback->getIndexedBufferCount(); i++)
+ {
+ if (i == bindIndex)
+ {
+ EXPECT_EQ(mFeedback->getIndexedBuffer(i).get(), buffer);
+ }
+ else
+ {
+ EXPECT_EQ(mFeedback->getIndexedBuffer(i).get(), nullptr);
+ }
+ }
+
+ // force-release the feedback object to ensure the buffer is released.
+ const size_t releaseCount = mFeedback->getRefCount();
+ for (size_t count = 0; count < releaseCount; ++count)
+ {
+ mFeedback->release();
+ }
+
+ mFeedback = nullptr;
+
+ testing::Mock::VerifyAndClear(bufferImpl);
+}
+
+} // anonymous namespace
diff --git a/gfx/angle/src/libANGLE/Uniform.cpp b/gfx/angle/src/libANGLE/Uniform.cpp
new file mode 100755
index 000000000..3caa3f5e2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Uniform.cpp
@@ -0,0 +1,160 @@
+//
+// Copyright (c) 2010-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.
+//
+
+#include "libANGLE/Uniform.h"
+
+#include "common/utilities.h"
+
+#include <cstring>
+
+namespace gl
+{
+
+LinkedUniform::LinkedUniform()
+ : blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
+{
+}
+
+LinkedUniform::LinkedUniform(GLenum typeIn,
+ GLenum precisionIn,
+ const std::string &nameIn,
+ unsigned int arraySizeIn,
+ const int blockIndexIn,
+ const sh::BlockMemberInfo &blockInfoIn)
+ : blockIndex(blockIndexIn), blockInfo(blockInfoIn)
+{
+ type = typeIn;
+ precision = precisionIn;
+ name = nameIn;
+ arraySize = arraySizeIn;
+}
+
+LinkedUniform::LinkedUniform(const sh::Uniform &uniform)
+ : sh::Uniform(uniform), blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
+{
+}
+
+LinkedUniform::LinkedUniform(const LinkedUniform &uniform)
+ : sh::Uniform(uniform), blockIndex(uniform.blockIndex), blockInfo(uniform.blockInfo)
+{
+ // This function is not intended to be called during runtime.
+ ASSERT(uniform.mLazyData.empty());
+}
+
+LinkedUniform &LinkedUniform::operator=(const LinkedUniform &uniform)
+{
+ // This function is not intended to be called during runtime.
+ ASSERT(uniform.mLazyData.empty());
+
+ sh::Uniform::operator=(uniform);
+ blockIndex = uniform.blockIndex;
+ blockInfo = uniform.blockInfo;
+
+ return *this;
+}
+
+LinkedUniform::~LinkedUniform()
+{
+}
+
+bool LinkedUniform::isInDefaultBlock() const
+{
+ return blockIndex == -1;
+}
+
+size_t LinkedUniform::dataSize() const
+{
+ ASSERT(type != GL_STRUCT_ANGLEX);
+ if (mLazyData.empty())
+ {
+ mLazyData.resize(VariableExternalSize(type) * elementCount());
+ ASSERT(!mLazyData.empty());
+ }
+
+ return mLazyData.size();
+}
+
+uint8_t *LinkedUniform::data()
+{
+ if (mLazyData.empty())
+ {
+ // dataSize() will init the data store.
+ size_t size = dataSize();
+ memset(mLazyData.data(), 0, size);
+ }
+
+ return mLazyData.data();
+}
+
+const uint8_t *LinkedUniform::data() const
+{
+ return const_cast<LinkedUniform *>(this)->data();
+}
+
+bool LinkedUniform::isSampler() const
+{
+ return IsSamplerType(type);
+}
+
+bool LinkedUniform::isField() const
+{
+ return name.find('.') != std::string::npos;
+}
+
+size_t LinkedUniform::getElementSize() const
+{
+ return VariableExternalSize(type);
+}
+
+size_t LinkedUniform::getElementComponents() const
+{
+ return VariableComponentCount(type);
+}
+
+uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex)
+{
+ ASSERT((!isArray() && elementIndex == 0) || (isArray() && elementIndex < arraySize));
+ return data() + getElementSize() * elementIndex;
+}
+
+const uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex) const
+{
+ return const_cast<LinkedUniform *>(this)->getDataPtrToElement(elementIndex);
+}
+
+UniformBlock::UniformBlock()
+ : isArray(false),
+ arrayElement(0),
+ dataSize(0),
+ vertexStaticUse(false),
+ fragmentStaticUse(false),
+ computeStaticUse(false)
+{
+}
+
+UniformBlock::UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn)
+ : name(nameIn),
+ isArray(isArrayIn),
+ arrayElement(arrayElementIn),
+ dataSize(0),
+ vertexStaticUse(false),
+ fragmentStaticUse(false),
+ computeStaticUse(false)
+{
+}
+
+std::string UniformBlock::nameWithArrayIndex() const
+{
+ std::stringstream fullNameStr;
+ fullNameStr << name;
+ if (isArray)
+ {
+ fullNameStr << "[" << arrayElement << "]";
+ }
+
+ return fullNameStr.str();
+}
+}
diff --git a/gfx/angle/src/libANGLE/Uniform.h b/gfx/angle/src/libANGLE/Uniform.h
new file mode 100755
index 000000000..3b822e52b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Uniform.h
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2010-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.
+//
+
+#ifndef LIBANGLE_UNIFORM_H_
+#define LIBANGLE_UNIFORM_H_
+
+#include <string>
+#include <vector>
+
+#include "angle_gl.h"
+#include "common/debug.h"
+#include "common/MemoryBuffer.h"
+#include "compiler/translator/blocklayout.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+
+// Helper struct representing a single shader uniform
+struct LinkedUniform : public sh::Uniform
+{
+ LinkedUniform();
+ LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo);
+ LinkedUniform(const sh::Uniform &uniform);
+ LinkedUniform(const LinkedUniform &uniform);
+ LinkedUniform &operator=(const LinkedUniform &uniform);
+ ~LinkedUniform();
+
+ size_t dataSize() const;
+ uint8_t *data();
+ const uint8_t *data() const;
+ bool isSampler() const;
+ bool isInDefaultBlock() const;
+ bool isField() const;
+ size_t getElementSize() const;
+ size_t getElementComponents() const;
+ uint8_t *getDataPtrToElement(size_t elementIndex);
+ const uint8_t *getDataPtrToElement(size_t elementIndex) const;
+
+ int blockIndex;
+ sh::BlockMemberInfo blockInfo;
+
+ private:
+ mutable rx::MemoryBuffer mLazyData;
+};
+
+// Helper struct representing a single shader uniform block
+struct UniformBlock
+{
+ UniformBlock();
+ UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn);
+ UniformBlock(const UniformBlock &other) = default;
+ UniformBlock &operator=(const UniformBlock &other) = default;
+
+ std::string nameWithArrayIndex() const;
+
+ std::string name;
+ bool isArray;
+ unsigned int arrayElement;
+ unsigned int dataSize;
+
+ bool vertexStaticUse;
+ bool fragmentStaticUse;
+ bool computeStaticUse;
+
+ std::vector<unsigned int> memberUniformIndexes;
+};
+
+}
+
+#endif // LIBANGLE_UNIFORM_H_
diff --git a/gfx/angle/src/libANGLE/Version.h b/gfx/angle/src/libANGLE/Version.h
new file mode 100755
index 000000000..4c9730c7b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Version.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 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_
+
+#include <angle_gl.h>
+
+namespace gl
+{
+
+struct Version
+{
+ constexpr Version();
+ constexpr Version(GLuint major, GLuint minor);
+
+ GLuint major;
+ GLuint 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);
+}
+
+#include "Version.inl"
+
+#endif // LIBANGLE_VERSION_H_
diff --git a/gfx/angle/src/libANGLE/Version.inl b/gfx/angle/src/libANGLE/Version.inl
new file mode 100755
index 000000000..495209720
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Version.inl
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 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.inl: 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(GLuint major_, GLuint 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);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/VertexArray.cpp b/gfx/angle/src/libANGLE/VertexArray.cpp
new file mode 100755
index 000000000..0b8fcb63d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/VertexArray.cpp
@@ -0,0 +1,138 @@
+//
+// Copyright (c) 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 "libANGLE/Buffer.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/VertexArrayImpl.h"
+
+namespace gl
+{
+
+VertexArrayState::VertexArrayState(size_t maxAttribs)
+ : mLabel(), mVertexAttributes(maxAttribs), mMaxEnabledAttribute(0)
+{
+}
+
+VertexArrayState::~VertexArrayState()
+{
+ for (size_t i = 0; i < getMaxAttribs(); i++)
+ {
+ mVertexAttributes[i].buffer.set(nullptr);
+ }
+ mElementArrayBuffer.set(nullptr);
+}
+
+VertexArray::VertexArray(rx::GLImplFactory *factory, GLuint id, size_t maxAttribs)
+ : mId(id), mState(maxAttribs), mVertexArray(factory->createVertexArray(mState))
+{
+}
+
+VertexArray::~VertexArray()
+{
+ SafeDelete(mVertexArray);
+}
+
+GLuint VertexArray::id() const
+{
+ return mId;
+}
+
+void VertexArray::setLabel(const std::string &label)
+{
+ mState.mLabel = label;
+}
+
+const std::string &VertexArray::getLabel() const
+{
+ return mState.mLabel;
+}
+
+void VertexArray::detachBuffer(GLuint bufferName)
+{
+ for (size_t attribute = 0; attribute < getMaxAttribs(); attribute++)
+ {
+ if (mState.mVertexAttributes[attribute].buffer.id() == bufferName)
+ {
+ mState.mVertexAttributes[attribute].buffer.set(nullptr);
+ }
+ }
+
+ if (mState.mElementArrayBuffer.id() == bufferName)
+ {
+ mState.mElementArrayBuffer.set(nullptr);
+ }
+}
+
+const VertexAttribute &VertexArray::getVertexAttribute(size_t attributeIndex) const
+{
+ ASSERT(attributeIndex < getMaxAttribs());
+ return mState.mVertexAttributes[attributeIndex];
+}
+
+void VertexArray::setVertexAttribDivisor(size_t index, GLuint divisor)
+{
+ ASSERT(index < getMaxAttribs());
+ mState.mVertexAttributes[index].divisor = divisor;
+ mDirtyBits.set(DIRTY_BIT_ATTRIB_0_DIVISOR + index);
+}
+
+void VertexArray::enableAttribute(size_t attributeIndex, bool enabledState)
+{
+ ASSERT(attributeIndex < getMaxAttribs());
+ mState.mVertexAttributes[attributeIndex].enabled = enabledState;
+ mDirtyBits.set(DIRTY_BIT_ATTRIB_0_ENABLED + attributeIndex);
+
+ // Update state cache
+ if (enabledState)
+ {
+ mState.mMaxEnabledAttribute = std::max(attributeIndex + 1, mState.mMaxEnabledAttribute);
+ }
+ else if (mState.mMaxEnabledAttribute == attributeIndex + 1)
+ {
+ while (mState.mMaxEnabledAttribute > 0 &&
+ !mState.mVertexAttributes[mState.mMaxEnabledAttribute - 1].enabled)
+ {
+ --mState.mMaxEnabledAttribute;
+ }
+ }
+}
+
+void VertexArray::setAttributeState(size_t attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type,
+ bool normalized, bool pureInteger, GLsizei stride, const void *pointer)
+{
+ ASSERT(attributeIndex < getMaxAttribs());
+
+ VertexAttribute *attrib = &mState.mVertexAttributes[attributeIndex];
+
+ attrib->buffer.set(boundBuffer);
+ attrib->size = size;
+ attrib->type = type;
+ attrib->normalized = normalized;
+ attrib->pureInteger = pureInteger;
+ attrib->stride = stride;
+ attrib->pointer = pointer;
+ mDirtyBits.set(DIRTY_BIT_ATTRIB_0_POINTER + attributeIndex);
+}
+
+void VertexArray::setElementArrayBuffer(Buffer *buffer)
+{
+ mState.mElementArrayBuffer.set(buffer);
+ mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
+}
+
+void VertexArray::syncImplState()
+{
+ if (mDirtyBits.any())
+ {
+ mVertexArray->syncState(mDirtyBits);
+ mDirtyBits.reset();
+ }
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/VertexArray.h b/gfx/angle/src/libANGLE/VertexArray.h
new file mode 100755
index 000000000..65c62f1ba
--- /dev/null
+++ b/gfx/angle/src/libANGLE/VertexArray.h
@@ -0,0 +1,130 @@
+//
+// Copyright (c) 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 "libANGLE/RefCountObject.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexAttribute.h"
+
+#include <vector>
+
+namespace rx
+{
+class GLImplFactory;
+class VertexArrayImpl;
+}
+
+namespace gl
+{
+class Buffer;
+
+class VertexArrayState final : public angle::NonCopyable
+{
+ public:
+ explicit VertexArrayState(size_t maxAttribs);
+ ~VertexArrayState();
+
+ const std::string &getLabel() const { return mLabel; }
+
+ const BindingPointer<Buffer> &getElementArrayBuffer() const { return mElementArrayBuffer; }
+ size_t getMaxAttribs() const { return mVertexAttributes.size(); }
+ size_t getMaxEnabledAttribute() const { return mMaxEnabledAttribute; }
+ const std::vector<VertexAttribute> &getVertexAttributes() const { return mVertexAttributes; }
+ const VertexAttribute &getVertexAttribute(size_t index) const
+ {
+ return mVertexAttributes[index];
+ }
+
+ private:
+ friend class VertexArray;
+ std::string mLabel;
+ std::vector<VertexAttribute> mVertexAttributes;
+ BindingPointer<Buffer> mElementArrayBuffer;
+ size_t mMaxEnabledAttribute;
+};
+
+class VertexArray final : public LabeledObject
+{
+ public:
+ VertexArray(rx::GLImplFactory *factory, GLuint id, size_t maxAttribs);
+ ~VertexArray();
+
+ GLuint id() const;
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ const VertexAttribute &getVertexAttribute(size_t attributeIndex) const;
+
+ void detachBuffer(GLuint bufferName);
+ void setVertexAttribDivisor(size_t index, GLuint divisor);
+ void enableAttribute(size_t attributeIndex, bool enabledState);
+ void setAttributeState(size_t attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type,
+ bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
+
+ void setElementArrayBuffer(Buffer *buffer);
+
+ const BindingPointer<Buffer> &getElementArrayBuffer() const
+ {
+ return mState.getElementArrayBuffer();
+ }
+ size_t getMaxAttribs() const { return mState.getVertexAttributes().size(); }
+ const std::vector<VertexAttribute> &getVertexAttributes() const
+ {
+ return mState.getVertexAttributes();
+ }
+
+ rx::VertexArrayImpl *getImplementation() const { return mVertexArray; }
+
+ size_t getMaxEnabledAttribute() const { return mState.getMaxEnabledAttribute(); }
+
+ enum DirtyBitType
+ {
+ DIRTY_BIT_ELEMENT_ARRAY_BUFFER,
+
+ // Reserve bits for enabled flags
+ DIRTY_BIT_ATTRIB_0_ENABLED,
+ DIRTY_BIT_ATTRIB_MAX_ENABLED = DIRTY_BIT_ATTRIB_0_ENABLED + gl::MAX_VERTEX_ATTRIBS,
+
+ // Reserve bits for attrib pointers
+ DIRTY_BIT_ATTRIB_0_POINTER = DIRTY_BIT_ATTRIB_MAX_ENABLED,
+ DIRTY_BIT_ATTRIB_MAX_POINTER = DIRTY_BIT_ATTRIB_0_POINTER + gl::MAX_VERTEX_ATTRIBS,
+
+ // Reserve bits for divisors
+ DIRTY_BIT_ATTRIB_0_DIVISOR = DIRTY_BIT_ATTRIB_MAX_POINTER,
+ DIRTY_BIT_ATTRIB_MAX_DIVISOR = DIRTY_BIT_ATTRIB_0_DIVISOR + gl::MAX_VERTEX_ATTRIBS,
+
+ DIRTY_BIT_UNKNOWN = DIRTY_BIT_ATTRIB_MAX_DIVISOR,
+ DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN,
+ };
+
+ typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
+
+ void syncImplState();
+ bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
+ private:
+ GLuint mId;
+
+ VertexArrayState mState;
+ DirtyBits mDirtyBits;
+
+ rx::VertexArrayImpl *mVertexArray;
+};
+
+}
+
+#endif // LIBANGLE_VERTEXARRAY_H_
diff --git a/gfx/angle/src/libANGLE/VertexAttribute.cpp b/gfx/angle/src/libANGLE/VertexAttribute.cpp
new file mode 100755
index 000000000..13d78fd13
--- /dev/null
+++ b/gfx/angle/src/libANGLE/VertexAttribute.cpp
@@ -0,0 +1,74 @@
+//
+// 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 class for mananging GLES 3 Vertex Array Objects.
+//
+
+#include "libANGLE/VertexAttribute.h"
+
+namespace gl
+{
+
+VertexAttribute::VertexAttribute()
+ : enabled(false),
+ type(GL_FLOAT),
+ size(4),
+ normalized(false),
+ pureInteger(false),
+ stride(0),
+ pointer(NULL),
+ divisor(0)
+{
+}
+
+size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib)
+{
+ GLuint size = attrib.size;
+ switch (attrib.type)
+ {
+ case GL_BYTE: return size * sizeof(GLbyte);
+ case GL_UNSIGNED_BYTE: return size * sizeof(GLubyte);
+ case GL_SHORT: return size * sizeof(GLshort);
+ case GL_UNSIGNED_SHORT: return size * sizeof(GLushort);
+ case GL_INT: return size * sizeof(GLint);
+ case GL_UNSIGNED_INT: return size * sizeof(GLuint);
+ case GL_INT_2_10_10_10_REV: return 4;
+ case GL_UNSIGNED_INT_2_10_10_10_REV: return 4;
+ case GL_FIXED: return size * sizeof(GLfixed);
+ case GL_HALF_FLOAT: return size * sizeof(GLhalf);
+ case GL_FLOAT: return size * sizeof(GLfloat);
+ default: UNREACHABLE(); return size * sizeof(GLfloat);
+ }
+}
+
+size_t ComputeVertexAttributeStride(const VertexAttribute& attrib)
+{
+ if (!attrib.enabled)
+ {
+ return 16;
+ }
+ return attrib.stride ? attrib.stride : ComputeVertexAttributeTypeSize(attrib);
+}
+
+size_t ComputeVertexAttributeElementCount(const VertexAttribute &attrib,
+ 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 && attrib.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 + attrib.divisor - 1u) / attrib.divisor;
+ }
+
+ return drawCount;
+}
+}
diff --git a/gfx/angle/src/libANGLE/VertexAttribute.h b/gfx/angle/src/libANGLE/VertexAttribute.h
new file mode 100755
index 000000000..a8cc8573b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/VertexAttribute.h
@@ -0,0 +1,72 @@
+//
+// Copyright (c) 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 structure describing a single vertex attribute
+//
+
+#ifndef LIBANGLE_VERTEXATTRIBUTE_H_
+#define LIBANGLE_VERTEXATTRIBUTE_H_
+
+#include "libANGLE/Buffer.h"
+
+namespace gl
+{
+
+struct VertexAttribute
+{
+ bool enabled; // From glEnable/DisableVertexAttribArray
+
+ GLenum type;
+ GLuint size;
+ bool normalized;
+ bool pureInteger;
+ GLuint stride; // 0 means natural stride
+
+ union
+ {
+ const GLvoid *pointer;
+ GLintptr offset;
+ };
+ BindingPointer<Buffer> buffer; // Captured when glVertexAttribPointer is called.
+
+ GLuint divisor;
+
+ VertexAttribute();
+};
+
+bool operator==(const VertexAttribute &a, const VertexAttribute &b);
+bool operator!=(const VertexAttribute &a, const VertexAttribute &b);
+
+size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib);
+size_t ComputeVertexAttributeStride(const VertexAttribute& attrib);
+size_t ComputeVertexAttributeElementCount(const VertexAttribute &attrib,
+ size_t drawCount,
+ size_t instanceCount);
+
+struct VertexAttribCurrentValueData
+{
+ union
+ {
+ GLfloat FloatValues[4];
+ GLint IntValues[4];
+ GLuint UnsignedIntValues[4];
+ };
+ GLenum 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);
+
+}
+
+#include "VertexAttribute.inl"
+
+#endif // LIBANGLE_VERTEXATTRIBUTE_H_
diff --git a/gfx/angle/src/libANGLE/VertexAttribute.inl b/gfx/angle/src/libANGLE/VertexAttribute.inl
new file mode 100755
index 000000000..a1f88f317
--- /dev/null
+++ b/gfx/angle/src/libANGLE/VertexAttribute.inl
@@ -0,0 +1,76 @@
+//
+// Copyright (c) 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.inl: Inline vertex attribute methods
+//
+
+namespace gl
+{
+
+inline bool operator==(const VertexAttribute &a, const VertexAttribute &b)
+{
+ return a.enabled == b.enabled &&
+ a.type == b.type &&
+ a.size == b.size &&
+ a.normalized == b.normalized &&
+ a.pureInteger == b.pureInteger &&
+ a.stride == b.stride &&
+ a.pointer == b.pointer &&
+ a.buffer.get() == b.buffer.get() &&
+ a.divisor == b.divisor;
+}
+
+inline bool operator!=(const VertexAttribute &a, const VertexAttribute &b)
+{
+ return !(a == b);
+}
+
+inline VertexAttribCurrentValueData::VertexAttribCurrentValueData()
+ : Type(GL_FLOAT)
+{
+ FloatValues[0] = 0.0f;
+ FloatValues[1] = 0.0f;
+ FloatValues[2] = 0.0f;
+ FloatValues[3] = 1.0f;
+}
+
+inline void VertexAttribCurrentValueData::setFloatValues(const GLfloat floatValues[4])
+{
+ for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+ {
+ FloatValues[valueIndex] = floatValues[valueIndex];
+ }
+ Type = GL_FLOAT;
+}
+
+inline void VertexAttribCurrentValueData::setIntValues(const GLint intValues[4])
+{
+ for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+ {
+ IntValues[valueIndex] = intValues[valueIndex];
+ }
+ Type = GL_INT;
+}
+
+inline void VertexAttribCurrentValueData::setUnsignedIntValues(const GLuint unsignedIntValues[4])
+{
+ for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+ {
+ UnsignedIntValues[valueIndex] = unsignedIntValues[valueIndex];
+ }
+ Type = GL_UNSIGNED_INT;
+}
+
+inline bool operator==(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b)
+{
+ return (a.Type == b.Type && memcmp(a.FloatValues, b.FloatValues, sizeof(float) * 4) == 0);
+}
+
+inline bool operator!=(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b)
+{
+ return !(a == b);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/Workarounds.h b/gfx/angle/src/libANGLE/Workarounds.h
new file mode 100644
index 000000000..c5533c1c8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Workarounds.h
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 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.
+//
+
+// Workarounds.h: Workarounds for driver bugs and other behaviors seen
+// on all platforms.
+
+#ifndef LIBANGLE_WORKAROUNDS_H_
+#define LIBANGLE_WORKAROUNDS_H_
+
+namespace gl
+{
+
+struct Workarounds
+{
+ // Force the context to be lost (via KHR_robustness) if a GL_OUT_OF_MEMORY error occurs. The
+ // driver may be in an inconsistent state if this happens, and some users of ANGLE rely on this
+ // notification to prevent further execution.
+ bool loseContextOnOutOfMemory = false;
+};
+} // namespace gl
+
+#endif // LIBANGLE_WORKAROUNDS_H_
diff --git a/gfx/angle/src/libANGLE/angletypes.cpp b/gfx/angle/src/libANGLE/angletypes.cpp
new file mode 100755
index 000000000..70a3ae645
--- /dev/null
+++ b/gfx/angle/src/libANGLE/angletypes.cpp
@@ -0,0 +1,144 @@
+//
+// Copyright (c) 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/VertexAttribute.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
+
+namespace gl
+{
+
+PrimitiveType GetPrimitiveType(GLenum drawMode)
+{
+ switch (drawMode)
+ {
+ case GL_POINTS:
+ return PRIMITIVE_POINTS;
+ case GL_LINES:
+ return PRIMITIVE_LINES;
+ case GL_LINE_STRIP:
+ return PRIMITIVE_LINE_STRIP;
+ case GL_LINE_LOOP:
+ return PRIMITIVE_LINE_LOOP;
+ case GL_TRIANGLES:
+ return PRIMITIVE_TRIANGLES;
+ case GL_TRIANGLE_STRIP:
+ return PRIMITIVE_TRIANGLE_STRIP;
+ case GL_TRIANGLE_FAN:
+ return PRIMITIVE_TRIANGLE_FAN;
+ default:
+ UNREACHABLE();
+ return PRIMITIVE_TYPE_MAX;
+ }
+}
+
+SamplerState::SamplerState()
+ : minFilter(GL_NEAREST_MIPMAP_LINEAR),
+ magFilter(GL_LINEAR),
+ wrapS(GL_REPEAT),
+ wrapT(GL_REPEAT),
+ wrapR(GL_REPEAT),
+ maxAnisotropy(1.0f),
+ minLod(-1000.0f),
+ maxLod(1000.0f),
+ compareMode(GL_NONE),
+ compareFunc(GL_LEQUAL),
+ sRGBDecode(GL_DECODE_EXT)
+{
+}
+
+// static
+SamplerState SamplerState::CreateDefaultForTarget(GLenum target)
+{
+ SamplerState state;
+
+ // According to OES_EGL_image_external: For external textures, the default min filter is
+ // GL_LINEAR and the default s and t wrap modes are GL_CLAMP_TO_EDGE.
+ if (target == GL_TEXTURE_EXTERNAL_OES)
+ {
+ state.minFilter = GL_LINEAR;
+ state.wrapS = GL_CLAMP_TO_EDGE;
+ state.wrapT = GL_CLAMP_TO_EDGE;
+ }
+
+ return state;
+}
+
+static void MinMax(int a, int b, int *minimum, int *maximum)
+{
+ if (a < b)
+ {
+ *minimum = a;
+ *maximum = b;
+ }
+ else
+ {
+ *minimum = b;
+ *maximum = a;
+ }
+}
+
+bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection)
+{
+ int minSourceX, maxSourceX, minSourceY, maxSourceY;
+ MinMax(source.x, source.x + source.width, &minSourceX, &maxSourceX);
+ MinMax(source.y, source.y + source.height, &minSourceY, &maxSourceY);
+
+ int minClipX, maxClipX, minClipY, maxClipY;
+ MinMax(clip.x, clip.x + clip.width, &minClipX, &maxClipX);
+ MinMax(clip.y, clip.y + clip.height, &minClipY, &maxClipY);
+
+ if (minSourceX >= maxClipX || maxSourceX <= minClipX || minSourceY >= maxClipY || maxSourceY <= minClipY)
+ {
+ if (intersection)
+ {
+ intersection->x = minSourceX;
+ intersection->y = maxSourceY;
+ intersection->width = maxSourceX - minSourceX;
+ intersection->height = maxSourceY - minSourceY;
+ }
+
+ return false;
+ }
+ else
+ {
+ if (intersection)
+ {
+ intersection->x = std::max(minSourceX, minClipX);
+ intersection->y = std::max(minSourceY, minClipY);
+ intersection->width = std::min(maxSourceX, maxClipX) - std::max(minSourceX, minClipX);
+ intersection->height = std::min(maxSourceY, maxClipY) - std::max(minSourceY, minClipY);
+ }
+
+ return true;
+ }
+}
+
+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);
+}
+
+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);
+}
+}
diff --git a/gfx/angle/src/libANGLE/angletypes.h b/gfx/angle/src/libANGLE/angletypes.h
new file mode 100755
index 000000000..4c345c3d0
--- /dev/null
+++ b/gfx/angle/src/libANGLE/angletypes.h
@@ -0,0 +1,341 @@
+//
+// Copyright (c) 2012-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
+
+#ifndef LIBANGLE_ANGLETYPES_H_
+#define LIBANGLE_ANGLETYPES_H_
+
+#include "libANGLE/Constants.h"
+#include "libANGLE/RefCountObject.h"
+
+#include <stdint.h>
+
+#include <bitset>
+#include <unordered_map>
+
+namespace gl
+{
+class Buffer;
+class State;
+class Program;
+struct VertexAttribute;
+struct VertexAttribCurrentValueData;
+
+enum PrimitiveType
+{
+ PRIMITIVE_POINTS,
+ PRIMITIVE_LINES,
+ PRIMITIVE_LINE_STRIP,
+ PRIMITIVE_LINE_LOOP,
+ PRIMITIVE_TRIANGLES,
+ PRIMITIVE_TRIANGLE_STRIP,
+ PRIMITIVE_TRIANGLE_FAN,
+ PRIMITIVE_TYPE_MAX,
+};
+
+PrimitiveType GetPrimitiveType(GLenum drawMode);
+
+enum SamplerType
+{
+ SAMPLER_PIXEL,
+ SAMPLER_VERTEX
+};
+
+struct Rectangle
+{
+ Rectangle() : x(0), y(0), width(0), height(0) {}
+ Rectangle(int x_in, int y_in, int width_in, int height_in)
+ : x(x_in), y(y_in), width(width_in), height(height_in)
+ {
+ }
+
+ int x0() const { return x; }
+ int y0() const { return y; }
+ int x1() const { return x + width; }
+ int y1() const { return y + height; }
+
+ int x;
+ int y;
+ int width;
+ int height;
+};
+
+bool operator==(const Rectangle &a, const Rectangle &b);
+bool operator!=(const Rectangle &a, const Rectangle &b);
+
+bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection);
+
+struct Offset
+{
+ int x;
+ int y;
+ int z;
+
+ Offset() : x(0), y(0), z(0) { }
+ Offset(int x_in, int y_in, int z_in) : x(x_in), y(y_in), z(z_in) { }
+};
+
+struct Extents
+{
+ int width;
+ int height;
+ int depth;
+
+ 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; }
+};
+
+bool operator==(const Extents &lhs, const Extents &rhs);
+bool operator!=(const Extents &lhs, const Extents &rhs);
+
+struct Box
+{
+ int x;
+ int y;
+ int z;
+ int width;
+ int height;
+ int depth;
+
+ 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) { }
+ Box(const Offset &offset, const Extents &size) : x(offset.x), y(offset.y), z(offset.z), width(size.width), height(size.height), depth(size.depth) { }
+ bool operator==(const Box &other) const;
+ bool operator!=(const Box &other) const;
+};
+
+
+struct RasterizerState
+{
+ bool cullFace;
+ GLenum cullMode;
+ GLenum frontFace;
+
+ bool polygonOffsetFill;
+ GLfloat polygonOffsetFactor;
+ GLfloat polygonOffsetUnits;
+
+ bool pointDrawMode;
+ bool multiSample;
+
+ bool rasterizerDiscard;
+};
+
+struct BlendState
+{
+ bool blend;
+ GLenum sourceBlendRGB;
+ GLenum destBlendRGB;
+ GLenum sourceBlendAlpha;
+ GLenum destBlendAlpha;
+ GLenum blendEquationRGB;
+ GLenum blendEquationAlpha;
+
+ bool colorMaskRed;
+ bool colorMaskGreen;
+ bool colorMaskBlue;
+ bool colorMaskAlpha;
+
+ bool sampleAlphaToCoverage;
+
+ bool dither;
+};
+
+struct DepthStencilState
+{
+ 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;
+};
+
+// State from Table 6.10 (state per sampler object)
+struct SamplerState
+{
+ SamplerState();
+ static SamplerState CreateDefaultForTarget(GLenum target);
+
+ GLenum minFilter;
+ GLenum magFilter;
+
+ GLenum wrapS;
+ GLenum wrapT;
+ GLenum wrapR;
+
+ // From EXT_texture_filter_anisotropic
+ float maxAnisotropy;
+
+ GLfloat minLod;
+ GLfloat maxLod;
+
+ GLenum compareMode;
+ GLenum compareFunc;
+
+ GLenum sRGBDecode;
+};
+
+bool operator==(const SamplerState &a, const SamplerState &b);
+bool operator!=(const SamplerState &a, const SamplerState &b);
+
+struct PixelStoreStateBase
+{
+ BindingPointer<Buffer> pixelBuffer;
+ GLint alignment = 4;
+ GLint rowLength = 0;
+ GLint skipRows = 0;
+ GLint skipPixels = 0;
+ GLint imageHeight = 0;
+ GLint skipImages = 0;
+};
+
+struct PixelUnpackState : PixelStoreStateBase
+{
+ PixelUnpackState() {}
+
+ PixelUnpackState(GLint alignmentIn, GLint rowLengthIn)
+ {
+ alignment = alignmentIn;
+ rowLength = rowLengthIn;
+ }
+};
+
+struct PixelPackState : PixelStoreStateBase
+{
+ PixelPackState() {}
+
+ PixelPackState(GLint alignmentIn, bool reverseRowOrderIn)
+ : reverseRowOrder(reverseRowOrderIn)
+ {
+ alignment = alignmentIn;
+ }
+
+ bool reverseRowOrder = false;
+};
+
+// Used in Program and VertexArray.
+typedef std::bitset<MAX_VERTEX_ATTRIBS> AttributesMask;
+
+// Use in Program
+typedef std::bitset<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS> UniformBlockBindingMask;
+
+// A map of GL objects indexed by object ID. The specific map implementation may change.
+// Client code should treat it as a std::map.
+template <class ResourceT>
+using ResourceMap = std::unordered_map<GLuint, ResourceT *>;
+}
+
+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());
+}
+
+}
+
+#include "angletypes.inl"
+
+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;
+ }
+}
+}
+
+#endif // LIBANGLE_ANGLETYPES_H_
diff --git a/gfx/angle/src/libANGLE/angletypes.inl b/gfx/angle/src/libANGLE/angletypes.inl
new file mode 100755
index 000000000..3371286b9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/angletypes.inl
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// angletypes.inl : 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 a.minFilter == b.minFilter &&
+ a.magFilter == b.magFilter &&
+ a.wrapS == b.wrapS &&
+ a.wrapT == b.wrapT &&
+ a.wrapR == b.wrapR &&
+ a.maxAnisotropy == b.maxAnisotropy &&
+ a.minLod == b.minLod &&
+ a.maxLod == b.maxLod &&
+ a.compareMode == b.compareMode &&
+ a.compareFunc == b.compareFunc;
+}
+
+inline bool operator!=(const SamplerState &a, const SamplerState &b)
+{
+ return !(a == b);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/es3_copy_conversion_formats.json b/gfx/angle/src/libANGLE/es3_copy_conversion_formats.json
new file mode 100644
index 000000000..39b71fd93
--- /dev/null
+++ b/gfx/angle/src/libANGLE/es3_copy_conversion_formats.json
@@ -0,0 +1,44 @@
+{
+ "From ES 3.0.1 spec, table 3.15":
+ [
+ [ "GL_ALPHA", "GL_RGBA" ],
+ [ "GL_LUMINANCE", "GL_RED" ],
+ [ "GL_LUMINANCE", "GL_RG" ],
+ [ "GL_LUMINANCE", "GL_RGB" ],
+ [ "GL_LUMINANCE", "GL_RGBA" ],
+ [ "GL_LUMINANCE_ALPHA", "GL_RGBA" ],
+ [ "GL_RED", "GL_RED" ],
+ [ "GL_RED", "GL_RG" ],
+ [ "GL_RED", "GL_RGB" ],
+ [ "GL_RED", "GL_RGBA" ],
+ [ "GL_RG", "GL_RG" ],
+ [ "GL_RG", "GL_RGB" ],
+ [ "GL_RG", "GL_RGBA" ],
+ [ "GL_RGB", "GL_RGB" ],
+ [ "GL_RGB", "GL_RGBA" ],
+ [ "GL_RGBA", "GL_RGBA" ]
+ ],
+
+ "Necessary for ANGLE back-buffers":
+ [
+ [ "GL_ALPHA", "GL_BGRA_EXT" ],
+ [ "GL_LUMINANCE", "GL_BGRA_EXT" ],
+ [ "GL_LUMINANCE_ALPHA", "GL_BGRA_EXT" ],
+ [ "GL_RED", "GL_BGRA_EXT" ],
+ [ "GL_RG", "GL_BGRA_EXT" ],
+ [ "GL_RGB", "GL_BGRA_EXT" ],
+ [ "GL_RGBA", "GL_BGRA_EXT" ],
+ [ "GL_BGRA_EXT", "GL_BGRA_EXT" ],
+
+ [ "GL_RED_INTEGER", "GL_RED_INTEGER" ],
+ [ "GL_RED_INTEGER", "GL_RG_INTEGER" ],
+ [ "GL_RED_INTEGER", "GL_RGB_INTEGER" ],
+ [ "GL_RED_INTEGER", "GL_RGBA_INTEGER" ],
+ [ "GL_RG_INTEGER", "GL_RG_INTEGER" ],
+ [ "GL_RG_INTEGER", "GL_RGB_INTEGER" ],
+ [ "GL_RG_INTEGER", "GL_RGBA_INTEGER" ],
+ [ "GL_RGB_INTEGER", "GL_RGB_INTEGER" ],
+ [ "GL_RGB_INTEGER", "GL_RGBA_INTEGER" ],
+ [ "GL_RGBA_INTEGER", "GL_RGBA_INTEGER" ]
+ ]
+}
diff --git a/gfx/angle/src/libANGLE/es3_copy_conversion_table_autogen.cpp b/gfx/angle/src/libANGLE/es3_copy_conversion_table_autogen.cpp
new file mode 100644
index 000000000..3647445c5
--- /dev/null
+++ b/gfx/angle/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/src/libANGLE/es3_format_type_combinations.json b/gfx/angle/src/libANGLE/es3_format_type_combinations.json
new file mode 100644
index 000000000..fb12242e7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/es3_format_type_combinations.json
@@ -0,0 +1,171 @@
+{
+ "Format combinations from ES 3.0.1 spec, table 3.2":
+ [
+ [ "GL_RGBA8", "GL_RGBA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGB5_A1", "GL_RGBA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGBA4", "GL_RGBA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_SRGB8_ALPHA8", "GL_RGBA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGBA8_SNORM", "GL_RGBA", "GL_BYTE" ],
+ [ "GL_RGBA4", "GL_RGBA", "GL_UNSIGNED_SHORT_4_4_4_4" ],
+ [ "GL_RGB10_A2", "GL_RGBA", "GL_UNSIGNED_INT_2_10_10_10_REV" ],
+ [ "GL_RGB5_A1", "GL_RGBA", "GL_UNSIGNED_INT_2_10_10_10_REV" ],
+ [ "GL_RGB5_A1", "GL_RGBA", "GL_UNSIGNED_SHORT_5_5_5_1" ],
+ [ "GL_RGBA16F", "GL_RGBA", "GL_HALF_FLOAT" ],
+ [ "GL_RGBA16F", "GL_RGBA", "GL_HALF_FLOAT_OES" ],
+ [ "GL_RGBA32F", "GL_RGBA", "GL_FLOAT" ],
+ [ "GL_RGBA16F", "GL_RGBA", "GL_FLOAT" ],
+ [ "GL_RGBA8UI", "GL_RGBA_INTEGER", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGBA8I", "GL_RGBA_INTEGER", "GL_BYTE" ],
+ [ "GL_RGBA16UI", "GL_RGBA_INTEGER", "GL_UNSIGNED_SHORT" ],
+ [ "GL_RGBA16I", "GL_RGBA_INTEGER", "GL_SHORT" ],
+ [ "GL_RGBA32UI", "GL_RGBA_INTEGER", "GL_UNSIGNED_INT" ],
+ [ "GL_RGBA32I", "GL_RGBA_INTEGER", "GL_INT" ],
+ [ "GL_RGB10_A2UI", "GL_RGBA_INTEGER", "GL_UNSIGNED_INT_2_10_10_10_REV" ],
+ [ "GL_RGB8", "GL_RGB", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGB565", "GL_RGB", "GL_UNSIGNED_BYTE" ],
+ [ "GL_SRGB8", "GL_RGB", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGB8_SNORM", "GL_RGB", "GL_BYTE" ],
+ [ "GL_RGB565", "GL_RGB", "GL_UNSIGNED_SHORT_5_6_5" ],
+ [ "GL_R11F_G11F_B10F", "GL_RGB", "GL_UNSIGNED_INT_10F_11F_11F_REV" ],
+ [ "GL_RGB9_E5", "GL_RGB", "GL_UNSIGNED_INT_5_9_9_9_REV" ],
+ [ "GL_RGB16F", "GL_RGB", "GL_HALF_FLOAT" ],
+ [ "GL_RGB16F", "GL_RGB", "GL_HALF_FLOAT_OES" ],
+ [ "GL_R11F_G11F_B10F", "GL_RGB", "GL_HALF_FLOAT" ],
+ [ "GL_R11F_G11F_B10F", "GL_RGB", "GL_HALF_FLOAT_OES" ],
+ [ "GL_RGB9_E5", "GL_RGB", "GL_HALF_FLOAT" ],
+ [ "GL_RGB9_E5", "GL_RGB", "GL_HALF_FLOAT_OES" ],
+ [ "GL_RGB32F", "GL_RGB", "GL_FLOAT" ],
+ [ "GL_RGB16F", "GL_RGB", "GL_FLOAT" ],
+ [ "GL_R11F_G11F_B10F", "GL_RGB", "GL_FLOAT" ],
+ [ "GL_RGB9_E5", "GL_RGB", "GL_FLOAT" ],
+ [ "GL_RGB8UI", "GL_RGB_INTEGER", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGB8I", "GL_RGB_INTEGER", "GL_BYTE" ],
+ [ "GL_RGB16UI", "GL_RGB_INTEGER", "GL_UNSIGNED_SHORT" ],
+ [ "GL_RGB16I", "GL_RGB_INTEGER", "GL_SHORT" ],
+ [ "GL_RGB32UI", "GL_RGB_INTEGER", "GL_UNSIGNED_INT" ],
+ [ "GL_RGB32I", "GL_RGB_INTEGER", "GL_INT" ],
+ [ "GL_RG8", "GL_RG", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RG8_SNORM", "GL_RG", "GL_BYTE" ],
+ [ "GL_RG16F", "GL_RG", "GL_HALF_FLOAT" ],
+ [ "GL_RG16F", "GL_RG", "GL_HALF_FLOAT_OES" ],
+ [ "GL_RG32F", "GL_RG", "GL_FLOAT" ],
+ [ "GL_RG16F", "GL_RG", "GL_FLOAT" ],
+ [ "GL_RG8UI", "GL_RG_INTEGER", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RG8I", "GL_RG_INTEGER", "GL_BYTE" ],
+ [ "GL_RG16UI", "GL_RG_INTEGER", "GL_UNSIGNED_SHORT" ],
+ [ "GL_RG16I", "GL_RG_INTEGER", "GL_SHORT" ],
+ [ "GL_RG32UI", "GL_RG_INTEGER", "GL_UNSIGNED_INT" ],
+ [ "GL_RG32I", "GL_RG_INTEGER", "GL_INT" ],
+ [ "GL_R8", "GL_RED", "GL_UNSIGNED_BYTE" ],
+ [ "GL_R8_SNORM", "GL_RED", "GL_BYTE" ],
+ [ "GL_R16F", "GL_RED", "GL_HALF_FLOAT" ],
+ [ "GL_R16F", "GL_RED", "GL_HALF_FLOAT_OES" ],
+ [ "GL_R32F", "GL_RED", "GL_FLOAT" ],
+ [ "GL_R16F", "GL_RED", "GL_FLOAT" ],
+ [ "GL_R8UI", "GL_RED_INTEGER", "GL_UNSIGNED_BYTE" ],
+ [ "GL_R8I", "GL_RED_INTEGER", "GL_BYTE" ],
+ [ "GL_R16UI", "GL_RED_INTEGER", "GL_UNSIGNED_SHORT" ],
+ [ "GL_R16I", "GL_RED_INTEGER", "GL_SHORT" ],
+ [ "GL_R32UI", "GL_RED_INTEGER", "GL_UNSIGNED_INT" ],
+ [ "GL_R32I", "GL_RED_INTEGER", "GL_INT" ]
+ ],
+ "Unsized formats":
+ [
+ [ "GL_RGBA", "GL_RGBA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGBA", "GL_RGBA", "GL_UNSIGNED_SHORT_4_4_4_4" ],
+ [ "GL_RGBA", "GL_RGBA", "GL_UNSIGNED_SHORT_5_5_5_1" ],
+ [ "GL_RGB", "GL_RGB", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGB", "GL_RGB", "GL_UNSIGNED_SHORT_5_6_5" ],
+ [ "GL_LUMINANCE_ALPHA", "GL_LUMINANCE_ALPHA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_LUMINANCE", "GL_LUMINANCE", "GL_UNSIGNED_BYTE" ],
+ [ "GL_ALPHA", "GL_ALPHA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_SRGB_ALPHA_EXT", "GL_SRGB_ALPHA_EXT", "GL_UNSIGNED_BYTE" ],
+ [ "GL_SRGB_EXT", "GL_SRGB_EXT", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RG", "GL_RG", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RG", "GL_RG", "GL_FLOAT" ],
+ [ "GL_RG", "GL_RG", "GL_HALF_FLOAT" ],
+ [ "GL_RG", "GL_RG", "GL_HALF_FLOAT_OES" ],
+ [ "GL_RED", "GL_RED", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RED", "GL_RED", "GL_FLOAT" ],
+ [ "GL_RED", "GL_RED", "GL_HALF_FLOAT" ],
+ [ "GL_RED", "GL_RED", "GL_HALF_FLOAT_OES" ],
+ [ "GL_DEPTH_STENCIL", "GL_DEPTH_STENCIL", "GL_UNSIGNED_INT_24_8" ]
+ ],
+ "Depth stencil formats":
+ [
+ [ "GL_DEPTH_COMPONENT16", "GL_DEPTH_COMPONENT", "GL_UNSIGNED_SHORT" ],
+ [ "GL_DEPTH_COMPONENT24", "GL_DEPTH_COMPONENT", "GL_UNSIGNED_INT" ],
+ [ "GL_DEPTH_COMPONENT16", "GL_DEPTH_COMPONENT", "GL_UNSIGNED_INT" ],
+ [ "GL_DEPTH_COMPONENT32F", "GL_DEPTH_COMPONENT", "GL_FLOAT" ],
+ [ "GL_DEPTH24_STENCIL8", "GL_DEPTH_STENCIL", "GL_UNSIGNED_INT_24_8" ],
+ [ "GL_DEPTH32F_STENCIL8", "GL_DEPTH_STENCIL", "GL_FLOAT_32_UNSIGNED_INT_24_8_REV" ]
+ ],
+ "From GL_EXT_sRGB":
+ [
+ [ "GL_SRGB8_ALPHA8_EXT", "GL_SRGB_ALPHA_EXT", "GL_UNSIGNED_BYTE" ],
+ [ "GL_SRGB8", "GL_SRGB_EXT", "GL_UNSIGNED_BYTE" ]
+ ],
+ "From GL_OES_texture_float":
+ [
+ [ "GL_RGBA", "GL_RGBA", "GL_FLOAT" ],
+ [ "GL_RGB", "GL_RGB", "GL_FLOAT" ],
+ [ "GL_LUMINANCE_ALPHA", "GL_LUMINANCE_ALPHA", "GL_FLOAT" ],
+ [ "GL_LUMINANCE", "GL_LUMINANCE", "GL_FLOAT" ],
+ [ "GL_ALPHA", "GL_ALPHA", "GL_FLOAT" ]
+ ],
+ "From GL_OES_texture_half_float":
+ [
+ [ "GL_RGBA", "GL_RGBA", "GL_HALF_FLOAT_OES" ],
+ [ "GL_RGB", "GL_RGB", "GL_HALF_FLOAT_OES" ],
+ [ "GL_LUMINANCE_ALPHA", "GL_LUMINANCE_ALPHA", "GL_HALF_FLOAT" ],
+ [ "GL_LUMINANCE_ALPHA", "GL_LUMINANCE_ALPHA", "GL_HALF_FLOAT_OES" ],
+ [ "GL_LUMINANCE", "GL_LUMINANCE", "GL_HALF_FLOAT" ],
+ [ "GL_LUMINANCE", "GL_LUMINANCE", "GL_HALF_FLOAT_OES" ],
+ [ "GL_ALPHA", "GL_ALPHA", "GL_HALF_FLOAT" ],
+ [ "GL_ALPHA", "GL_ALPHA", "GL_HALF_FLOAT_OES" ]
+ ],
+ "From GL_EXT_texture_format_BGRA8888":
+ [
+ [ "GL_BGRA_EXT", "GL_BGRA_EXT", "GL_UNSIGNED_BYTE" ]
+ ],
+ "From GL_EXT_texture_storage":
+ [
+ [ "GL_ALPHA8_EXT", "GL_ALPHA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_LUMINANCE8_EXT", "GL_LUMINANCE", "GL_UNSIGNED_BYTE" ],
+ [ "GL_LUMINANCE8_ALPHA8_EXT", "GL_LUMINANCE_ALPHA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_ALPHA32F_EXT", "GL_ALPHA", "GL_FLOAT" ],
+ [ "GL_LUMINANCE32F_EXT", "GL_LUMINANCE", "GL_FLOAT" ],
+ [ "GL_LUMINANCE_ALPHA32F_EXT", "GL_LUMINANCE_ALPHA", "GL_FLOAT" ],
+ [ "GL_ALPHA16F_EXT", "GL_ALPHA", "GL_HALF_FLOAT" ],
+ [ "GL_ALPHA16F_EXT", "GL_ALPHA", "GL_HALF_FLOAT_OES" ],
+ [ "GL_LUMINANCE16F_EXT", "GL_LUMINANCE", "GL_HALF_FLOAT" ],
+ [ "GL_LUMINANCE16F_EXT", "GL_LUMINANCE", "GL_HALF_FLOAT_OES" ],
+ [ "GL_LUMINANCE_ALPHA16F_EXT", "GL_LUMINANCE_ALPHA", "GL_HALF_FLOAT" ],
+ [ "GL_LUMINANCE_ALPHA16F_EXT", "GL_LUMINANCE_ALPHA", "GL_HALF_FLOAT_OES" ]
+ ],
+ "From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888":
+ [
+ [ "GL_BGRA8_EXT", "GL_BGRA_EXT", "GL_UNSIGNED_BYTE" ],
+ [ "GL_BGRA4_ANGLEX", "GL_BGRA_EXT", "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT" ],
+ [ "GL_BGRA4_ANGLEX", "GL_BGRA_EXT", "GL_UNSIGNED_BYTE" ],
+ [ "GL_BGR5_A1_ANGLEX", "GL_BGRA_EXT", "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT" ],
+ [ "GL_BGR5_A1_ANGLEX", "GL_BGRA_EXT", "GL_UNSIGNED_BYTE" ]
+ ],
+ "From GL_ANGLE_depth_texture and OES_depth_texture":
+ [
+ [ "GL_DEPTH_COMPONENT32_OES", "GL_DEPTH_COMPONENT", "GL_UNSIGNED_INT_24_8" ],
+ [ "GL_DEPTH_COMPONENT", "GL_DEPTH_COMPONENT", "GL_UNSIGNED_SHORT" ],
+ [ "GL_DEPTH_COMPONENT", "GL_DEPTH_COMPONENT", "GL_UNSIGNED_INT" ]
+ ],
+ "From GL_EXT_texture_norm16":
+ [
+ [ "GL_R16_EXT", "GL_RED", "GL_UNSIGNED_SHORT" ],
+ [ "GL_RG16_EXT", "GL_RG", "GL_UNSIGNED_SHORT" ],
+ [ "GL_RGB16_EXT", "GL_RGB", "GL_UNSIGNED_SHORT" ],
+ [ "GL_RGBA16_EXT", "GL_RGBA", "GL_UNSIGNED_SHORT" ],
+ [ "GL_R16_SNORM_EXT", "GL_RED", "GL_SHORT" ],
+ [ "GL_RG16_SNORM_EXT", "GL_RG", "GL_SHORT" ],
+ [ "GL_RGB16_SNORM_EXT", "GL_RGB", "GL_SHORT" ],
+ [ "GL_RGBA16_SNORM_EXT", "GL_RGBA", "GL_SHORT" ]
+ ]
+}
diff --git a/gfx/angle/src/libANGLE/features.h b/gfx/angle/src/libANGLE/features.h
new file mode 100755
index 000000000..ecf486dcf
--- /dev/null
+++ b/gfx/angle/src/libANGLE/features.h
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 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_
+
+#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
+
+// Program binary loading
+#if !defined(ANGLE_PROGRAM_BINARY_LOAD)
+#define ANGLE_PROGRAM_BINARY_LOAD 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
+
+#endif // LIBANGLE_FEATURES_H_
diff --git a/gfx/angle/src/libANGLE/format_map_autogen.cpp b/gfx/angle/src/libANGLE/format_map_autogen.cpp
new file mode 100644
index 000000000..707d38426
--- /dev/null
+++ b/gfx/angle/src/libANGLE/format_map_autogen.cpp
@@ -0,0 +1,1530 @@
+// 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_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_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_S3TC_DXT1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGB_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_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_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_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:
+ 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_RGB_INTEGER:
+ switch (type)
+ {
+ case GL_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB32I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16UI:
+ 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_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB8I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB32UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA_INTEGER:
+ switch (type)
+ {
+ case GL_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA32I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16UI:
+ 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_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_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA8I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA32UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_R11F_G11F_B10F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16_EXT:
+ 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_RGB:
+ case GL_RGB8:
+ case GL_RGB565:
+ case GL_SRGB8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT_5_6_5:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB:
+ case GL_RGB565:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB:
+ case GL_RGB16F:
+ case GL_R11F_G11F_B10F:
+ case GL_RGB9_E5:
+ 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_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB:
+ case GL_RGB32F:
+ case GL_RGB16F:
+ case GL_R11F_G11F_B10F:
+ case GL_RGB9_E5:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB8_SNORM:
+ 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;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE_ALPHA32F_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;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_ALPHA:
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ case GL_ALPHA16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ case GL_ALPHA32F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ case GL_ALPHA8_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;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB10_A2:
+ case GL_RGB5_A1:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16_SNORM_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA:
+ case GL_RGBA4:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA:
+ case GL_RGBA8:
+ case GL_RGB5_A1:
+ case GL_RGBA4:
+ case GL_SRGB8_ALPHA8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA:
+ case GL_RGBA16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA:
+ case GL_RGBA32F:
+ case GL_RGBA16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA8_SNORM:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA:
+ case GL_RGB5_A1:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE:
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE:
+ case GL_LUMINANCE16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE:
+ case GL_LUMINANCE32F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE:
+ case GL_LUMINANCE8_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;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG_INTEGER:
+ switch (type)
+ {
+ case GL_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG32I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16UI:
+ 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_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG8I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG32UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED_INTEGER:
+ switch (type)
+ {
+ case GL_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R32I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16UI:
+ 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_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_R8I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R32UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16_SNORM_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RED:
+ case GL_R32F:
+ case GL_R16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_RED:
+ case GL_R16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RED:
+ case GL_R16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RED:
+ case GL_R8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_R8_SNORM:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_DEPTH_COMPONENT:
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT16:
+ 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_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT32F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_DEPTH_STENCIL:
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_24_8:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_STENCIL:
+ case GL_DEPTH24_STENCIL8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH32F_STENCIL8:
+ 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_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_RG:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16_SNORM_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG:
+ case GL_RG32F:
+ case GL_RG16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG:
+ case GL_RG16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG:
+ case GL_RG16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG:
+ case GL_RG8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG8_SNORM:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ {
+ switch (internalFormat)
+ {
+ case GL_BGRA4_ANGLEX:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_BGRA8_EXT:
+ case GL_BGRA4_ANGLEX:
+ case GL_BGR5_A1_ANGLEX:
+ case GL_BGRA_EXT:
+ 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;
+ }
+ default:
+ break;
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return false;
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/format_map_data.json b/gfx/angle/src/libANGLE/format_map_data.json
new file mode 100644
index 000000000..3d6ad6c3c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/format_map_data.json
@@ -0,0 +1,130 @@
+{
+ "GL_RGBA": {
+ "GL_UNSIGNED_BYTE": "GL_RGBA8",
+ "GL_UNSIGNED_SHORT": "GL_RGBA16_EXT",
+ "GL_BYTE": "GL_RGBA8_SNORM",
+ "GL_SHORT": "GL_RGBA16_SNORM_EXT",
+ "GL_UNSIGNED_SHORT_4_4_4_4": "GL_RGBA4",
+ "GL_UNSIGNED_SHORT_5_5_5_1": "GL_RGB5_A1",
+ "GL_UNSIGNED_INT_2_10_10_10_REV": "GL_RGB10_A2",
+ "GL_FLOAT": "GL_RGBA32F",
+ "GL_HALF_FLOAT": "GL_RGBA16F",
+ "GL_HALF_FLOAT_OES": "GL_RGBA16F"
+ },
+ "GL_RGBA_INTEGER": {
+ "GL_UNSIGNED_BYTE": "GL_RGBA8UI",
+ "GL_BYTE": "GL_RGBA8I",
+ "GL_UNSIGNED_SHORT": "GL_RGBA16UI",
+ "GL_SHORT": "GL_RGBA16I",
+ "GL_UNSIGNED_INT": "GL_RGBA32UI",
+ "GL_INT": "GL_RGBA32I",
+ "GL_UNSIGNED_INT_2_10_10_10_REV": "GL_RGB10_A2UI"
+ },
+ "GL_RGB": {
+ "GL_UNSIGNED_BYTE": "GL_RGB8",
+ "GL_UNSIGNED_SHORT": "GL_RGB16_EXT",
+ "GL_BYTE": "GL_RGB8_SNORM",
+ "GL_SHORT": "GL_RGB16_SNORM_EXT",
+ "GL_UNSIGNED_SHORT_5_6_5": "GL_RGB565",
+ "GL_UNSIGNED_INT_10F_11F_11F_REV": "GL_R11F_G11F_B10F",
+ "GL_UNSIGNED_INT_5_9_9_9_REV": "GL_RGB9_E5",
+ "GL_FLOAT": "GL_RGB32F",
+ "GL_HALF_FLOAT": "GL_RGB16F",
+ "GL_HALF_FLOAT_OES": "GL_RGB16F"
+ },
+ "GL_RGB_INTEGER": {
+ "GL_UNSIGNED_BYTE": "GL_RGB8UI",
+ "GL_BYTE": "GL_RGB8I", "GL_UNSIGNED_SHORT": "GL_RGB16UI",
+ "GL_SHORT": "GL_RGB16I",
+ "GL_UNSIGNED_INT": "GL_RGB32UI",
+ "GL_INT": "GL_RGB32I"
+ },
+ "GL_RG": {
+ "GL_UNSIGNED_BYTE": "GL_RG8",
+ "GL_UNSIGNED_SHORT": "GL_RG16_EXT",
+ "GL_BYTE": "GL_RG8_SNORM",
+ "GL_SHORT": "GL_RG16_SNORM_EXT",
+ "GL_FLOAT": "GL_RG32F",
+ "GL_HALF_FLOAT": "GL_RG16F",
+ "GL_HALF_FLOAT_OES": "GL_RG16F"
+ },
+ "GL_RG_INTEGER": {
+ "GL_UNSIGNED_BYTE": "GL_RG8UI",
+ "GL_BYTE": "GL_RG8I",
+ "GL_UNSIGNED_SHORT": "GL_RG16UI",
+ "GL_SHORT": "GL_RG16I",
+ "GL_UNSIGNED_INT": "GL_RG32UI",
+ "GL_INT": "GL_RG32I"
+ },
+ "GL_RED": {
+ "GL_UNSIGNED_BYTE": "GL_R8",
+ "GL_UNSIGNED_SHORT": "GL_R16_EXT",
+ "GL_BYTE": "GL_R8_SNORM",
+ "GL_SHORT": "GL_R16_SNORM_EXT",
+ "GL_FLOAT": "GL_R32F",
+ "GL_HALF_FLOAT": "GL_R16F",
+ "GL_HALF_FLOAT_OES": "GL_R16F"
+ },
+ "GL_RED_INTEGER": {
+ "GL_UNSIGNED_BYTE": "GL_R8UI",
+ "GL_BYTE": "GL_R8I",
+ "GL_UNSIGNED_SHORT": "GL_R16UI",
+ "GL_SHORT": "GL_R16I",
+ "GL_UNSIGNED_INT": "GL_R32UI",
+ "GL_INT": "GL_R32I"
+ },
+ "GL_LUMINANCE_ALPHA": {
+ "GL_UNSIGNED_BYTE": "GL_LUMINANCE8_ALPHA8_EXT",
+ "GL_FLOAT": "GL_LUMINANCE_ALPHA32F_EXT",
+ "GL_HALF_FLOAT": "GL_LUMINANCE_ALPHA16F_EXT",
+ "GL_HALF_FLOAT_OES": "GL_LUMINANCE_ALPHA16F_EXT"
+ },
+ "GL_LUMINANCE": {
+ "GL_UNSIGNED_BYTE": "GL_LUMINANCE8_EXT",
+ "GL_FLOAT": "GL_LUMINANCE32F_EXT",
+ "GL_HALF_FLOAT": "GL_LUMINANCE16F_EXT",
+ "GL_HALF_FLOAT_OES": "GL_LUMINANCE16F_EXT"
+ },
+ "GL_ALPHA": {
+ "GL_UNSIGNED_BYTE": "GL_ALPHA8_EXT",
+ "GL_FLOAT": "GL_ALPHA32F_EXT",
+ "GL_HALF_FLOAT": "GL_ALPHA16F_EXT",
+ "GL_HALF_FLOAT_OES": "GL_ALPHA16F_EXT"
+ },
+ "GL_BGRA_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_BGRA8_EXT",
+ "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT": "GL_BGRA4_ANGLEX",
+ "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT": "GL_BGR5_A1_ANGLEX",
+ "GL_UNSIGNED_SHORT_5_6_5": "GL_BGR565_ANGLEX"
+ },
+ "GL_SRGB_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_SRGB8"
+ },
+ "GL_SRGB_ALPHA_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_SRGB8_ALPHA8"
+ },
+ "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_COMPRESSED_RGB_S3TC_DXT1_EXT"
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": {
+ "GL_UNSIGNED_BYTE": "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE"
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": {
+ "GL_UNSIGNED_BYTE": "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE"
+ },
+ "GL_DEPTH_COMPONENT": {
+ "GL_UNSIGNED_SHORT": "GL_DEPTH_COMPONENT16",
+ "GL_UNSIGNED_INT": "GL_DEPTH_COMPONENT32_OES",
+ "GL_FLOAT": "GL_DEPTH_COMPONENT32F"
+ },
+ "GL_STENCIL": {
+ "GL_UNSIGNED_BYTE": "GL_STENCIL_INDEX8"
+ },
+ "GL_DEPTH_STENCIL": {
+ "GL_UNSIGNED_INT_24_8": "GL_DEPTH24_STENCIL8",
+ "GL_FLOAT_32_UNSIGNED_INT_24_8_REV": "GL_DEPTH32F_STENCIL8"
+ }
+}
diff --git a/gfx/angle/src/libANGLE/formatutils.cpp b/gfx/angle/src/libANGLE/formatutils.cpp
new file mode 100755
index 000000000..2aa2e75d4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/formatutils.cpp
@@ -0,0 +1,1656 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// formatutils.cpp: Queries for GL image formats.
+
+#include "common/mathutil.h"
+#include "libANGLE/formatutils.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
+{
+typedef std::pair<GLenum, InternalFormat> InternalFormatInfoPair;
+typedef std::map<GLenum, InternalFormat> InternalFormatInfoMap;
+
+} // 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;
+}
+
+Type::Type()
+ : bytes(0),
+ bytesShift(0),
+ specialInterpretation(false)
+{
+}
+
+static Type GenTypeInfo(GLuint bytes, bool specialInterpretation)
+{
+ Type info;
+ info.bytes = bytes;
+ GLuint i = 0;
+ while ((1u << i) < bytes)
+ {
+ ++i;
+ }
+ info.bytesShift = i;
+ ASSERT((1u << info.bytesShift) == bytes);
+ info.specialInterpretation = specialInterpretation;
+ return info;
+}
+
+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;
+}
+
+template <GLuint minCoreGLMajorVersion, GLuint minCoreGLMinorVersion>
+static bool RequireES(const Version &clientVersion, const Extensions &)
+{
+ return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion);
+}
+
+// Pointer to a boolean memeber of the Extensions struct
+typedef bool(Extensions::*ExtensionBool);
+
+// 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;
+}
+
+// Special function for half float formats with three or four channels.
+static bool HalfFloatSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(3, 0) || extensions.textureHalfFloat;
+}
+
+static bool HalfFloatRenderableSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return HalfFloatSupport(clientVersion, extensions) && extensions.colorBufferHalfFloat;
+}
+
+// Special function for half float formats with one or two channels.
+static bool HalfFloatSupportRG(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(3, 0) || (extensions.textureHalfFloat && extensions.textureRG);
+}
+
+static bool HalfFloatRenderableSupportRG(const Version &clientVersion, const Extensions &extensions)
+{
+ return HalfFloatSupportRG(clientVersion, extensions) && extensions.colorBufferHalfFloat;
+}
+
+// Special function for float formats with three or four channels.
+static bool FloatSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(3, 0) || extensions.textureFloat;
+}
+
+static bool FloatRenderableSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ // We don't expose colorBufferFloat in ES2, but we silently support rendering to float.
+ return FloatSupport(clientVersion, extensions) &&
+ (extensions.colorBufferFloat || clientVersion == Version(2, 0));
+}
+
+// Special function for float formats with one or two channels.
+static bool FloatSupportRG(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(3, 0) || (extensions.textureFloat && extensions.textureRG);
+}
+
+static bool FloatRenderableSupportRG(const Version &clientVersion, const Extensions &extensions)
+{
+ // We don't expose colorBufferFloat in ES2, but we silently support rendering to float.
+ return FloatSupportRG(clientVersion, extensions) &&
+ (extensions.colorBufferFloat || clientVersion == Version(2, 0));
+}
+
+InternalFormat::InternalFormat()
+ : internalFormat(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),
+ format(GL_NONE),
+ type(GL_NONE),
+ componentType(GL_NONE),
+ colorEncoding(GL_NONE),
+ textureSupport(NeverSupported),
+ renderSupport(NeverSupported),
+ filterSupport(NeverSupported)
+{
+}
+
+bool InternalFormat::isLUMA() const
+{
+ return ((redBits + greenBits + blueBits + depthBits + stencilBits) == 0 &&
+ (luminanceBits + alphaBits) > 0);
+}
+
+GLenum InternalFormat::getReadPixelsFormat() const
+{
+ return format;
+}
+
+GLenum InternalFormat::getReadPixelsType() const
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ // 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
+ return GL_HALF_FLOAT_OES;
+
+ default:
+ return type;
+ }
+}
+
+Format::Format(GLenum internalFormat) : Format(GetInternalFormatInfo(internalFormat))
+{
+}
+
+Format::Format(const InternalFormat &internalFormat)
+ : info(&internalFormat), format(info->format), type(info->type), sized(true)
+{
+ ASSERT((info->pixelBytes > 0 && format != GL_NONE && type != GL_NONE) ||
+ internalFormat.format == GL_NONE);
+}
+
+Format::Format(GLenum internalFormat, GLenum format, GLenum type)
+ : info(nullptr), format(format), type(type), sized(false)
+{
+ const auto &plainInfo = GetInternalFormatInfo(internalFormat);
+ sized = plainInfo.pixelBytes > 0;
+ info = (sized ? &plainInfo : &GetInternalFormatInfo(GetSizedFormatInternal(format, type)));
+ ASSERT(format == GL_NONE || info->pixelBytes > 0);
+}
+
+Format::Format(const Format &other) = default;
+Format &Format::operator=(const Format &other) = default;
+
+GLenum Format::asSized() const
+{
+ return sized ? info->internalFormat : GetSizedFormatInternal(format, type);
+}
+
+bool Format::valid() const
+{
+ return info->format != GL_NONE;
+}
+
+// static
+bool Format::SameSized(const Format &a, const Format &b)
+{
+ return (a.info == b.info);
+}
+
+// static
+Format Format::Invalid()
+{
+ static Format invalid(GL_NONE, GL_NONE, GL_NONE);
+ return invalid;
+}
+
+bool InternalFormat::operator==(const InternalFormat &other) const
+{
+ // We assume there are no duplicates.
+ ASSERT((this == &other) == (internalFormat == other.internalFormat));
+ return internalFormat == other.internalFormat;
+}
+
+bool InternalFormat::operator!=(const InternalFormat &other) const
+{
+ // We assume there are no duplicates.
+ ASSERT((this != &other) == (internalFormat != other.internalFormat));
+ return internalFormat != other.internalFormat;
+}
+
+static void AddUnsizedFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ GLenum format,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction renderSupport,
+ InternalFormat::SupportCheckFunction filterSupport)
+{
+ InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ formatInfo.format = format;
+ formatInfo.textureSupport = textureSupport;
+ formatInfo.renderSupport = renderSupport;
+ formatInfo.filterSupport = filterSupport;
+ ASSERT(map->count(internalFormat) == 0);
+ (*map)[internalFormat] = formatInfo;
+}
+
+void AddRGBAFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ GLuint red,
+ GLuint green,
+ GLuint blue,
+ GLuint alpha,
+ GLuint shared,
+ GLenum format,
+ GLenum type,
+ GLenum componentType,
+ bool srgb,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction renderSupport,
+ InternalFormat::SupportCheckFunction filterSupport)
+{
+ InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ formatInfo.redBits = red;
+ formatInfo.greenBits = green;
+ formatInfo.blueBits = blue;
+ formatInfo.alphaBits = alpha;
+ formatInfo.sharedBits = shared;
+ formatInfo.pixelBytes = (red + green + blue + alpha + shared) / 8;
+ formatInfo.componentCount = ((red > 0) ? 1 : 0) + ((green > 0) ? 1 : 0) + ((blue > 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.renderSupport = renderSupport;
+ formatInfo.filterSupport = filterSupport;
+ ASSERT(map->count(internalFormat) == 0);
+ (*map)[internalFormat] = formatInfo;
+}
+
+static InternalFormat LUMAFormat(GLuint luminance, GLuint alpha, GLenum format, GLenum type, GLenum componentType,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction renderSupport,
+ InternalFormat::SupportCheckFunction filterSupport)
+{
+ InternalFormat formatInfo;
+ formatInfo.internalFormat = GetSizedFormatInternal(format, 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.renderSupport = renderSupport;
+ formatInfo.filterSupport = filterSupport;
+ return formatInfo;
+}
+
+void AddDepthStencilFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ GLuint depthBits,
+ GLuint stencilBits,
+ GLuint unusedBits,
+ GLenum format,
+ GLenum type,
+ GLenum componentType,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction renderSupport,
+ InternalFormat::SupportCheckFunction filterSupport)
+{
+ InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ 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.renderSupport = renderSupport;
+ formatInfo.filterSupport = filterSupport;
+ ASSERT(map->count(internalFormat) == 0);
+ (*map)[internalFormat] = formatInfo;
+}
+
+static InternalFormat CompressedFormat(GLuint compressedBlockWidth, GLuint compressedBlockHeight, GLuint compressedBlockSize,
+ GLuint componentCount, GLenum format, GLenum type, bool srgb,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction renderSupport,
+ InternalFormat::SupportCheckFunction filterSupport)
+{
+ InternalFormat formatInfo;
+ formatInfo.internalFormat = format;
+ formatInfo.compressedBlockWidth = compressedBlockWidth;
+ formatInfo.compressedBlockHeight = compressedBlockHeight;
+ formatInfo.pixelBytes = compressedBlockSize / 8;
+ formatInfo.componentCount = componentCount;
+ formatInfo.format = format;
+ formatInfo.type = type;
+ formatInfo.componentType = GL_UNSIGNED_NORMALIZED;
+ formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR);
+ formatInfo.compressed = true;
+ formatInfo.textureSupport = textureSupport;
+ formatInfo.renderSupport = renderSupport;
+ formatInfo.filterSupport = filterSupport;
+ return formatInfo;
+}
+
+static InternalFormatInfoMap BuildInternalFormatInfoMap()
+{
+ InternalFormatInfoMap map;
+
+ // From ES 3.0.1 spec, table 3.12
+ map.insert(InternalFormatInfoPair(GL_NONE, InternalFormat()));
+
+ // clang-format off
+
+ // | Internal format | R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Renderable | Filterable |
+ AddRGBAFormat(&map, GL_R8, 8, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureRG>, RequireESOrExt<3, 0, &Extensions::textureRG>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_R8_SNORM, 8, 0, 0, 0, 0, GL_RED, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RG8, 8, 8, 0, 0, 0, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureRG>, RequireESOrExt<3, 0, &Extensions::textureRG>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RG8_SNORM, 8, 8, 0, 0, 0, GL_RG, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB8, 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB8_SNORM, 8, 8, 8, 0, 0, GL_RGB, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB565, 5, 6, 5, 0, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA4, 4, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB5_A1, 5, 5, 5, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA8, 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA8_SNORM, 8, 8, 8, 8, 0, GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB10_A2, 10, 10, 10, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireES<3, 0>, RequireES<3, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB10_A2UI, 10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_SRGB8, 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, 0, &Extensions::sRGB>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_SRGB8_ALPHA8, 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, 0, &Extensions::sRGB>, RequireESOrExt<3, 0, &Extensions::sRGB>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB9_E5, 9, 9, 9, 0, 5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_R8I, 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R8UI, 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R16I, 16, 0, 0, 0, 0, GL_RED_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R16UI, 16, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R32I, 32, 0, 0, 0, 0, GL_RED_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R32UI, 32, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG8I, 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG8UI, 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG16I, 16, 16, 0, 0, 0, GL_RG_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG16UI, 16, 16, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG32I, 32, 32, 0, 0, 0, GL_RG_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R11F_G11F_B10F, 11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, RequireES<3, 0>, RequireExt<&Extensions::colorBufferFloat>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RG32UI, 32, 32, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB8I, 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB8UI, 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB16I, 16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB16UI, 16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB32I, 32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB32UI, 32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA8I, 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA8UI, 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA16I, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA16UI, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA32I, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA32UI, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+
+ AddRGBAFormat(&map, GL_BGRA8_EXT, 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_BGRA4_ANGLEX, 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_BGR5_A1_ANGLEX, 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
+
+ // Special format which is not really supported, so always false for all supports.
+ AddRGBAFormat(&map, GL_BGR565_ANGLEX, 5, 6, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported);
+
+ // Floating point renderability and filtering is provided by OES_texture_float and OES_texture_half_float
+ // | Internal format | D |S | Format | Type | Comp | SRGB | Texture supported | Renderable | Filterable |
+ // | | | | | | type | | | | |
+ AddRGBAFormat(&map, GL_R16F, 16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupportRG, HalfFloatRenderableSupportRG, RequireExt<&Extensions::textureHalfFloatLinear>);
+ AddRGBAFormat(&map, GL_RG16F, 16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupportRG, HalfFloatRenderableSupportRG, RequireExt<&Extensions::textureHalfFloatLinear>);
+ AddRGBAFormat(&map, GL_RGB16F, 16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupport, HalfFloatRenderableSupport, RequireExt<&Extensions::textureHalfFloatLinear>);
+ AddRGBAFormat(&map, GL_RGBA16F, 16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupport, HalfFloatRenderableSupport, RequireExt<&Extensions::textureHalfFloatLinear>);
+ AddRGBAFormat(&map, GL_R32F, 32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, FloatSupportRG, FloatRenderableSupportRG, RequireExt<&Extensions::textureFloatLinear> );
+ AddRGBAFormat(&map, GL_RG32F, 32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, FloatSupportRG, FloatRenderableSupportRG, RequireExt<&Extensions::textureFloatLinear> );
+ AddRGBAFormat(&map, GL_RGB32F, 32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, FloatSupport, FloatRenderableSupport, RequireExt<&Extensions::textureFloatLinear> );
+ AddRGBAFormat(&map, GL_RGBA32F, 32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, FloatSupport, FloatRenderableSupport, RequireExt<&Extensions::textureFloatLinear> );
+
+ // Depth stencil formats
+ // | Internal format | D |S | X | Format | Type | Component type | Supported | Renderable | Filterable |
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT16, 16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireES<2, 0>, RequireES<2, 0>, RequireESOrExt<3, 0, &Extensions::depthTextures>);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT24, 24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireES<3, 0>, RequireES<3, 0>, RequireESOrExt<3, 0, &Extensions::depthTextures>);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32F, 32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireES<3, 0>, RequireES<3, 0>, RequireESOrExt<3, 0, &Extensions::depthTextures>);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32_OES, 32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExtOrExt<&Extensions::depthTextures, &Extensions::depth32>, RequireExtOrExt<&Extensions::depthTextures, &Extensions::depth32>, AlwaysSupported );
+ AddDepthStencilFormat(&map, GL_DEPTH24_STENCIL8, 24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, 0, &Extensions::depthTextures>, RequireESOrExtOrExt<3, 0, &Extensions::depthTextures, &Extensions::packedDepthStencil>, AlwaysSupported );
+ AddDepthStencilFormat(&map, GL_DEPTH32F_STENCIL8, 32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireES<3, 0>, RequireES<3, 0>, AlwaysSupported );
+ // STENCIL_INDEX8 is special-cased, see around the bottom of the list.
+
+ // Luminance alpha formats
+ // | Internal format | | L | A | Format | Type | Component type | Supported | Renderable | Filterable |
+ map.insert(InternalFormatInfoPair(GL_ALPHA8_EXT, LUMAFormat( 0, 8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_LUMINANCE8_EXT, LUMAFormat( 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_ALPHA32F_EXT, LUMAFormat( 0, 32, GL_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_LUMINANCE32F_EXT, LUMAFormat(32, 0, GL_LUMINANCE, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_ALPHA16F_EXT, LUMAFormat( 0, 16, GL_ALPHA, GL_HALF_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_LUMINANCE16F_EXT, LUMAFormat(16, 0, GL_LUMINANCE, GL_HALF_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_LUMINANCE8_ALPHA8_EXT, LUMAFormat( 8, 8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA32F_EXT, LUMAFormat(32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA16F_EXT, LUMAFormat(16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
+
+ // Unsized formats
+ // | Internal format | Format | Supported | Renderable | Filterable |
+ AddUnsizedFormat(&map, GL_ALPHA, GL_ALPHA, RequireES<2, 0>, NeverSupported, AlwaysSupported);
+ AddUnsizedFormat(&map, GL_LUMINANCE, GL_LUMINANCE, RequireES<2, 0>, NeverSupported, AlwaysSupported);
+ AddUnsizedFormat(&map, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, RequireES<2, 0>, NeverSupported, AlwaysSupported);
+ AddUnsizedFormat(&map, GL_RED, GL_RED, RequireESOrExt<3, 0, &Extensions::textureRG>, NeverSupported, AlwaysSupported);
+ AddUnsizedFormat(&map, GL_RG, GL_RG, RequireESOrExt<3, 0, &Extensions::textureRG>, NeverSupported, AlwaysSupported);
+ AddUnsizedFormat(&map, GL_RGB, GL_RGB, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddUnsizedFormat(&map, GL_RGBA, GL_RGBA, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddUnsizedFormat(&map, GL_RED_INTEGER, GL_RED_INTEGER, RequireES<3, 0>, NeverSupported, NeverSupported );
+ AddUnsizedFormat(&map, GL_RG_INTEGER, GL_RG_INTEGER, RequireES<3, 0>, NeverSupported, NeverSupported );
+ AddUnsizedFormat(&map, GL_RGB_INTEGER, GL_RGB_INTEGER, RequireES<3, 0>, NeverSupported, NeverSupported );
+ AddUnsizedFormat(&map, GL_RGBA_INTEGER, GL_RGBA_INTEGER, RequireES<3, 0>, NeverSupported, NeverSupported );
+ AddUnsizedFormat(&map, GL_BGRA_EXT, GL_BGRA_EXT, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
+ AddUnsizedFormat(&map, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddUnsizedFormat(&map, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, RequireESOrExt<3, 0, &Extensions::packedDepthStencil>, RequireESOrExt<3, 0, &Extensions::packedDepthStencil>, AlwaysSupported);
+ AddUnsizedFormat(&map, GL_SRGB_EXT, GL_RGB, RequireESOrExt<3, 0, &Extensions::sRGB>, NeverSupported, AlwaysSupported);
+ AddUnsizedFormat(&map, GL_SRGB_ALPHA_EXT, GL_RGBA, RequireESOrExt<3, 0, &Extensions::sRGB>, RequireESOrExt<3, 0, &Extensions::sRGB>, AlwaysSupported);
+
+ // Compressed formats, From ES 3.0.1 spec, table 3.16
+ // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable |
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, true, RequireES<3, 0>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, true, RequireES<3, 0>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, true, RequireES<3, 0>, NeverSupported, AlwaysSupported)));
+
+ // From GL_EXT_texture_compression_dxt1
+ // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable |
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported)));
+
+ // From GL_ANGLE_texture_compression_dxt3
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported)));
+
+ // From GL_ANGLE_texture_compression_dxt5
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported)));
+
+ // From GL_OES_compressed_ETC1_RGB8_texture
+ map.insert(InternalFormatInfoPair(GL_ETC1_RGB8_OES, CompressedFormat(4, 4, 64, 3, GL_ETC1_RGB8_OES, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::compressedETC1RGB8Texture>, NeverSupported, AlwaysSupported)));
+
+ // From KHR_texture_compression_astc_hdr
+ // | Internal format | | W | H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable |
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_4x4_KHR, CompressedFormat( 4, 4, 128, 4, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_5x4_KHR, CompressedFormat( 5, 4, 128, 4, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_5x5_KHR, CompressedFormat( 5, 5, 128, 4, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_6x5_KHR, CompressedFormat( 6, 5, 128, 4, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_6x6_KHR, CompressedFormat( 6, 6, 128, 4, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_8x5_KHR, CompressedFormat( 8, 5, 128, 4, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_8x6_KHR, CompressedFormat( 8, 6, 128, 4, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_8x8_KHR, CompressedFormat( 8, 8, 128, 4, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_10x5_KHR, CompressedFormat(10, 5, 128, 4, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_10x6_KHR, CompressedFormat(10, 6, 128, 4, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_10x8_KHR, CompressedFormat(10, 8, 128, 4, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_10x10_KHR, CompressedFormat(10, 10, 128, 4, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_12x10_KHR, CompressedFormat(12, 10, 128, 4, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_12x12_KHR, CompressedFormat(12, 12, 128, 4, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, CompressedFormat( 4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, CompressedFormat( 5, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, CompressedFormat( 5, 5, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, CompressedFormat( 6, 5, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, CompressedFormat( 6, 6, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, CompressedFormat( 8, 5, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, CompressedFormat( 8, 6, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, CompressedFormat( 8, 8, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, CompressedFormat(10, 5, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, CompressedFormat(10, 6, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, CompressedFormat(10, 8, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, CompressedFormat(10, 10, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, CompressedFormat(12, 10, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, CompressedFormat(12, 12, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+
+ // 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 |D |S |X | Format | Type | Component type | Supported | Renderable | Filterable |
+ AddDepthStencilFormat(&map, GL_STENCIL_INDEX8, 0, 8, 0, GL_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2, 0>, RequireES<2, 0>, NeverSupported);
+
+ // From GL_ANGLE_lossy_etc_decode
+ map.insert(InternalFormatInfoPair(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, CompressedFormat(4, 4, 64, 3, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported)));
+
+ // From GL_EXT_texture_norm16
+ // | Internal format | R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Renderable | Filterable |
+ AddRGBAFormat(&map, GL_R16_EXT, 16, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, RequireExt<&Extensions::textureNorm16>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_R16_SNORM_EXT, 16, 0, 0, 0, 0, GL_RED, GL_SHORT, GL_SIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RG16_EXT, 16, 16, 0, 0, 0, GL_RG, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, RequireExt<&Extensions::textureNorm16>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RG16_SNORM_EXT, 16, 16, 0, 0, 0, GL_RG, GL_SHORT, GL_SIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB16_EXT, 16, 16, 16, 0, 0, GL_RGB, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB16_SNORM_EXT, 16, 16, 16, 0, 0, GL_RGB, GL_SHORT, GL_SIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA16_EXT, 16, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, RequireExt<&Extensions::textureNorm16>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA16_SNORM_EXT, 16, 16, 16, 16, 0, GL_RGBA, GL_SHORT, GL_SIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, NeverSupported, AlwaysSupported);
+
+ // clang-format on
+
+ return map;
+}
+
+static const InternalFormatInfoMap &GetInternalFormatMap()
+{
+ static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap();
+ return formatMap;
+}
+
+static FormatSet BuildAllSizedInternalFormatSet()
+{
+ FormatSet result;
+
+ for (auto iter : GetInternalFormatMap())
+ {
+ if (iter.second.pixelBytes > 0)
+ {
+ // TODO(jmadill): Fix this hack.
+ if (iter.first == GL_BGR565_ANGLEX)
+ continue;
+
+ result.insert(iter.first);
+ }
+ }
+
+ return result;
+}
+
+const Type &GetTypeInfo(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_BYTE:
+ {
+ static const Type info = GenTypeInfo(1, false);
+ return info;
+ }
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ case GL_HALF_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ {
+ static const Type info = GenTypeInfo(2, false);
+ return info;
+ }
+ case GL_UNSIGNED_INT:
+ case GL_INT:
+ case GL_FLOAT:
+ {
+ static const Type info = GenTypeInfo(4, false);
+ return info;
+ }
+ 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 const Type info = GenTypeInfo(2, true);
+ return info;
+ }
+ 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 const Type info = GenTypeInfo(4, true);
+ return info;
+ }
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ {
+ static const Type info = GenTypeInfo(8, true);
+ return info;
+ }
+ default:
+ {
+ static const Type defaultInfo;
+ return defaultInfo;
+ }
+ }
+}
+
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat)
+{
+ const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
+ auto iter = formatMap.find(internalFormat);
+ if (iter != formatMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ static const InternalFormat defaultInternalFormat;
+ return defaultInternalFormat;
+ }
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLsizei width,
+ GLint alignment,
+ GLint rowLength) const
+{
+ // Compressed images do not use pack/unpack parameters.
+ if (compressed)
+ {
+ ASSERT(rowLength == 0);
+ return computeCompressedImageSize(Extents(width, 1, 1));
+ }
+
+ CheckedNumeric<GLuint> checkedWidth(rowLength > 0 ? rowLength : width);
+ CheckedNumeric<GLuint> checkedRowBytes = checkedWidth * pixelBytes;
+
+ ASSERT(alignment > 0 && isPow2(alignment));
+ CheckedNumeric<GLuint> checkedAlignment(alignment);
+ auto aligned = rx::roundUp(checkedRowBytes, checkedAlignment);
+ ANGLE_TRY_CHECKED_MATH(aligned);
+ return aligned.ValueOrDie();
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLsizei height,
+ GLint imageHeight,
+ GLuint rowPitch)
+{
+ GLuint rows =
+ (imageHeight > 0 ? static_cast<GLuint>(imageHeight) : static_cast<GLuint>(height));
+ CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
+
+ auto depthPitch = checkedRowPitch * rows;
+ ANGLE_TRY_CHECKED_MATH(depthPitch);
+ return depthPitch.ValueOrDie();
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLsizei width,
+ GLsizei height,
+ GLint alignment,
+ GLint rowLength,
+ GLint imageHeight) const
+{
+ GLuint rowPitch = 0;
+ ANGLE_TRY_RESULT(computeRowPitch(width, alignment, rowLength), rowPitch);
+ return computeDepthPitch(height, imageHeight, rowPitch);
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeCompressedImageSize(const Extents &size) const
+{
+ CheckedNumeric<GLuint> checkedWidth(size.width);
+ CheckedNumeric<GLuint> checkedHeight(size.height);
+ CheckedNumeric<GLuint> checkedDepth(size.depth);
+ CheckedNumeric<GLuint> checkedBlockWidth(compressedBlockWidth);
+ CheckedNumeric<GLuint> checkedBlockHeight(compressedBlockHeight);
+
+ ASSERT(compressed);
+ auto numBlocksWide = (checkedWidth + checkedBlockWidth - 1u) / checkedBlockWidth;
+ auto numBlocksHigh = (checkedHeight + checkedBlockHeight - 1u) / checkedBlockHeight;
+ auto bytes = numBlocksWide * numBlocksHigh * pixelBytes * checkedDepth;
+ ANGLE_TRY_CHECKED_MATH(bytes);
+ return bytes.ValueOrDie();
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeSkipBytes(GLuint rowPitch,
+ GLuint depthPitch,
+ const PixelStoreStateBase &state,
+ bool is3D) 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(pixelBytes);
+ auto checkedSkipImagesBytes = checkedSkipImages * checkedDepthPitch;
+ if (!is3D)
+ {
+ checkedSkipImagesBytes = 0;
+ }
+ auto skipBytes = checkedSkipImagesBytes + checkedSkipRows * checkedRowPitch +
+ checkedSkipPixels * checkedPixelBytes;
+ ANGLE_TRY_CHECKED_MATH(skipBytes);
+ return skipBytes.ValueOrDie();
+}
+
+ErrorOrResult<GLuint> InternalFormat::computePackUnpackEndByte(const Extents &size,
+ const PixelStoreStateBase &state,
+ bool is3D) const
+{
+ GLuint rowPitch = 0;
+ ANGLE_TRY_RESULT(computeRowPitch(size.width, state.alignment, state.rowLength),
+ rowPitch);
+
+ GLuint depthPitch = 0;
+ if (is3D)
+ {
+ ANGLE_TRY_RESULT(computeDepthPitch(size.height, state.imageHeight, rowPitch), depthPitch);
+ }
+
+ CheckedNumeric<GLuint> checkedCopyBytes = 0;
+ if (compressed)
+ {
+ ANGLE_TRY_RESULT(computeCompressedImageSize(size), checkedCopyBytes);
+ }
+ else if (size.height != 0 && (!is3D || size.depth != 0))
+ {
+ CheckedNumeric<GLuint> bytes = pixelBytes;
+ checkedCopyBytes += size.width * bytes;
+
+ CheckedNumeric<GLuint> heightMinusOne = size.height - 1;
+ checkedCopyBytes += heightMinusOne * rowPitch;
+
+ if (is3D)
+ {
+ CheckedNumeric<GLuint> depthMinusOne = size.depth - 1;
+ checkedCopyBytes += depthMinusOne * depthPitch;
+ }
+ }
+
+ CheckedNumeric<GLuint> checkedSkipBytes = 0;
+ ANGLE_TRY_RESULT(computeSkipBytes(rowPitch, depthPitch, state, is3D),
+ checkedSkipBytes);
+
+ CheckedNumeric<GLuint> endByte = checkedCopyBytes + checkedSkipBytes;
+
+ ANGLE_TRY_CHECKED_MATH(endByte);
+ return endByte.ValueOrDie();
+}
+
+GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type)
+{
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
+ if (formatInfo.pixelBytes > 0)
+ {
+ return internalFormat;
+ }
+ return GetSizedFormatInternal(internalFormat, type);
+}
+
+const FormatSet &GetAllSizedInternalFormats()
+{
+ static 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;
+ }
+}
+
+VertexFormatType GetVertexFormatType(GLenum type, GLboolean normalized, GLuint components, bool pureInteger)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ switch (components)
+ {
+ case 1:
+ if (pureInteger)
+ return VERTEX_FORMAT_SBYTE1_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SBYTE1_NORM;
+ return VERTEX_FORMAT_SBYTE1;
+ case 2:
+ if (pureInteger)
+ return VERTEX_FORMAT_SBYTE2_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SBYTE2_NORM;
+ return VERTEX_FORMAT_SBYTE2;
+ case 3:
+ if (pureInteger)
+ return VERTEX_FORMAT_SBYTE3_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SBYTE3_NORM;
+ return VERTEX_FORMAT_SBYTE3;
+ case 4:
+ if (pureInteger)
+ return VERTEX_FORMAT_SBYTE4_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SBYTE4_NORM;
+ return VERTEX_FORMAT_SBYTE4;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ switch (components)
+ {
+ case 1:
+ if (pureInteger)
+ return VERTEX_FORMAT_UBYTE1_INT;
+ if (normalized)
+ return VERTEX_FORMAT_UBYTE1_NORM;
+ return VERTEX_FORMAT_UBYTE1;
+ case 2:
+ if (pureInteger)
+ return VERTEX_FORMAT_UBYTE2_INT;
+ if (normalized)
+ return VERTEX_FORMAT_UBYTE2_NORM;
+ return VERTEX_FORMAT_UBYTE2;
+ case 3:
+ if (pureInteger)
+ return VERTEX_FORMAT_UBYTE3_INT;
+ if (normalized)
+ return VERTEX_FORMAT_UBYTE3_NORM;
+ return VERTEX_FORMAT_UBYTE3;
+ case 4:
+ if (pureInteger)
+ return VERTEX_FORMAT_UBYTE4_INT;
+ if (normalized)
+ return VERTEX_FORMAT_UBYTE4_NORM;
+ return VERTEX_FORMAT_UBYTE4;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ case GL_SHORT:
+ switch (components)
+ {
+ case 1:
+ if (pureInteger)
+ return VERTEX_FORMAT_SSHORT1_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SSHORT1_NORM;
+ return VERTEX_FORMAT_SSHORT1;
+ case 2:
+ if (pureInteger)
+ return VERTEX_FORMAT_SSHORT2_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SSHORT2_NORM;
+ return VERTEX_FORMAT_SSHORT2;
+ case 3:
+ if (pureInteger)
+ return VERTEX_FORMAT_SSHORT3_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SSHORT3_NORM;
+ return VERTEX_FORMAT_SSHORT3;
+ case 4:
+ if (pureInteger)
+ return VERTEX_FORMAT_SSHORT4_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SSHORT4_NORM;
+ return VERTEX_FORMAT_SSHORT4;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ switch (components)
+ {
+ case 1:
+ if (pureInteger)
+ return VERTEX_FORMAT_USHORT1_INT;
+ if (normalized)
+ return VERTEX_FORMAT_USHORT1_NORM;
+ return VERTEX_FORMAT_USHORT1;
+ case 2:
+ if (pureInteger)
+ return VERTEX_FORMAT_USHORT2_INT;
+ if (normalized)
+ return VERTEX_FORMAT_USHORT2_NORM;
+ return VERTEX_FORMAT_USHORT2;
+ case 3:
+ if (pureInteger)
+ return VERTEX_FORMAT_USHORT3_INT;
+ if (normalized)
+ return VERTEX_FORMAT_USHORT3_NORM;
+ return VERTEX_FORMAT_USHORT3;
+ case 4:
+ if (pureInteger)
+ return VERTEX_FORMAT_USHORT4_INT;
+ if (normalized)
+ return VERTEX_FORMAT_USHORT4_NORM;
+ return VERTEX_FORMAT_USHORT4;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ case GL_INT:
+ switch (components)
+ {
+ case 1:
+ if (pureInteger)
+ return VERTEX_FORMAT_SINT1_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SINT1_NORM;
+ return VERTEX_FORMAT_SINT1;
+ case 2:
+ if (pureInteger)
+ return VERTEX_FORMAT_SINT2_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SINT2_NORM;
+ return VERTEX_FORMAT_SINT2;
+ case 3:
+ if (pureInteger)
+ return VERTEX_FORMAT_SINT3_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SINT3_NORM;
+ return VERTEX_FORMAT_SINT3;
+ case 4:
+ if (pureInteger)
+ return VERTEX_FORMAT_SINT4_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SINT4_NORM;
+ return VERTEX_FORMAT_SINT4;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ switch (components)
+ {
+ case 1:
+ if (pureInteger)
+ return VERTEX_FORMAT_UINT1_INT;
+ if (normalized)
+ return VERTEX_FORMAT_UINT1_NORM;
+ return VERTEX_FORMAT_UINT1;
+ case 2:
+ if (pureInteger)
+ return VERTEX_FORMAT_UINT2_INT;
+ if (normalized)
+ return VERTEX_FORMAT_UINT2_NORM;
+ return VERTEX_FORMAT_UINT2;
+ case 3:
+ if (pureInteger)
+ return VERTEX_FORMAT_UINT3_INT;
+ if (normalized)
+ return VERTEX_FORMAT_UINT3_NORM;
+ return VERTEX_FORMAT_UINT3;
+ case 4:
+ if (pureInteger)
+ return VERTEX_FORMAT_UINT4_INT;
+ if (normalized)
+ return VERTEX_FORMAT_UINT4_NORM;
+ return VERTEX_FORMAT_UINT4;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ case GL_FLOAT:
+ switch (components)
+ {
+ case 1:
+ return VERTEX_FORMAT_FLOAT1;
+ case 2:
+ return VERTEX_FORMAT_FLOAT2;
+ case 3:
+ return VERTEX_FORMAT_FLOAT3;
+ case 4:
+ return VERTEX_FORMAT_FLOAT4;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ case GL_HALF_FLOAT:
+ switch (components)
+ {
+ case 1:
+ return VERTEX_FORMAT_HALF1;
+ case 2:
+ return VERTEX_FORMAT_HALF2;
+ case 3:
+ return VERTEX_FORMAT_HALF3;
+ case 4:
+ return VERTEX_FORMAT_HALF4;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ case GL_FIXED:
+ switch (components)
+ {
+ case 1:
+ return VERTEX_FORMAT_FIXED1;
+ case 2:
+ return VERTEX_FORMAT_FIXED2;
+ case 3:
+ return VERTEX_FORMAT_FIXED3;
+ case 4:
+ return VERTEX_FORMAT_FIXED4;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ case GL_INT_2_10_10_10_REV:
+ if (pureInteger)
+ return VERTEX_FORMAT_SINT210_INT;
+ if (normalized)
+ return VERTEX_FORMAT_SINT210_NORM;
+ return VERTEX_FORMAT_SINT210;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ if (pureInteger)
+ return VERTEX_FORMAT_UINT210_INT;
+ if (normalized)
+ return VERTEX_FORMAT_UINT210_NORM;
+ return VERTEX_FORMAT_UINT210;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return VERTEX_FORMAT_UBYTE1;
+}
+
+VertexFormatType GetVertexFormatType(const VertexAttribute &attrib)
+{
+ return GetVertexFormatType(attrib.type, attrib.normalized, attrib.size, attrib.pureInteger);
+}
+
+VertexFormatType GetVertexFormatType(const VertexAttribute &attrib, GLenum currentValueType)
+{
+ if (!attrib.enabled)
+ {
+ return GetVertexFormatType(currentValueType, GL_FALSE, 4, (currentValueType != GL_FLOAT));
+ }
+ return GetVertexFormatType(attrib);
+}
+
+const VertexFormat &GetVertexFormatFromType(VertexFormatType vertexFormatType)
+{
+ switch (vertexFormatType)
+ {
+ case VERTEX_FORMAT_SBYTE1:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SBYTE1_NORM:
+ {
+ static const VertexFormat format(GL_BYTE, GL_TRUE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SBYTE2:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SBYTE2_NORM:
+ {
+ static const VertexFormat format(GL_BYTE, GL_TRUE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SBYTE3:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SBYTE3_NORM:
+ {
+ static const VertexFormat format(GL_BYTE, GL_TRUE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SBYTE4:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SBYTE4_NORM:
+ {
+ static const VertexFormat format(GL_BYTE, GL_TRUE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UBYTE1:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UBYTE1_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UBYTE2:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UBYTE2_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UBYTE3:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UBYTE3_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UBYTE4:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UBYTE4_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SSHORT1:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SSHORT1_NORM:
+ {
+ static const VertexFormat format(GL_SHORT, GL_TRUE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SSHORT2:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SSHORT2_NORM:
+ {
+ static const VertexFormat format(GL_SHORT, GL_TRUE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SSHORT3:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SSHORT3_NORM:
+ {
+ static const VertexFormat format(GL_SHORT, GL_TRUE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SSHORT4:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SSHORT4_NORM:
+ {
+ static const VertexFormat format(GL_SHORT, GL_TRUE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_USHORT1:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_USHORT1_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_USHORT2:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_USHORT2_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_USHORT3:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_USHORT3_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_USHORT4:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_USHORT4_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT1:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT1_NORM:
+ {
+ static const VertexFormat format(GL_INT, GL_TRUE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT2:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT2_NORM:
+ {
+ static const VertexFormat format(GL_INT, GL_TRUE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT3:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT3_NORM:
+ {
+ static const VertexFormat format(GL_INT, GL_TRUE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT4:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT4_NORM:
+ {
+ static const VertexFormat format(GL_INT, GL_TRUE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT1:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT1_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT2:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT2_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT3:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT3_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT4:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT4_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SBYTE1_INT:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 1, true);
+ return format;
+ }
+ case VERTEX_FORMAT_SBYTE2_INT:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 2, true);
+ return format;
+ }
+ case VERTEX_FORMAT_SBYTE3_INT:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 3, true);
+ return format;
+ }
+ case VERTEX_FORMAT_SBYTE4_INT:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 4, true);
+ return format;
+ }
+ case VERTEX_FORMAT_UBYTE1_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 1, true);
+ return format;
+ }
+ case VERTEX_FORMAT_UBYTE2_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 2, true);
+ return format;
+ }
+ case VERTEX_FORMAT_UBYTE3_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 3, true);
+ return format;
+ }
+ case VERTEX_FORMAT_UBYTE4_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 4, true);
+ return format;
+ }
+ case VERTEX_FORMAT_SSHORT1_INT:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 1, true);
+ return format;
+ }
+ case VERTEX_FORMAT_SSHORT2_INT:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 2, true);
+ return format;
+ }
+ case VERTEX_FORMAT_SSHORT3_INT:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 3, true);
+ return format;
+ }
+ case VERTEX_FORMAT_SSHORT4_INT:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 4, true);
+ return format;
+ }
+ case VERTEX_FORMAT_USHORT1_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 1, true);
+ return format;
+ }
+ case VERTEX_FORMAT_USHORT2_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 2, true);
+ return format;
+ }
+ case VERTEX_FORMAT_USHORT3_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 3, true);
+ return format;
+ }
+ case VERTEX_FORMAT_USHORT4_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 4, true);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT1_INT:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 1, true);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT2_INT:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 2, true);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT3_INT:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 3, true);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT4_INT:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 4, true);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT1_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 1, true);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT2_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 2, true);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT3_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 3, true);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT4_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 4, true);
+ return format;
+ }
+ case VERTEX_FORMAT_FIXED1:
+ {
+ static const VertexFormat format(GL_FIXED, GL_FALSE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_FIXED2:
+ {
+ static const VertexFormat format(GL_FIXED, GL_FALSE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_FIXED3:
+ {
+ static const VertexFormat format(GL_FIXED, GL_FALSE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_FIXED4:
+ {
+ static const VertexFormat format(GL_FIXED, GL_FALSE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_HALF1:
+ {
+ static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_HALF2:
+ {
+ static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_HALF3:
+ {
+ static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_HALF4:
+ {
+ static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_FLOAT1:
+ {
+ static const VertexFormat format(GL_FLOAT, GL_FALSE, 1, false);
+ return format;
+ }
+ case VERTEX_FORMAT_FLOAT2:
+ {
+ static const VertexFormat format(GL_FLOAT, GL_FALSE, 2, false);
+ return format;
+ }
+ case VERTEX_FORMAT_FLOAT3:
+ {
+ static const VertexFormat format(GL_FLOAT, GL_FALSE, 3, false);
+ return format;
+ }
+ case VERTEX_FORMAT_FLOAT4:
+ {
+ static const VertexFormat format(GL_FLOAT, GL_FALSE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT210:
+ {
+ static const VertexFormat format(GL_INT_2_10_10_10_REV, GL_FALSE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT210:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT210_NORM:
+ {
+ static const VertexFormat format(GL_INT_2_10_10_10_REV, GL_TRUE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT210_NORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, false);
+ return format;
+ }
+ case VERTEX_FORMAT_SINT210_INT:
+ {
+ static const VertexFormat format(GL_INT_2_10_10_10_REV, GL_FALSE, 4, true);
+ return format;
+ }
+ case VERTEX_FORMAT_UINT210_INT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, true);
+ return format;
+ }
+ default:
+ {
+ static const VertexFormat format(GL_NONE, GL_FALSE, 0, false);
+ return format;
+ }
+ }
+}
+
+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);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/formatutils.h b/gfx/angle/src/libANGLE/formatutils.h
new file mode 100755
index 000000000..d6f9402d4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/formatutils.h
@@ -0,0 +1,301 @@
+//
+// Copyright (c) 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 <cstddef>
+#include <stdint.h>
+
+#include "angle_gl.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+
+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();
+
+ GLuint bytes;
+ GLuint bytesShift; // Bit shift by this value to effectively divide/multiply by "bytes" in a more optimal way
+ bool specialInterpretation;
+};
+const Type &GetTypeInfo(GLenum type);
+
+struct InternalFormat
+{
+ InternalFormat();
+
+ ErrorOrResult<GLuint> computeRowPitch(GLsizei width,
+ GLint alignment,
+ GLint rowLength) const;
+ static ErrorOrResult<GLuint> computeDepthPitch(GLsizei height,
+ GLint imageHeight,
+ GLuint rowPitch);
+ ErrorOrResult<GLuint> computeDepthPitch(GLsizei width,
+ GLsizei height,
+ GLint alignment,
+ GLint rowLength,
+ GLint imageHeight) const;
+
+ ErrorOrResult<GLuint> computeCompressedImageSize(const Extents &size) const;
+
+ ErrorOrResult<GLuint> computeSkipBytes(GLuint rowPitch,
+ GLuint depthPitch,
+ const PixelStoreStateBase &state,
+ bool is3D) const;
+
+ ErrorOrResult<GLuint> computePackUnpackEndByte(const Extents &size,
+ const PixelStoreStateBase &state,
+ bool is3D) const;
+
+ bool isLUMA() const;
+ GLenum getReadPixelsFormat() const;
+ GLenum getReadPixelsType() const;
+
+ bool operator==(const InternalFormat &other) const;
+ bool operator!=(const InternalFormat &other) const;
+
+ GLenum internalFormat;
+
+ 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;
+
+ GLenum format;
+ GLenum type;
+
+ GLenum componentType;
+ GLenum colorEncoding;
+
+ typedef bool (*SupportCheckFunction)(const Version &, const Extensions &);
+ SupportCheckFunction textureSupport;
+ SupportCheckFunction renderSupport;
+ SupportCheckFunction filterSupport;
+};
+
+// A "Format" is either a sized format, or an {unsized format, type} combination.
+struct Format
+{
+ // Sized types only.
+ explicit Format(GLenum internalFormat);
+ explicit Format(const InternalFormat &internalFormat);
+
+ // Sized or unsized types.
+ Format(GLenum internalFormat, GLenum format, GLenum type);
+
+ Format(const Format &other);
+ Format &operator=(const Format &other);
+
+ GLenum asSized() const;
+ bool valid() const;
+
+ static Format Invalid();
+ static bool SameSized(const Format &a, const Format &b);
+
+ // This is the sized info.
+ const InternalFormat *info;
+ GLenum format;
+ GLenum type;
+ bool sized;
+};
+
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat);
+
+GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type);
+
+typedef std::set<GLenum> FormatSet;
+const FormatSet &GetAllSizedInternalFormats();
+
+// 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);
+
+enum VertexFormatType
+{
+ VERTEX_FORMAT_INVALID,
+ VERTEX_FORMAT_SBYTE1,
+ VERTEX_FORMAT_SBYTE1_NORM,
+ VERTEX_FORMAT_SBYTE2,
+ VERTEX_FORMAT_SBYTE2_NORM,
+ VERTEX_FORMAT_SBYTE3,
+ VERTEX_FORMAT_SBYTE3_NORM,
+ VERTEX_FORMAT_SBYTE4,
+ VERTEX_FORMAT_SBYTE4_NORM,
+ VERTEX_FORMAT_UBYTE1,
+ VERTEX_FORMAT_UBYTE1_NORM,
+ VERTEX_FORMAT_UBYTE2,
+ VERTEX_FORMAT_UBYTE2_NORM,
+ VERTEX_FORMAT_UBYTE3,
+ VERTEX_FORMAT_UBYTE3_NORM,
+ VERTEX_FORMAT_UBYTE4,
+ VERTEX_FORMAT_UBYTE4_NORM,
+ VERTEX_FORMAT_SSHORT1,
+ VERTEX_FORMAT_SSHORT1_NORM,
+ VERTEX_FORMAT_SSHORT2,
+ VERTEX_FORMAT_SSHORT2_NORM,
+ VERTEX_FORMAT_SSHORT3,
+ VERTEX_FORMAT_SSHORT3_NORM,
+ VERTEX_FORMAT_SSHORT4,
+ VERTEX_FORMAT_SSHORT4_NORM,
+ VERTEX_FORMAT_USHORT1,
+ VERTEX_FORMAT_USHORT1_NORM,
+ VERTEX_FORMAT_USHORT2,
+ VERTEX_FORMAT_USHORT2_NORM,
+ VERTEX_FORMAT_USHORT3,
+ VERTEX_FORMAT_USHORT3_NORM,
+ VERTEX_FORMAT_USHORT4,
+ VERTEX_FORMAT_USHORT4_NORM,
+ VERTEX_FORMAT_SINT1,
+ VERTEX_FORMAT_SINT1_NORM,
+ VERTEX_FORMAT_SINT2,
+ VERTEX_FORMAT_SINT2_NORM,
+ VERTEX_FORMAT_SINT3,
+ VERTEX_FORMAT_SINT3_NORM,
+ VERTEX_FORMAT_SINT4,
+ VERTEX_FORMAT_SINT4_NORM,
+ VERTEX_FORMAT_UINT1,
+ VERTEX_FORMAT_UINT1_NORM,
+ VERTEX_FORMAT_UINT2,
+ VERTEX_FORMAT_UINT2_NORM,
+ VERTEX_FORMAT_UINT3,
+ VERTEX_FORMAT_UINT3_NORM,
+ VERTEX_FORMAT_UINT4,
+ VERTEX_FORMAT_UINT4_NORM,
+ VERTEX_FORMAT_SBYTE1_INT,
+ VERTEX_FORMAT_SBYTE2_INT,
+ VERTEX_FORMAT_SBYTE3_INT,
+ VERTEX_FORMAT_SBYTE4_INT,
+ VERTEX_FORMAT_UBYTE1_INT,
+ VERTEX_FORMAT_UBYTE2_INT,
+ VERTEX_FORMAT_UBYTE3_INT,
+ VERTEX_FORMAT_UBYTE4_INT,
+ VERTEX_FORMAT_SSHORT1_INT,
+ VERTEX_FORMAT_SSHORT2_INT,
+ VERTEX_FORMAT_SSHORT3_INT,
+ VERTEX_FORMAT_SSHORT4_INT,
+ VERTEX_FORMAT_USHORT1_INT,
+ VERTEX_FORMAT_USHORT2_INT,
+ VERTEX_FORMAT_USHORT3_INT,
+ VERTEX_FORMAT_USHORT4_INT,
+ VERTEX_FORMAT_SINT1_INT,
+ VERTEX_FORMAT_SINT2_INT,
+ VERTEX_FORMAT_SINT3_INT,
+ VERTEX_FORMAT_SINT4_INT,
+ VERTEX_FORMAT_UINT1_INT,
+ VERTEX_FORMAT_UINT2_INT,
+ VERTEX_FORMAT_UINT3_INT,
+ VERTEX_FORMAT_UINT4_INT,
+ VERTEX_FORMAT_FIXED1,
+ VERTEX_FORMAT_FIXED2,
+ VERTEX_FORMAT_FIXED3,
+ VERTEX_FORMAT_FIXED4,
+ VERTEX_FORMAT_HALF1,
+ VERTEX_FORMAT_HALF2,
+ VERTEX_FORMAT_HALF3,
+ VERTEX_FORMAT_HALF4,
+ VERTEX_FORMAT_FLOAT1,
+ VERTEX_FORMAT_FLOAT2,
+ VERTEX_FORMAT_FLOAT3,
+ VERTEX_FORMAT_FLOAT4,
+ VERTEX_FORMAT_SINT210,
+ VERTEX_FORMAT_UINT210,
+ VERTEX_FORMAT_SINT210_NORM,
+ VERTEX_FORMAT_UINT210_NORM,
+ VERTEX_FORMAT_SINT210_INT,
+ VERTEX_FORMAT_UINT210_INT,
+};
+
+typedef std::vector<VertexFormatType> InputLayout;
+
+struct VertexFormat : angle::NonCopyable
+{
+ VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn);
+
+ GLenum type;
+ GLboolean normalized;
+ GLuint components;
+ bool pureInteger;
+};
+
+VertexFormatType GetVertexFormatType(GLenum type, GLboolean normalized, GLuint components, bool pureInteger);
+VertexFormatType GetVertexFormatType(const VertexAttribute &attrib);
+VertexFormatType GetVertexFormatType(const VertexAttribute &attrib, GLenum currentValueType);
+const VertexFormat &GetVertexFormatFromType(VertexFormatType vertexFormatType);
+
+// Implemented in format_map_autogen.cpp
+bool ValidES3Format(GLenum format);
+bool ValidES3Type(GLenum type);
+bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat);
+
+// Implemented in es3_copy_conversion_table_autogen.cpp
+bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat);
+
+} // namespace gl
+
+#endif // LIBANGLE_FORMATUTILS_H_
diff --git a/gfx/angle/src/libANGLE/gen_copy_conversion_table.py b/gfx/angle/src/libANGLE/gen_copy_conversion_table.py
new file mode 100644
index 000000000..f2c9603d5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/gen_copy_conversion_table.py
@@ -0,0 +1,91 @@
+#!/usr/bin/python
+# 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.
+#
+# gen_copy_conversion_table.py:
+# Code generation for ES3 valid copy conversions table format map.
+
+from datetime import date
+import sys
+
+sys.path.append('renderer')
+import angle_format
+
+template_cpp = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}.
+//
+// Copyright {copyright_year} The ANGLE Project 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)
+ {{
+{texture_format_cases} default:
+ break;
+ }}
+
+ return false;
+}}
+
+}} // namespace gl
+"""
+
+template_format_case = """ case {texture_format}:
+ switch (framebufferFormat)
+ {{
+{framebuffer_format_cases} return true;
+ default:
+ break;
+ }}
+ break;
+
+"""
+
+template_simple_case = """ case {key}:
+"""
+
+def parse_texture_format_case(texture_format, framebuffer_formats):
+ framebuffer_format_cases = ""
+ for framebuffer_format in sorted(framebuffer_formats):
+ framebuffer_format_cases += template_simple_case.format(key = framebuffer_format)
+ return template_format_case.format(
+ texture_format = texture_format, framebuffer_format_cases = framebuffer_format_cases)
+
+data_source_name = 'es3_copy_conversion_formats.json'
+
+json_data = angle_format.load_json(data_source_name)
+
+format_map = {}
+
+for description, data in json_data.iteritems():
+ for texture_format, framebuffer_format in data:
+ if texture_format not in format_map:
+ format_map[texture_format] = []
+ format_map[texture_format] += [ framebuffer_format ]
+
+texture_format_cases = ""
+
+for texture_format, framebuffer_formats in sorted(format_map.iteritems()):
+ texture_format_cases += parse_texture_format_case(texture_format, framebuffer_formats)
+
+with open('es3_copy_conversion_table_autogen.cpp', 'wt') as out_file:
+ output_cpp = template_cpp.format(
+ script_name = sys.argv[0],
+ data_source_name = data_source_name,
+ copyright_year = date.today().year,
+ texture_format_cases = texture_format_cases)
+ out_file.write(output_cpp)
+ out_file.close()
diff --git a/gfx/angle/src/libANGLE/gen_format_map.py b/gfx/angle/src/libANGLE/gen_format_map.py
new file mode 100644
index 000000000..b67f42784
--- /dev/null
+++ b/gfx/angle/src/libANGLE/gen_format_map.py
@@ -0,0 +1,187 @@
+#!/usr/bin/python
+# 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.
+#
+# gen_format_map.py:
+# Code generation for GL format map. The format map matches between
+# {format,type} and internal format.
+
+from datetime import date
+import sys
+
+sys.path.append('renderer')
+import angle_format
+
+template_cpp = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}.
+// ES3 format info from {es3_data_source_name}.
+//
+// Copyright {copyright_year} The ANGLE Project 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)
+ {{
+{format_cases} case GL_NONE:
+ return GL_NONE;
+
+ default:
+ break;
+ }}
+
+ return GL_NONE;
+}}
+
+bool ValidES3Format(GLenum format)
+{{
+ switch (format)
+ {{
+{es3_format_cases} return true;
+
+ default:
+ return false;
+ }}
+}}
+
+bool ValidES3Type(GLenum type)
+{{
+ switch (type)
+ {{
+{es3_type_cases} return true;
+
+ default:
+ return false;
+ }}
+}}
+
+bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat)
+{{
+ ASSERT(ValidES3Format(format) && ValidES3Type(type));
+
+ switch (format)
+ {{
+{es3_combo_cases} default:
+ UNREACHABLE();
+ break;
+ }}
+
+ return false;
+}}
+
+}} // namespace gl
+"""
+
+template_format_case = """ case {format}:
+ switch (type)
+ {{
+{type_cases} default:
+ break;
+ }}
+ break;
+
+"""
+
+template_simple_case = """ case {key}:
+ return {result};
+"""
+
+template_es3_combo_type_case = """ case {type}:
+ {{
+ switch (internalFormat)
+ {{
+{internal_format_cases} return true;
+ default:
+ break;
+ }}
+ break;
+ }}
+"""
+
+def parse_type_case(type, result):
+ return template_simple_case.format(
+ key = type, result = result)
+
+def parse_format_case(format, type_map):
+ type_cases = ""
+ for type, internal_format in sorted(type_map.iteritems()):
+ type_cases += parse_type_case(type, internal_format)
+ return template_format_case.format(
+ format = format, type_cases = type_cases)
+
+input_script = 'format_map_data.json'
+
+format_map = angle_format.load_json(input_script)
+
+format_cases = ""
+
+for format, type_map in sorted(format_map.iteritems()):
+ format_cases += parse_format_case(format, type_map)
+
+combo_data_file = 'es3_format_type_combinations.json'
+es3_combo_data = angle_format.load_json(combo_data_file)
+combo_data = [combo for sublist in es3_combo_data.values() for combo in sublist]
+
+types = set()
+formats = set()
+combos = {}
+
+for internal_format, format, type in combo_data:
+ types.update([type])
+ formats.update([format])
+ if format not in combos:
+ combos[format] = {}
+ if type not in combos[format]:
+ combos[format][type] = [internal_format]
+ else:
+ combos[format][type] += [internal_format]
+
+es3_format_cases = ""
+
+for format in sorted(formats):
+ es3_format_cases += " case " + format + ":\n"
+
+es3_type_cases = ""
+
+for type in sorted(types):
+ es3_type_cases += " case " + type + ":\n"
+
+es3_combo_cases = ""
+
+for format, type_combos in combos.iteritems():
+ this_type_cases = ""
+ for type, combos in type_combos.iteritems():
+ internal_format_cases = ""
+ for internal_format in combos:
+ internal_format_cases += " case " + internal_format + ":\n"
+
+ this_type_cases += template_es3_combo_type_case.format(
+ type = type, internal_format_cases = internal_format_cases)
+
+ es3_combo_cases += template_format_case.format(
+ format = format, type_cases = this_type_cases)
+
+with open('format_map_autogen.cpp', 'wt') as out_file:
+ output_cpp = template_cpp.format(
+ script_name = sys.argv[0],
+ data_source_name = input_script,
+ es3_data_source_name = combo_data_file,
+ copyright_year = date.today().year,
+ format_cases = format_cases,
+ es3_format_cases = es3_format_cases,
+ es3_type_cases = es3_type_cases,
+ es3_combo_cases = es3_combo_cases)
+ out_file.write(output_cpp)
+ out_file.close()
diff --git a/gfx/angle/src/libANGLE/histogram_macros.h b/gfx/angle/src/libANGLE/histogram_macros.h
new file mode 100755
index 000000000..d1c952a6b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/histogram_macros.h
@@ -0,0 +1,107 @@
+//
+// 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/Platform.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(\
+ 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(name, sample)
+
+#define ANGLE_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \
+ ANGLEPlatformCurrent()->histogramEnumeration(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(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 ScopedHistogramTimer##key \
+ { \
+ public: \
+ ScopedHistogramTimer##key() : constructed_(ANGLEPlatformCurrent()->currentTime()) {} \
+ ~ScopedHistogramTimer##key() \
+ { \
+ if (constructed_ == 0) \
+ return; \
+ double elapsed = ANGLEPlatformCurrent()->currentTime() - 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 // BASE_METRICS_HISTOGRAM_MACROS_H_
diff --git a/gfx/angle/src/libANGLE/moz.build b/gfx/angle/src/libANGLE/moz.build
new file mode 100755
index 000000000..0a2a4437f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/moz.build
@@ -0,0 +1,407 @@
+
+#
+# WARNING WARNING WARNING
+#
+# This file is generated by generate_mozbuild.py (from
+# https://github.com/mozilla/angle). Do not modify it without also modifying
+# generate_mozbuild.py.
+#
+# WARNING WARNING WARNING
+#
+UNIFIED_SOURCES += [
+ '../common/angleutils.cpp',
+ '../common/debug.cpp',
+ '../common/event_tracer.cpp',
+ '../common/Float16ToFloat32.cpp',
+ '../common/mathutil.cpp',
+ '../common/MemoryBuffer.cpp',
+ '../common/string_utils.cpp',
+ '../common/tls.cpp',
+ '../common/utilities.cpp',
+ '../compiler/preprocessor/DiagnosticsBase.cpp',
+ '../compiler/preprocessor/DirectiveHandlerBase.cpp',
+ '../compiler/preprocessor/DirectiveParser.cpp',
+ '../compiler/preprocessor/ExpressionParser.cpp',
+ '../compiler/preprocessor/Input.cpp',
+ '../compiler/preprocessor/Lexer.cpp',
+ '../compiler/preprocessor/Macro.cpp',
+ '../compiler/preprocessor/MacroExpander.cpp',
+ '../compiler/preprocessor/Preprocessor.cpp',
+ '../compiler/preprocessor/Token.cpp',
+ '../compiler/preprocessor/Tokenizer.cpp',
+ '../compiler/translator/AddAndTrueToLoopCondition.cpp',
+ '../compiler/translator/AddDefaultReturnStatements.cpp',
+ '../compiler/translator/ArrayReturnValueToOutParameter.cpp',
+ '../compiler/translator/ASTMetadataHLSL.cpp',
+ '../compiler/translator/blocklayout.cpp',
+ '../compiler/translator/blocklayoutHLSL.cpp',
+ '../compiler/translator/BreakVariableAliasingInInnerLoops.cpp',
+ '../compiler/translator/BuiltInFunctionEmulator.cpp',
+ '../compiler/translator/BuiltInFunctionEmulatorGLSL.cpp',
+ '../compiler/translator/BuiltInFunctionEmulatorHLSL.cpp',
+ '../compiler/translator/Cache.cpp',
+ '../compiler/translator/CallDAG.cpp',
+ '../compiler/translator/CodeGen.cpp',
+ '../compiler/translator/Compiler.cpp',
+ '../compiler/translator/ConstantUnion.cpp',
+ '../compiler/translator/DeferGlobalInitializers.cpp',
+ '../compiler/translator/Diagnostics.cpp',
+ '../compiler/translator/DirectiveHandler.cpp',
+ '../compiler/translator/EmulatePrecision.cpp',
+ '../compiler/translator/ExpandIntegerPowExpressions.cpp',
+ '../compiler/translator/ExtensionGLSL.cpp',
+ '../compiler/translator/FlagStd140Structs.cpp',
+ '../compiler/translator/ForLoopUnroll.cpp',
+ '../compiler/translator/InfoSink.cpp',
+ '../compiler/translator/Initialize.cpp',
+ '../compiler/translator/InitializeDll.cpp',
+ '../compiler/translator/InitializeParseContext.cpp',
+ '../compiler/translator/InitializeVariables.cpp',
+ '../compiler/translator/Intermediate.cpp',
+ '../compiler/translator/IntermNode.cpp',
+ '../compiler/translator/IntermNodePatternMatcher.cpp',
+ '../compiler/translator/intermOut.cpp',
+ '../compiler/translator/IntermTraverse.cpp',
+ '../compiler/translator/LoopInfo.cpp',
+ '../compiler/translator/Operator.cpp',
+ '../compiler/translator/OutputESSL.cpp',
+ '../compiler/translator/OutputGLSL.cpp',
+ '../compiler/translator/OutputGLSLBase.cpp',
+ '../compiler/translator/OutputHLSL.cpp',
+ '../compiler/translator/ParseContext.cpp',
+ '../compiler/translator/PoolAlloc.cpp',
+ '../compiler/translator/PruneEmptyDeclarations.cpp',
+ '../compiler/translator/QualifierTypes.cpp',
+ '../compiler/translator/RecordConstantPrecision.cpp',
+ '../compiler/translator/RegenerateStructNames.cpp',
+ '../compiler/translator/RemoveDynamicIndexing.cpp',
+ '../compiler/translator/RemoveInvariantDeclaration.cpp',
+ '../compiler/translator/RemovePow.cpp',
+ '../compiler/translator/RemoveSwitchFallThrough.cpp',
+ '../compiler/translator/RewriteDoWhile.cpp',
+ '../compiler/translator/RewriteElseBlocks.cpp',
+ '../compiler/translator/RewriteUnaryMinusOperatorInt.cpp',
+ '../compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp',
+ '../compiler/translator/SearchSymbol.cpp',
+ '../compiler/translator/SeparateArrayInitialization.cpp',
+ '../compiler/translator/SeparateDeclarations.cpp',
+ '../compiler/translator/SeparateExpressionsReturningArrays.cpp',
+ '../compiler/translator/ShaderVars.cpp',
+ '../compiler/translator/SimplifyLoopConditions.cpp',
+ '../compiler/translator/SplitSequenceOperator.cpp',
+ '../compiler/translator/StructureHLSL.cpp',
+ '../compiler/translator/SymbolTable.cpp',
+ '../compiler/translator/TextureFunctionHLSL.cpp',
+ '../compiler/translator/TranslatorESSL.cpp',
+ '../compiler/translator/TranslatorGLSL.cpp',
+ '../compiler/translator/TranslatorHLSL.cpp',
+ '../compiler/translator/Types.cpp',
+ '../compiler/translator/UnfoldShortCircuitAST.cpp',
+ '../compiler/translator/UnfoldShortCircuitToIf.cpp',
+ '../compiler/translator/UniformHLSL.cpp',
+ '../compiler/translator/UseInterfaceBlockFields.cpp',
+ '../compiler/translator/util.cpp',
+ '../compiler/translator/UtilsHLSL.cpp',
+ '../compiler/translator/ValidateGlobalInitializer.cpp',
+ '../compiler/translator/ValidateLimitations.cpp',
+ '../compiler/translator/ValidateMaxParameters.cpp',
+ '../compiler/translator/ValidateOutputs.cpp',
+ '../compiler/translator/ValidateSwitch.cpp',
+ '../compiler/translator/VariableInfo.cpp',
+ '../compiler/translator/VariablePacker.cpp',
+ '../compiler/translator/VersionGLSL.cpp',
+ '../image_util/copyimage.cpp',
+ '../image_util/imageformats.cpp',
+ '../image_util/loadimage.cpp',
+ '../image_util/loadimage_etc.cpp',
+ '../third_party/compiler/ArrayBoundsClamper.cpp',
+ '../third_party/murmurhash/MurmurHash3.cpp',
+ '../third_party/systeminfo/SystemInfo.cpp',
+ 'angletypes.cpp',
+ 'AttributeMap.cpp',
+ 'Buffer.cpp',
+ 'Caps.cpp',
+ 'Compiler.cpp',
+ 'Config.cpp',
+ 'Context.cpp',
+ 'ContextState.cpp',
+ 'Debug.cpp',
+ 'Device.cpp',
+ 'Error.cpp',
+ 'es3_copy_conversion_table_autogen.cpp',
+ 'Fence.cpp',
+ 'format_map_autogen.cpp',
+ 'formatutils.cpp',
+ 'Framebuffer.cpp',
+ 'FramebufferAttachment.cpp',
+ 'HandleAllocator.cpp',
+ 'HandleRangeAllocator.cpp',
+ 'Image.cpp',
+ 'ImageIndex.cpp',
+ 'IndexRangeCache.cpp',
+ 'Path.cpp',
+ 'Platform.cpp',
+ 'Program.cpp',
+ 'Query.cpp',
+ 'queryconversions.cpp',
+ 'queryutils.cpp',
+ 'Renderbuffer.cpp',
+ 'renderer/ContextImpl.cpp',
+ 'renderer/d3d/BufferD3D.cpp',
+ 'renderer/d3d/CompilerD3D.cpp',
+ 'renderer/d3d/d3d9/Blit9.cpp',
+ 'renderer/d3d/d3d9/Buffer9.cpp',
+ 'renderer/d3d/d3d9/Context9.cpp',
+ 'renderer/d3d/d3d9/DebugAnnotator9.cpp',
+ 'renderer/d3d/d3d9/Fence9.cpp',
+ 'renderer/d3d/d3d9/formatutils9.cpp',
+ 'renderer/d3d/d3d9/Framebuffer9.cpp',
+ 'renderer/d3d/d3d9/Image9.cpp',
+ 'renderer/d3d/d3d9/IndexBuffer9.cpp',
+ 'renderer/d3d/d3d9/NativeWindow9.cpp',
+ 'renderer/d3d/d3d9/Query9.cpp',
+ 'renderer/d3d/d3d9/Renderer9.cpp',
+ 'renderer/d3d/d3d9/renderer9_utils.cpp',
+ 'renderer/d3d/d3d9/RenderTarget9.cpp',
+ 'renderer/d3d/d3d9/ShaderExecutable9.cpp',
+ 'renderer/d3d/d3d9/StateManager9.cpp',
+ 'renderer/d3d/d3d9/SwapChain9.cpp',
+ 'renderer/d3d/d3d9/TextureStorage9.cpp',
+ 'renderer/d3d/d3d9/VertexBuffer9.cpp',
+ 'renderer/d3d/d3d9/VertexDeclarationCache.cpp',
+ 'renderer/d3d/DeviceD3D.cpp',
+ 'renderer/d3d/DynamicHLSL.cpp',
+ 'renderer/d3d/EGLImageD3D.cpp',
+ 'renderer/d3d/FramebufferD3D.cpp',
+ 'renderer/d3d/ImageD3D.cpp',
+ 'renderer/d3d/IndexBuffer.cpp',
+ 'renderer/d3d/IndexDataManager.cpp',
+ 'renderer/d3d/NativeWindowD3D.cpp',
+ 'renderer/d3d/ProgramD3D.cpp',
+ 'renderer/d3d/RenderbufferD3D.cpp',
+ 'renderer/d3d/RendererD3D.cpp',
+ 'renderer/d3d/RenderTargetD3D.cpp',
+ 'renderer/d3d/ShaderD3D.cpp',
+ 'renderer/d3d/ShaderExecutableD3D.cpp',
+ 'renderer/d3d/SurfaceD3D.cpp',
+ 'renderer/d3d/SwapChainD3D.cpp',
+ 'renderer/d3d/TextureD3D.cpp',
+ 'renderer/d3d/VaryingPacking.cpp',
+ 'renderer/d3d/VertexBuffer.cpp',
+ 'renderer/d3d/VertexDataManager.cpp',
+ 'renderer/DeviceImpl.cpp',
+ 'renderer/DisplayImpl.cpp',
+ 'renderer/driver_utils.cpp',
+ 'renderer/Format_table_autogen.cpp',
+ 'renderer/gl/BlitGL.cpp',
+ 'renderer/gl/BufferGL.cpp',
+ 'renderer/gl/CompilerGL.cpp',
+ 'renderer/gl/ContextGL.cpp',
+ 'renderer/gl/DisplayGL.cpp',
+ 'renderer/gl/FenceNVGL.cpp',
+ 'renderer/gl/FenceSyncGL.cpp',
+ 'renderer/gl/formatutilsgl.cpp',
+ 'renderer/gl/FramebufferGL.cpp',
+ 'renderer/gl/FunctionsGL.cpp',
+ 'renderer/gl/PathGL.cpp',
+ 'renderer/gl/ProgramGL.cpp',
+ 'renderer/gl/QueryGL.cpp',
+ 'renderer/gl/RenderbufferGL.cpp',
+ 'renderer/gl/RendererGL.cpp',
+ 'renderer/gl/renderergl_utils.cpp',
+ 'renderer/gl/SamplerGL.cpp',
+ 'renderer/gl/ShaderGL.cpp',
+ 'renderer/gl/StateManagerGL.cpp',
+ 'renderer/gl/SurfaceGL.cpp',
+ 'renderer/gl/TextureGL.cpp',
+ 'renderer/gl/TransformFeedbackGL.cpp',
+ 'renderer/gl/VertexArrayGL.cpp',
+ 'renderer/gl/wgl/D3DTextureSurfaceWGL.cpp',
+ 'renderer/gl/wgl/DisplayWGL.cpp',
+ 'renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp',
+ 'renderer/gl/wgl/FunctionsWGL.cpp',
+ 'renderer/gl/wgl/PbufferSurfaceWGL.cpp',
+ 'renderer/gl/wgl/wgl_utils.cpp',
+ 'renderer/gl/wgl/WindowSurfaceWGL.cpp',
+ 'renderer/load_functions_table_autogen.cpp',
+ 'renderer/null/BufferNULL.cpp',
+ 'renderer/null/CompilerNULL.cpp',
+ 'renderer/null/ContextNULL.cpp',
+ 'renderer/null/DeviceNULL.cpp',
+ 'renderer/null/DisplayNULL.cpp',
+ 'renderer/null/FenceNVNULL.cpp',
+ 'renderer/null/FenceSyncNULL.cpp',
+ 'renderer/null/FramebufferNULL.cpp',
+ 'renderer/null/ImageNULL.cpp',
+ 'renderer/null/PathNULL.cpp',
+ 'renderer/null/ProgramNULL.cpp',
+ 'renderer/null/QueryNULL.cpp',
+ 'renderer/null/RenderbufferNULL.cpp',
+ 'renderer/null/SamplerNULL.cpp',
+ 'renderer/null/ShaderNULL.cpp',
+ 'renderer/null/SurfaceNULL.cpp',
+ 'renderer/null/TextureNULL.cpp',
+ 'renderer/null/TransformFeedbackNULL.cpp',
+ 'renderer/null/VertexArrayNULL.cpp',
+ 'renderer/renderer_utils.cpp',
+ 'renderer/SurfaceImpl.cpp',
+ 'renderer/TextureImpl.cpp',
+ 'renderer/vulkan/BufferVk.cpp',
+ 'renderer/vulkan/CompilerVk.cpp',
+ 'renderer/vulkan/ContextVk.cpp',
+ 'renderer/vulkan/DeviceVk.cpp',
+ 'renderer/vulkan/DisplayVk.cpp',
+ 'renderer/vulkan/FenceNVVk.cpp',
+ 'renderer/vulkan/FenceSyncVk.cpp',
+ 'renderer/vulkan/FramebufferVk.cpp',
+ 'renderer/vulkan/ImageVk.cpp',
+ 'renderer/vulkan/ProgramVk.cpp',
+ 'renderer/vulkan/QueryVk.cpp',
+ 'renderer/vulkan/RenderbufferVk.cpp',
+ 'renderer/vulkan/RendererVk.cpp',
+ 'renderer/vulkan/SamplerVk.cpp',
+ 'renderer/vulkan/ShaderVk.cpp',
+ 'renderer/vulkan/SurfaceVk.cpp',
+ 'renderer/vulkan/TextureVk.cpp',
+ 'renderer/vulkan/TransformFeedbackVk.cpp',
+ 'renderer/vulkan/VertexArrayVk.cpp',
+ 'ResourceManager.cpp',
+ 'Sampler.cpp',
+ 'Shader.cpp',
+ 'signal_utils.cpp',
+ 'State.cpp',
+ 'Stream.cpp',
+ 'Surface.cpp',
+ 'Texture.cpp',
+ 'Thread.cpp',
+ 'TransformFeedback.cpp',
+ 'Uniform.cpp',
+ 'validationEGL.cpp',
+ 'validationES.cpp',
+ 'validationES2.cpp',
+ 'validationES3.cpp',
+ 'validationES31.cpp',
+ 'VertexArray.cpp',
+ 'VertexAttribute.cpp',
+]
+SOURCES += [
+ '../compiler/translator/EmulateGLFragColorBroadcast.cpp',
+ '../compiler/translator/glslang_lex.cpp',
+ '../compiler/translator/glslang_tab.cpp',
+ '../compiler/translator/RewriteTexelFetchOffset.cpp',
+ '../compiler/translator/ShaderLang.cpp',
+ 'Display.cpp',
+ 'renderer/d3d/DisplayD3D.cpp',
+ 'renderer/d3d/HLSLCompiler.cpp',
+]
+if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
+ UNIFIED_SOURCES += [
+ 'renderer/d3d/d3d11/Blit11.cpp',
+ 'renderer/d3d/d3d11/Buffer11.cpp',
+ 'renderer/d3d/d3d11/Clear11.cpp',
+ 'renderer/d3d/d3d11/Context11.cpp',
+ 'renderer/d3d/d3d11/DebugAnnotator11.cpp',
+ 'renderer/d3d/d3d11/dxgi_format_map_autogen.cpp',
+ 'renderer/d3d/d3d11/dxgi_support_table.cpp',
+ 'renderer/d3d/d3d11/Fence11.cpp',
+ 'renderer/d3d/d3d11/formatutils11.cpp',
+ 'renderer/d3d/d3d11/Framebuffer11.cpp',
+ 'renderer/d3d/d3d11/Image11.cpp',
+ 'renderer/d3d/d3d11/IndexBuffer11.cpp',
+ 'renderer/d3d/d3d11/InputLayoutCache.cpp',
+ 'renderer/d3d/d3d11/PixelTransfer11.cpp',
+ 'renderer/d3d/d3d11/Query11.cpp',
+ 'renderer/d3d/d3d11/Renderer11.cpp',
+ 'renderer/d3d/d3d11/renderer11_utils.cpp',
+ 'renderer/d3d/d3d11/RenderStateCache.cpp',
+ 'renderer/d3d/d3d11/RenderTarget11.cpp',
+ 'renderer/d3d/d3d11/ShaderExecutable11.cpp',
+ 'renderer/d3d/d3d11/StateManager11.cpp',
+ 'renderer/d3d/d3d11/StreamProducerNV12.cpp',
+ 'renderer/d3d/d3d11/texture_format_table.cpp',
+ 'renderer/d3d/d3d11/texture_format_table_autogen.cpp',
+ 'renderer/d3d/d3d11/TextureStorage11.cpp',
+ 'renderer/d3d/d3d11/TransformFeedback11.cpp',
+ 'renderer/d3d/d3d11/Trim11.cpp',
+ 'renderer/d3d/d3d11/VertexArray11.cpp',
+ 'renderer/d3d/d3d11/VertexBuffer11.cpp',
+ ]
+if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
+ SOURCES += [
+ 'renderer/d3d/d3d11/SwapChain11.cpp',
+ 'renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp',
+ ]
+
+CXXFLAGS += CONFIG['SSE2_FLAGS']
+
+if CONFIG['GNU_CXX']:
+ CXXFLAGS += [
+ '-Wno-attributes',
+ '-Wno-shadow',
+ '-Wno-sign-compare',
+ '-Wno-unknown-pragmas',
+ '-Wno-unreachable-code',
+ ]
+ if CONFIG['CLANG_CXX']:
+ CXXFLAGS += [
+ '-Wno-inconsistent-missing-override',
+ '-Wno-unused-private-field',
+ ]
+ else:
+ CXXFLAGS += [
+ '-Wno-shadow-compatible-local',
+ '-Wno-shadow-local',
+ ]
+
+if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
+ LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
+
+DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
+DEFINES['_HAS_EXCEPTIONS'] = 0
+
+if not CONFIG['MOZ_DEBUG']:
+ DEFINES['_SECURE_SCL'] = 0
+
+DEFINES['ANGLE_ENABLE_D3D9'] = True
+DEFINES['ANGLE_SKIP_DXGI_1_2_CHECK'] = True
+if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
+ DEFINES['ANGLE_ENABLE_D3D11'] = True
+
+DEFINES['ANGLE_COMPILE_OPTIMIZATION_LEVEL'] = 'D3DCOMPILE_OPTIMIZATION_LEVEL1'
+DEFINES['ANGLE_NO_EXCEPTIONS'] = True
+
+# We need these defined to nothing so that we don't get bogus dllimport declspecs
+DEFINES['GL_APICALL'] = ""
+DEFINES['GL_GLEXT_PROTOTYPES'] = ""
+DEFINES['EGLAPI'] = ""
+
+
+
+LOCAL_INCLUDES += [ '../../include', '../../src', '../../src/common/third_party/numerics', '../../src/third_party/khronos' ]
+
+DEFINES['LIBANGLE_IMPLEMENTATION'] = "1"
+DEFINES['ANGLE_ENABLE_HLSL'] = "1"
+DEFINES['ANGLE_ENABLE_GLSL'] = "1"
+DEFINES['ANGLE_ENABLE_ESSL'] = "1"
+DEFINES['ANGLE_ENABLE_KEYEDMUTEX'] = "1"
+DEFINES['ANGLE_DEFAULT_D3D11'] = "0"
+
+if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
+ OS_LIBS += [ 'd3d9', 'dxguid' ]
+else:
+ EXTRA_DSO_LDOPTS += [
+ '\'%s/lib/%s/d3d9.lib\'' % (CONFIG['MOZ_DIRECTX_SDK_PATH'], CONFIG['MOZ_D3D_CPU_SUFFIX']),
+ '\'%s/lib/%s/dxguid.lib\'' % (CONFIG['MOZ_DIRECTX_SDK_PATH'], CONFIG['MOZ_D3D_CPU_SUFFIX']),
+ ]
+
+Library('libANGLE')
+
+
+SOURCES['renderer/d3d/HLSLCompiler.cpp'].flags += ['-DANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES=\'{ TEXT("d3dcompiler_47.dll"), TEXT("d3dcompiler_46.dll"), TEXT("d3dcompiler_43.dll") }\'']
+
+if CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
+ SOURCES['renderer/d3d/d3d11/SwapChain11.cpp'].flags += ['-DANGLE_RESOURCE_SHARE_TYPE=D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX']
+
+# We allow warnings for third-party code that can be updated from upstream.
+ALLOW_COMPILER_WARNINGS = True
+
diff --git a/gfx/angle/src/libANGLE/queryconversions.cpp b/gfx/angle/src/libANGLE/queryconversions.cpp
new file mode 100755
index 000000000..611fbc4ba
--- /dev/null
+++ b/gfx/angle/src/libANGLE/queryconversions.cpp
@@ -0,0 +1,219 @@
+//
+// Copyright (c) 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 "libANGLE/Context.h"
+#include "common/utilities.h"
+
+namespace gl
+{
+
+namespace
+{
+
+GLint64 ExpandFloatToInteger(GLfloat value)
+{
+ return static_cast<GLint64>((static_cast<double>(0xFFFFFFFFULL) * value - 1.0) / 2.0);
+}
+
+template <typename QueryT>
+QueryT ClampToQueryRange(GLint64 value)
+{
+ const GLint64 min = static_cast<GLint64>(std::numeric_limits<QueryT>::min());
+ const GLint64 max = static_cast<GLint64>(std::numeric_limits<QueryT>::max());
+ return static_cast<QueryT>(clamp(value, min, max));
+}
+
+template <typename QueryT, typename NativeT>
+QueryT CastStateValueToInt(GLenum pname, NativeT value)
+{
+ GLenum queryType = GLTypeToGLenum<QueryT>::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
+ if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
+ {
+ return ClampToQueryRange<QueryT>(ExpandFloatToInteger(static_cast<GLfloat>(value)));
+ }
+ else
+ {
+ return gl::iround<QueryT>(static_cast<GLfloat>(value));
+ }
+ }
+
+ // Clamp 64-bit int values when casting to int
+ if (nativeType == GL_INT_64_ANGLEX && queryType == GL_INT)
+ {
+ GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<GLint>::min());
+ GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<GLint>::max());
+ GLint64 clampedValue = std::max(std::min(static_cast<GLint64>(value), maxIntValue), minIntValue);
+ return static_cast<QueryT>(clampedValue);
+ }
+
+ return static_cast<QueryT>(value);
+}
+
+template <typename QueryT, typename NativeT>
+QueryT CastStateValue(GLenum pname, NativeT value)
+{
+ GLenum queryType = GLTypeToGLenum<QueryT>::value;
+
+ switch (queryType)
+ {
+ case GL_INT:
+ return CastStateValueToInt<QueryT, NativeT>(pname, value);
+ case GL_INT_64_ANGLEX:
+ return CastStateValueToInt<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;
+ }
+}
+
+} // anonymous namespace
+
+template <typename QueryT>
+void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
+ unsigned int numParams, QueryT *outParams)
+{
+ if (nativeType == GL_INT)
+ {
+ std::vector<GLint> intParams(numParams, 0);
+ context->getIntegerv(pname, intParams.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastStateValue<QueryT>(pname, intParams[i]);
+ }
+ }
+ else if (nativeType == GL_BOOL)
+ {
+ std::vector<GLboolean> boolParams(numParams, GL_FALSE);
+ context->getBooleanv(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->getFloatv(pname, floatParams.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastStateValue<QueryT>(pname, floatParams[i]);
+ }
+ }
+ else if (nativeType == GL_INT_64_ANGLEX)
+ {
+ std::vector<GLint64> int64Params(numParams, 0);
+ context->getInteger64v(pname, int64Params.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastStateValue<QueryT>(pname, int64Params[i]);
+ }
+ }
+ else UNREACHABLE();
+}
+
+// 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
+
+template void CastStateValues<GLboolean>(Context *, GLenum, GLenum, unsigned int, GLboolean *);
+template void CastStateValues<GLint>(Context *, GLenum, GLenum, unsigned int, GLint *);
+template void CastStateValues<GLuint>(Context *, GLenum, GLenum, unsigned int, GLuint *);
+template void CastStateValues<GLfloat>(Context *, GLenum, GLenum, unsigned int, GLfloat *);
+template void CastStateValues<GLint64>(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] = CastStateValue<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] = CastStateValue<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 *);
+}
diff --git a/gfx/angle/src/libANGLE/queryconversions.h b/gfx/angle/src/libANGLE/queryconversions.h
new file mode 100755
index 000000000..5b96a3e15
--- /dev/null
+++ b/gfx/angle/src/libANGLE/queryconversions.h
@@ -0,0 +1,70 @@
+//
+// Copyright (c) 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 CastStateValue, 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<GLfloat>
+{
+ static constexpr GLenum value = GL_FLOAT;
+};
+
+// The GL state query API types are: bool, int, uint, float, int64
+template <typename QueryT>
+void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
+ unsigned int numParams, QueryT *outParams);
+
+// The GL state query API types are: bool, int, uint, float, int64
+template <typename QueryT>
+void CastIndexedStateValues(Context *context,
+ GLenum nativeType,
+ GLenum pname,
+ GLuint index,
+ unsigned int numParams,
+ QueryT *outParams);
+}
+
+#endif // LIBANGLE_QUERY_CONVERSIONS_H_
diff --git a/gfx/angle/src/libANGLE/queryutils.cpp b/gfx/angle/src/libANGLE/queryutils.cpp
new file mode 100644
index 000000000..fdd2980e2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/queryutils.cpp
@@ -0,0 +1,772 @@
+//
+// Copyright (c) 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 "common/utilities.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VertexAttribute.h"
+
+namespace gl
+{
+
+namespace
+{
+template <typename ParamType>
+void QueryTexParameterBase(const Texture *texture, GLenum pname, ParamType *params)
+{
+ ASSERT(texture != nullptr);
+
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = ConvertFromGLenum<ParamType>(texture->getMagFilter());
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = ConvertFromGLenum<ParamType>(texture->getMinFilter());
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = ConvertFromGLenum<ParamType>(texture->getWrapS());
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = ConvertFromGLenum<ParamType>(texture->getWrapT());
+ break;
+ case GL_TEXTURE_WRAP_R:
+ *params = ConvertFromGLenum<ParamType>(texture->getWrapR());
+ break;
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ *params = ConvertFromGLboolean<ParamType>(texture->getImmutableFormat());
+ break;
+ case GL_TEXTURE_IMMUTABLE_LEVELS:
+ *params = ConvertFromGLuint<ParamType>(texture->getImmutableLevels());
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ *params = ConvertFromGLenum<ParamType>(texture->getUsage());
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ *params = ConvertFromGLfloat<ParamType>(texture->getMaxAnisotropy());
+ break;
+ case GL_TEXTURE_SWIZZLE_R:
+ *params = ConvertFromGLenum<ParamType>(texture->getSwizzleRed());
+ break;
+ case GL_TEXTURE_SWIZZLE_G:
+ *params = ConvertFromGLenum<ParamType>(texture->getSwizzleGreen());
+ break;
+ case GL_TEXTURE_SWIZZLE_B:
+ *params = ConvertFromGLenum<ParamType>(texture->getSwizzleBlue());
+ break;
+ case GL_TEXTURE_SWIZZLE_A:
+ *params = ConvertFromGLenum<ParamType>(texture->getSwizzleAlpha());
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ *params = ConvertFromGLuint<ParamType>(texture->getBaseLevel());
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ *params = ConvertFromGLuint<ParamType>(texture->getMaxLevel());
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = ConvertFromGLfloat<ParamType>(texture->getSamplerState().minLod);
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = ConvertFromGLfloat<ParamType>(texture->getSamplerState().maxLod);
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ *params = ConvertFromGLenum<ParamType>(texture->getCompareMode());
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ *params = ConvertFromGLenum<ParamType>(texture->getCompareFunc());
+ break;
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ *params = ConvertFromGLenum<ParamType>(texture->getSRGBDecode());
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename ParamType>
+void SetTexParameterBase(Texture *texture, GLenum pname, const ParamType *params)
+{
+ ASSERT(texture != nullptr);
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ texture->setWrapS(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_WRAP_T:
+ texture->setWrapT(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_WRAP_R:
+ texture->setWrapR(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ texture->setMinFilter(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ texture->setMagFilter(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ texture->setUsage(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ texture->setMaxAnisotropy(ConvertToGLfloat(params[0]));
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ texture->setCompareMode(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ texture->setCompareFunc(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_SWIZZLE_R:
+ texture->setSwizzleRed(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_SWIZZLE_G:
+ texture->setSwizzleGreen(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_SWIZZLE_B:
+ texture->setSwizzleBlue(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_SWIZZLE_A:
+ texture->setSwizzleAlpha(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ texture->setBaseLevel(ConvertToGLuint(params[0]));
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ texture->setMaxLevel(ConvertToGLuint(params[0]));
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ texture->setMinLod(ConvertToGLfloat(params[0]));
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ texture->setMaxLod(ConvertToGLfloat(params[0]));
+ break;
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ texture->setSRGBDecode(ConvertToGLenum(params[0]));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename ParamType>
+void QuerySamplerParameterBase(const Sampler *sampler, GLenum pname, ParamType *params)
+{
+ switch (pname)
+ {
+ case GL_TEXTURE_MIN_FILTER:
+ *params = ConvertFromGLenum<ParamType>(sampler->getMinFilter());
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ *params = ConvertFromGLenum<ParamType>(sampler->getMagFilter());
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = ConvertFromGLenum<ParamType>(sampler->getWrapS());
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = ConvertFromGLenum<ParamType>(sampler->getWrapT());
+ break;
+ case GL_TEXTURE_WRAP_R:
+ *params = ConvertFromGLenum<ParamType>(sampler->getWrapR());
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ *params = ConvertFromGLfloat<ParamType>(sampler->getMaxAnisotropy());
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = ConvertFromGLfloat<ParamType>(sampler->getMinLod());
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = ConvertFromGLfloat<ParamType>(sampler->getMaxLod());
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ *params = ConvertFromGLenum<ParamType>(sampler->getCompareMode());
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ *params = ConvertFromGLenum<ParamType>(sampler->getCompareFunc());
+ break;
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ *params = ConvertFromGLenum<ParamType>(sampler->getSRGBDecode());
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename ParamType>
+void SetSamplerParameterBase(Sampler *sampler, GLenum pname, const ParamType *params)
+{
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ sampler->setWrapS(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_WRAP_T:
+ sampler->setWrapT(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_WRAP_R:
+ sampler->setWrapR(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ sampler->setMinFilter(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ sampler->setMagFilter(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ sampler->setMaxAnisotropy(ConvertToGLfloat(params[0]));
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ sampler->setCompareMode(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ sampler->setCompareFunc(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ sampler->setMinLod(ConvertToGLfloat(params[0]));
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ sampler->setMaxLod(ConvertToGLfloat(params[0]));
+ break;
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ sampler->setSRGBDecode(ConvertToGLenum(params[0]));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename ParamType, typename CurrentDataType>
+ParamType ConvertCurrentValue(CurrentDataType currentValue)
+{
+ return static_cast<ParamType>(currentValue);
+}
+
+template <>
+GLint ConvertCurrentValue(GLfloat currentValue)
+{
+ return iround<GLint>(currentValue);
+}
+
+template <typename ParamType, typename CurrentDataType, size_t CurrentValueCount>
+void QueryVertexAttribBase(const VertexAttribute &attrib,
+ 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] = ConvertCurrentValue<ParamType>(currentValueData[i]);
+ }
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+ *params = ConvertFromGLboolean<ParamType>(attrib.enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+ *params = ConvertFromGLuint<ParamType>(attrib.size);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+ *params = ConvertFromGLuint<ParamType>(attrib.stride);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+ *params = ConvertFromGLenum<ParamType>(attrib.type);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+ *params = ConvertFromGLboolean<ParamType>(attrib.normalized);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+ *params = ConvertFromGLuint<ParamType>(attrib.buffer.id());
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
+ *params = ConvertFromGLuint<ParamType>(attrib.divisor);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
+ *params = ConvertFromGLboolean<ParamType>(attrib.pureInteger);
+ 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 = ConvertFromGLenum<ParamType>(buffer->getUsage());
+ break;
+ case GL_BUFFER_SIZE:
+ *params = ConvertFromGLint64<ParamType>(buffer->getSize());
+ break;
+ case GL_BUFFER_ACCESS_FLAGS:
+ *params = ConvertFromGLuint<ParamType>(buffer->getAccessFlags());
+ break;
+ case GL_BUFFER_ACCESS_OES:
+ *params = ConvertFromGLenum<ParamType>(buffer->getAccess());
+ break;
+ case GL_BUFFER_MAPPED:
+ *params = ConvertFromGLboolean<ParamType>(buffer->isMapped());
+ break;
+ case GL_BUFFER_MAP_OFFSET:
+ *params = ConvertFromGLint64<ParamType>(buffer->getMapOffset());
+ break;
+ case GL_BUFFER_MAP_LENGTH:
+ *params = ConvertFromGLint64<ParamType>(buffer->getMapLength());
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+} // anonymous namespace
+
+void QueryFramebufferAttachmentParameteriv(const Framebuffer *framebuffer,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params)
+{
+ ASSERT(framebuffer);
+
+ const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(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:
+ *params = attachmentObject->cubeMapFace();
+ 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;
+
+ 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(const Program *program, GLenum pname, GLint *params)
+{
+ ASSERT(program != nullptr);
+
+ switch (pname)
+ {
+ case GL_DELETE_STATUS:
+ *params = program->isFlaggedForDeletion();
+ return;
+ case GL_LINK_STATUS:
+ *params = program->isLinked();
+ return;
+ case GL_VALIDATE_STATUS:
+ *params = program->isValidated();
+ return;
+ case GL_INFO_LOG_LENGTH:
+ *params = program->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 = program->getBinaryLength();
+ return;
+ case GL_ACTIVE_UNIFORM_BLOCKS:
+ *params = program->getActiveUniformBlockCount();
+ return;
+ case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+ *params = program->getActiveUniformBlockMaxLength();
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
+ *params = program->getTransformFeedbackBufferMode();
+ break;
+ case GL_TRANSFORM_FEEDBACK_VARYINGS:
+ *params = program->getTransformFeedbackVaryingCount();
+ break;
+ case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+ *params = program->getTransformFeedbackVaryingMaxLength();
+ break;
+ case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+ *params = program->getBinaryRetrievableHint();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryRenderbufferiv(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:
+ *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->getSamples();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryShaderiv(const Shader *shader, GLenum pname, GLint *params)
+{
+ ASSERT(shader != nullptr);
+
+ switch (pname)
+ {
+ case GL_SHADER_TYPE:
+ *params = shader->getType();
+ return;
+ case GL_DELETE_STATUS:
+ *params = shader->isFlaggedForDeletion();
+ return;
+ case GL_COMPILE_STATUS:
+ *params = shader->isCompiled() ? GL_TRUE : GL_FALSE;
+ return;
+ case GL_INFO_LOG_LENGTH:
+ *params = shader->getInfoLogLength();
+ return;
+ case GL_SHADER_SOURCE_LENGTH:
+ *params = shader->getSourceLength();
+ return;
+ case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+ *params = shader->getTranslatedSourceWithDebugInfoLength();
+ return;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryTexParameterfv(const Texture *texture, GLenum pname, GLfloat *params)
+{
+ QueryTexParameterBase(texture, pname, params);
+}
+
+void QueryTexParameteriv(const Texture *texture, GLenum pname, GLint *params)
+{
+ QueryTexParameterBase(texture, pname, params);
+}
+
+void QuerySamplerParameterfv(const Sampler *sampler, GLenum pname, GLfloat *params)
+{
+ QuerySamplerParameterBase(sampler, pname, params);
+}
+
+void QuerySamplerParameteriv(const Sampler *sampler, GLenum pname, GLint *params)
+{
+ QuerySamplerParameterBase(sampler, pname, params);
+}
+
+void QueryVertexAttribfv(const VertexAttribute &attrib,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLfloat *params)
+{
+ QueryVertexAttribBase(attrib, currentValueData.FloatValues, pname, params);
+}
+
+void QueryVertexAttribiv(const VertexAttribute &attrib,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLint *params)
+{
+ QueryVertexAttribBase(attrib, currentValueData.FloatValues, pname, params);
+}
+
+void QueryVertexAttribPointerv(const VertexAttribute &attrib, GLenum pname, GLvoid **pointer)
+{
+ switch (pname)
+ {
+ case GL_VERTEX_ATTRIB_ARRAY_POINTER:
+ *pointer = const_cast<GLvoid *>(attrib.pointer);
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryVertexAttribIiv(const VertexAttribute &attrib,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLint *params)
+{
+ QueryVertexAttribBase(attrib, currentValueData.IntValues, pname, params);
+}
+
+void QueryVertexAttribIuiv(const VertexAttribute &attrib,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLuint *params)
+{
+ QueryVertexAttribBase(attrib, currentValueData.UnsignedIntValues, pname, params);
+}
+
+void QueryActiveUniformBlockiv(const Program *program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params)
+{
+ const UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
+ switch (pname)
+ {
+ case GL_UNIFORM_BLOCK_BINDING:
+ *params = ConvertToGLint(program->getUniformBlockBinding(uniformBlockIndex));
+ break;
+ case GL_UNIFORM_BLOCK_DATA_SIZE:
+ *params = ConvertToGLint(uniformBlock.dataSize);
+ break;
+ case GL_UNIFORM_BLOCK_NAME_LENGTH:
+ *params = ConvertToGLint(uniformBlock.nameWithArrayIndex().size() + 1);
+ break;
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ *params = ConvertToGLint(uniformBlock.memberUniformIndexes.size());
+ break;
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ for (size_t blockMemberIndex = 0;
+ blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
+ {
+ params[blockMemberIndex] =
+ ConvertToGLint(uniformBlock.memberUniformIndexes[blockMemberIndex]);
+ }
+ break;
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ *params = ConvertToGLint(uniformBlock.vertexStaticUse);
+ break;
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ *params = ConvertToGLint(uniformBlock.fragmentStaticUse);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryInternalFormativ(const TextureCaps &format, GLenum pname, GLsizei bufSize, GLint *params)
+{
+ switch (pname)
+ {
+ case GL_NUM_SAMPLE_COUNTS:
+ if (bufSize != 0)
+ {
+ *params = static_cast<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 SetTexParameterf(Texture *texture, GLenum pname, GLfloat param)
+{
+ SetTexParameterBase(texture, pname, &param);
+}
+
+void SetTexParameterfv(Texture *texture, GLenum pname, const GLfloat *params)
+{
+ SetTexParameterBase(texture, pname, params);
+}
+
+void SetTexParameteri(Texture *texture, GLenum pname, GLint param)
+{
+ SetTexParameterBase(texture, pname, &param);
+}
+
+void SetTexParameteriv(Texture *texture, GLenum pname, const GLint *params)
+{
+ SetTexParameterBase(texture, pname, params);
+}
+
+void SetSamplerParameterf(Sampler *sampler, GLenum pname, GLfloat param)
+{
+ SetSamplerParameterBase(sampler, pname, &param);
+}
+
+void SetSamplerParameterfv(Sampler *sampler, GLenum pname, const GLfloat *params)
+{
+ SetSamplerParameterBase(sampler, pname, params);
+}
+
+void SetSamplerParameteri(Sampler *sampler, GLenum pname, GLint param)
+{
+ SetSamplerParameterBase(sampler, pname, &param);
+}
+
+void SetSamplerParameteriv(Sampler *sampler, GLenum pname, const GLint *params)
+{
+ SetSamplerParameterBase(sampler, pname, params);
+}
+}
diff --git a/gfx/angle/src/libANGLE/queryutils.h b/gfx/angle/src/libANGLE/queryutils.h
new file mode 100644
index 000000000..28a84b3bd
--- /dev/null
+++ b/gfx/angle/src/libANGLE/queryutils.h
@@ -0,0 +1,79 @@
+//
+// Copyright (c) 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/angleutils.h"
+
+namespace gl
+{
+class Buffer;
+class Framebuffer;
+class Program;
+class Renderbuffer;
+class Sampler;
+class Shader;
+class Texture;
+struct TextureCaps;
+struct UniformBlock;
+struct VertexAttribute;
+struct VertexAttribCurrentValueData;
+
+void QueryFramebufferAttachmentParameteriv(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(const Program *program, GLenum pname, GLint *params);
+void QueryRenderbufferiv(const Renderbuffer *renderbuffer, GLenum pname, GLint *params);
+void QueryShaderiv(const Shader *shader, GLenum pname, GLint *params);
+void QueryTexParameterfv(const Texture *texture, GLenum pname, GLfloat *params);
+void QueryTexParameteriv(const Texture *texture, GLenum pname, GLint *params);
+void QuerySamplerParameterfv(const Sampler *sampler, GLenum pname, GLfloat *params);
+void QuerySamplerParameteriv(const Sampler *sampler, GLenum pname, GLint *params);
+void QueryVertexAttribfv(const VertexAttribute &attrib,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLfloat *params);
+void QueryVertexAttribiv(const VertexAttribute &attrib,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLint *params);
+void QueryVertexAttribPointerv(const VertexAttribute &attrib, GLenum pname, GLvoid **pointer);
+void QueryVertexAttribIiv(const VertexAttribute &attrib,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLint *params);
+void QueryVertexAttribIuiv(const VertexAttribute &attrib,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLuint *params);
+
+void QueryActiveUniformBlockiv(const Program *program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params);
+
+void QueryInternalFormativ(const TextureCaps &format, GLenum pname, GLsizei bufSize, GLint *params);
+
+void SetTexParameterf(Texture *texture, GLenum pname, GLfloat param);
+void SetTexParameterfv(Texture *texture, GLenum pname, const GLfloat *params);
+void SetTexParameteri(Texture *texture, GLenum pname, GLint param);
+void SetTexParameteriv(Texture *texture, GLenum pname, const GLint *params);
+
+void SetSamplerParameterf(Sampler *sampler, GLenum pname, GLfloat param);
+void SetSamplerParameterfv(Sampler *sampler, GLenum pname, const GLfloat *params);
+void SetSamplerParameteri(Sampler *sampler, GLenum pname, GLint param);
+void SetSamplerParameteriv(Sampler *sampler, GLenum pname, const GLint *params);
+}
+
+#endif // LIBANGLE_QUERYUTILS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/BufferImpl.h b/gfx/angle/src/libANGLE/renderer/BufferImpl.h
new file mode 100755
index 000000000..10d371541
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/BufferImpl.h
@@ -0,0 +1,54 @@
+//
+// 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/angleutils.h"
+#include "common/mathutil.h"
+#include "libANGLE/Error.h"
+
+#include <stdint.h>
+
+namespace gl
+{
+class BufferState;
+}
+
+namespace rx
+{
+
+class BufferImpl : angle::NonCopyable
+{
+ public:
+ BufferImpl(const gl::BufferState &state) : mState(state) {}
+ virtual ~BufferImpl() { }
+
+ virtual gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) = 0;
+ virtual gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) = 0;
+ virtual gl::Error copySubData(BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size) = 0;
+ virtual gl::Error map(GLenum access, GLvoid **mapPtr) = 0;
+ virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0;
+ virtual gl::Error unmap(GLboolean *result) = 0;
+
+ virtual gl::Error getIndexRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ gl::IndexRange *outRange) = 0;
+
+ protected:
+ const gl::BufferState &mState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_BUFFERIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/BufferImpl_mock.h b/gfx/angle/src/libANGLE/renderer/BufferImpl_mock.h
new file mode 100755
index 000000000..7e45c01b7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/BufferImpl_mock.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.
+//
+
+// BufferImpl_mock.h: Defines a mock of the BufferImpl class.
+
+#ifndef LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_
+#define LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/BufferImpl.h"
+
+namespace rx
+{
+
+class MockBufferImpl : public BufferImpl
+{
+ public:
+ MockBufferImpl() : BufferImpl(mMockState) {}
+ ~MockBufferImpl() { destructor(); }
+
+ MOCK_METHOD4(setData, gl::Error(GLenum, const void *, size_t, GLenum));
+ MOCK_METHOD4(setSubData, gl::Error(GLenum, const void *, size_t, size_t));
+ MOCK_METHOD4(copySubData, gl::Error(BufferImpl *, GLintptr, GLintptr, GLsizeiptr));
+ MOCK_METHOD2(map, gl::Error(GLenum, GLvoid **));
+ MOCK_METHOD4(mapRange, gl::Error(size_t, size_t, GLbitfield, GLvoid **));
+ MOCK_METHOD1(unmap, gl::Error(GLboolean *result));
+
+ MOCK_METHOD5(getIndexRange, gl::Error(GLenum, size_t, size_t, bool, gl::IndexRange *));
+
+ MOCK_METHOD0(destructor, void());
+
+ protected:
+ gl::BufferState mMockState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/CompilerImpl.h b/gfx/angle/src/libANGLE/renderer/CompilerImpl.h
new file mode 100755
index 000000000..82f1ffe0d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/CompilerImpl.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 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 "common/angleutils.h"
+#include "GLSLANG/ShaderLang.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() {}
+
+ virtual gl::Error release() = 0;
+
+ // TODO(jmadill): Expose translator built-in resources init method.
+ virtual ShShaderOutput getTranslatorOutputType() const = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_COMPILERIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/ContextImpl.cpp b/gfx/angle/src/libANGLE/renderer/ContextImpl.cpp
new file mode 100755
index 000000000..0e1c9ff41
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/ContextImpl.cpp
@@ -0,0 +1,113 @@
+//
+// 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"
+
+namespace rx
+{
+
+ContextImpl::ContextImpl(const gl::ContextState &state) : mState(state)
+{
+}
+
+ContextImpl::~ContextImpl()
+{
+}
+
+void ContextImpl::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::coverFillPath(const gl::Path *path, GLenum coverMode)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::coverStrokePath(const gl::Path *path, GLenum coverMode)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilThenCoverFillPath(const gl::Path *path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilThenCoverStrokePath(const gl::Path *path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::coverFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ UNREACHABLE();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/ContextImpl.h b/gfx/angle/src/libANGLE/renderer/ContextImpl.h
new file mode 100755
index 000000000..3fc9db593
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/ContextImpl.h
@@ -0,0 +1,153 @@
+//
+// 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/ContextState.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace gl
+{
+class Path;
+}
+
+namespace rx
+{
+class ContextImpl : public GLImplFactory
+{
+ public:
+ ContextImpl(const gl::ContextState &state);
+ virtual ~ContextImpl();
+
+ virtual gl::Error initialize() = 0;
+
+ // Flush and finish.
+ virtual gl::Error flush() = 0;
+ virtual gl::Error finish() = 0;
+
+ // Drawing methods.
+ virtual gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) = 0;
+ virtual gl::Error drawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) = 0;
+
+ virtual gl::Error drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange) = 0;
+ virtual gl::Error drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange) = 0;
+ virtual gl::Error drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange) = 0;
+
+ // CHROMIUM_path_rendering path drawing methods.
+ virtual void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask);
+ virtual void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask);
+ virtual void coverFillPath(const gl::Path *path, GLenum coverMode);
+ virtual void coverStrokePath(const gl::Path *path, GLenum coverMode);
+ virtual void stencilThenCoverFillPath(const gl::Path *path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode);
+
+ virtual void stencilThenCoverStrokePath(const gl::Path *path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode);
+
+ virtual void coverFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ virtual void coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ virtual void stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ virtual void stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ virtual void stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ virtual void stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+
+ // Device loss
+ virtual GLenum getResetStatus() = 0;
+
+ // Vendor and description strings.
+ virtual std::string getVendorString() const = 0;
+ virtual std::string getRendererDescription() const = 0;
+
+ // Debug markers.
+ virtual void insertEventMarker(GLsizei length, const char *marker) = 0;
+ virtual void pushGroupMarker(GLsizei length, const char *marker) = 0;
+ virtual void popGroupMarker() = 0;
+
+ // State sync with dirty bits.
+ virtual void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) = 0;
+
+ // Disjoint timer queries
+ virtual GLint getGPUDisjoint() = 0;
+ virtual GLint64 getTimestamp() = 0;
+
+ // Context switching
+ virtual void onMakeCurrent(const gl::ContextState &data) = 0;
+
+ // Native capabilities, unmodified by gl::Context.
+ virtual const 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;
+
+ const gl::ContextState &getContextState() { return mState; }
+ int getClientMajorVersion() const { return mState.getClientMajorVersion(); }
+ int getClientMinorVersion() const { return mState.getClientMinorVersion(); }
+ const gl::State &getGLState() const { return mState.getState(); }
+ 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(); }
+
+ protected:
+ const gl::ContextState &mState;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_CONTEXTIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/DeviceImpl.cpp b/gfx/angle/src/libANGLE/renderer/DeviceImpl.cpp
new file mode 100755
index 000000000..6a166236d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/DeviceImpl.cpp
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 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()
+{
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/DeviceImpl.h b/gfx/angle/src/libANGLE/renderer/DeviceImpl.h
new file mode 100755
index 000000000..550bc1e2d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/DeviceImpl.h
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 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/Error.h"
+#include "libANGLE/Caps.h"
+
+namespace egl
+{
+class Device;
+}
+
+namespace rx
+{
+class DeviceImpl : angle::NonCopyable
+{
+ public:
+ DeviceImpl();
+ virtual ~DeviceImpl();
+
+ virtual egl::Error getDevice(void **outValue) = 0;
+ virtual EGLint getType() = 0;
+ virtual void generateExtensions(egl::DeviceExtensions *outExtensions) const = 0;
+ virtual bool deviceExternallySourced() = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_DEVICEIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/DisplayImpl.cpp b/gfx/angle/src/libANGLE/renderer/DisplayImpl.cpp
new file mode 100755
index 000000000..fc2f2c5ce
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/DisplayImpl.cpp
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 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/Surface.h"
+
+namespace rx
+{
+
+DisplayImpl::DisplayImpl()
+ : mExtensionsInitialized(false),
+ mCapsInitialized(false)
+{
+}
+
+DisplayImpl::~DisplayImpl()
+{
+ ASSERT(mSurfaceSet.empty());
+}
+
+void DisplayImpl::destroySurface(egl::Surface *surface)
+{
+ mSurfaceSet.erase(surface);
+ surface->onDestroy();
+}
+
+const egl::DisplayExtensions &DisplayImpl::getExtensions() const
+{
+ if (!mExtensionsInitialized)
+ {
+ generateExtensions(&mExtensions);
+ mExtensionsInitialized = true;
+ }
+
+ return mExtensions;
+}
+
+egl::Error DisplayImpl::validateClientBuffer(const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ UNREACHABLE();
+ return egl::Error(EGL_BAD_DISPLAY, "DisplayImpl::validateClientBuffer unimplemented.");
+}
+
+const egl::Caps &DisplayImpl::getCaps() const
+{
+ if (!mCapsInitialized)
+ {
+ generateCaps(&mCaps);
+ mCapsInitialized = true;
+ }
+
+ return mCaps;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/DisplayImpl.h b/gfx/angle/src/libANGLE/renderer/DisplayImpl.h
new file mode 100755
index 000000000..ec603e85b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/DisplayImpl.h
@@ -0,0 +1,104 @@
+//
+// Copyright (c) 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/angleutils.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Version.h"
+
+#include <set>
+#include <vector>
+
+namespace egl
+{
+class AttributeMap;
+class Display;
+struct Config;
+class Surface;
+class ImageSibling;
+}
+
+namespace gl
+{
+class Context;
+}
+
+namespace rx
+{
+class SurfaceImpl;
+class ImageImpl;
+struct ConfigDesc;
+class DeviceImpl;
+class StreamProducerImpl;
+
+class DisplayImpl : public EGLImplFactory
+{
+ public:
+ DisplayImpl();
+ virtual ~DisplayImpl();
+
+ virtual egl::Error initialize(egl::Display *display) = 0;
+ virtual void terminate() = 0;
+
+ virtual egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) = 0;
+
+ virtual egl::ConfigSet generateConfigs() = 0;
+
+ virtual bool testDeviceLost() = 0;
+ virtual egl::Error restoreLostDevice() = 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 std::string getVendorString() const = 0;
+
+ virtual egl::Error getDevice(DeviceImpl **device) = 0;
+
+ virtual egl::Error waitClient() const = 0;
+ virtual egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const = 0;
+ virtual gl::Version getMaxSupportedESVersion() const = 0;
+ const egl::Caps &getCaps() const;
+
+ typedef std::set<egl::Surface*> SurfaceSet;
+ const SurfaceSet &getSurfaceSet() const { return mSurfaceSet; }
+ SurfaceSet &getSurfaceSet() { return mSurfaceSet; }
+
+ void destroySurface(egl::Surface *surface);
+
+ const egl::DisplayExtensions &getExtensions() const;
+
+ protected:
+ // Place the surface set here so it can be accessible for handling
+ // context loss events. (It is shared between the Display and Impl.)
+ SurfaceSet mSurfaceSet;
+
+ 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;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_DISPLAYIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/EGLImplFactory.h b/gfx/angle/src/libANGLE/renderer/EGLImplFactory.h
new file mode 100755
index 000000000..2ddbb7625
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/EGLImplFactory.h
@@ -0,0 +1,71 @@
+//
+// 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 SurfaceState;
+}
+
+namespace gl
+{
+class Context;
+class ContextState;
+}
+
+namespace rx
+{
+class ContextImpl;
+class ImageImpl;
+class SurfaceImpl;
+
+class EGLImplFactory : angle::NonCopyable
+{
+ public:
+ EGLImplFactory() {}
+ virtual ~EGLImplFactory() {}
+
+ virtual SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) = 0;
+ virtual SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) = 0;
+ virtual SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) = 0;
+ virtual SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) = 0;
+
+ virtual ImageImpl *createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs) = 0;
+
+ virtual ContextImpl *createContext(const gl::ContextState &state) = 0;
+
+ virtual StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) = 0;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_EGLIMPLFACTORY_H_
diff --git a/gfx/angle/src/libANGLE/renderer/FenceNVImpl.h b/gfx/angle/src/libANGLE/renderer/FenceNVImpl.h
new file mode 100755
index 000000000..a53491497
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/FenceNVImpl.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 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 rx
+{
+
+class FenceNVImpl : angle::NonCopyable
+{
+ public:
+ FenceNVImpl() { };
+ virtual ~FenceNVImpl() { };
+
+ virtual gl::Error set(GLenum condition) = 0;
+ virtual gl::Error test(GLboolean *outFinished) = 0;
+ virtual gl::Error finish() = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_FENCENVIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/FenceSyncImpl.h b/gfx/angle/src/libANGLE/renderer/FenceSyncImpl.h
new file mode 100755
index 000000000..6b78e69d4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/FenceSyncImpl.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 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.
+//
+
+// FenceSyncImpl.h: Defines the rx::FenceSyncImpl class.
+
+#ifndef LIBANGLE_RENDERER_FENCESYNCIMPL_H_
+#define LIBANGLE_RENDERER_FENCESYNCIMPL_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+
+class FenceSyncImpl : angle::NonCopyable
+{
+ public:
+ FenceSyncImpl() { };
+ virtual ~FenceSyncImpl() { };
+
+ virtual gl::Error set(GLenum condition, GLbitfield flags) = 0;
+ virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0;
+ virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0;
+ virtual gl::Error getStatus(GLint *outResult) = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_FENCESYNCIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/Format.h b/gfx/angle/src/libANGLE/renderer/Format.h
new file mode 100755
index 000000000..5c6e7e1fe
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/Format.h
@@ -0,0 +1,101 @@
+//
+// 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/formatutils.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace angle
+{
+
+struct Format final : angle::NonCopyable
+{
+ enum class ID;
+
+ constexpr Format(ID id,
+ GLenum glFormat,
+ GLenum fboFormat,
+ rx::MipGenerationFunction mipGen,
+ const rx::FastCopyFunctionMap &fastCopyFunctions,
+ rx::ColorReadFunction colorRead,
+ GLenum componentType,
+ GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint depthBits,
+ GLuint stencilBits);
+
+ static const Format &Get(ID id);
+
+ ID 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::ColorReadFunction colorReadFunction;
+
+ // 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 depthBits;
+ GLuint stencilBits;
+};
+
+constexpr Format::Format(ID id,
+ GLenum glFormat,
+ GLenum fboFormat,
+ rx::MipGenerationFunction mipGen,
+ const rx::FastCopyFunctionMap &fastCopyFunctions,
+ rx::ColorReadFunction colorRead,
+ GLenum componentType,
+ GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint depthBits,
+ GLuint stencilBits)
+ : id(id),
+ glInternalFormat(glFormat),
+ fboImplementationInternalFormat(fboFormat),
+ mipGenerationFunction(mipGen),
+ colorReadFunction(colorRead),
+ fastCopyFunctions(fastCopyFunctions),
+ componentType(componentType),
+ redBits(redBits),
+ greenBits(greenBits),
+ blueBits(blueBits),
+ alphaBits(alphaBits),
+ depthBits(depthBits),
+ stencilBits(stencilBits)
+{
+}
+
+} // namespace angle
+
+#include "libANGLE/renderer/Format_ID_autogen.inl"
+
+#endif // LIBANGLE_RENDERER_FORMAT_H_
diff --git a/gfx/angle/src/libANGLE/renderer/Format_ID_autogen.inl b/gfx/angle/src/libANGLE/renderer/Format_ID_autogen.inl
new file mode 100755
index 000000000..deee1fea1
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/Format_ID_autogen.inl
@@ -0,0 +1,138 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_angle_format_table.py using data from angle_format_data.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.
+//
+// ANGLE format enumeration.
+
+namespace angle
+{
+
+enum class Format::ID
+{
+ NONE,
+ A16_FLOAT,
+ 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_4x4_SRGB_BLOCK,
+ ASTC_4x4_UNORM_BLOCK,
+ ASTC_5x4_SRGB_BLOCK,
+ ASTC_5x4_UNORM_BLOCK,
+ ASTC_5x5_SRGB_BLOCK,
+ ASTC_5x5_UNORM_BLOCK,
+ ASTC_6x5_SRGB_BLOCK,
+ ASTC_6x5_UNORM_BLOCK,
+ ASTC_6x6_SRGB_BLOCK,
+ ASTC_6x6_UNORM_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,
+ B4G4R4A4_UNORM,
+ B5G5R5A1_UNORM,
+ B5G6R5_UNORM,
+ B8G8R8A8_UNORM,
+ B8G8R8X8_UNORM,
+ BC1_RGBA_UNORM_BLOCK,
+ BC1_RGB_UNORM_BLOCK,
+ BC2_RGBA_UNORM_BLOCK,
+ BC3_RGBA_UNORM_BLOCK,
+ D16_UNORM,
+ D24_UNORM,
+ D24_UNORM_S8_UINT,
+ D32_FLOAT,
+ D32_FLOAT_S8X24_UINT,
+ D32_UNORM,
+ EAC_R11G11_SNORM_BLOCK,
+ EAC_R11G11_UNORM_BLOCK,
+ EAC_R11_SNORM_BLOCK,
+ EAC_R11_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,
+ L16A16_FLOAT,
+ L16_FLOAT,
+ L32A32_FLOAT,
+ L32_FLOAT,
+ L8A8_UNORM,
+ L8_UNORM,
+ R10G10B10A2_UINT,
+ R10G10B10A2_UNORM,
+ R11G11B10_FLOAT,
+ R16G16B16A16_FLOAT,
+ R16G16B16A16_SINT,
+ R16G16B16A16_SNORM,
+ R16G16B16A16_UINT,
+ R16G16B16A16_UNORM,
+ R16G16B16_FLOAT,
+ R16G16B16_SINT,
+ R16G16B16_SNORM,
+ R16G16B16_UINT,
+ R16G16B16_UNORM,
+ R16G16_FLOAT,
+ R16G16_SINT,
+ R16G16_SNORM,
+ R16G16_UINT,
+ R16G16_UNORM,
+ R16_FLOAT,
+ R16_SINT,
+ R16_SNORM,
+ R16_UINT,
+ R16_UNORM,
+ R32G32B32A32_FLOAT,
+ R32G32B32A32_SINT,
+ R32G32B32A32_UINT,
+ R32G32B32_FLOAT,
+ R32G32B32_SINT,
+ R32G32B32_UINT,
+ R32G32_FLOAT,
+ R32G32_SINT,
+ R32G32_UINT,
+ R32_FLOAT,
+ R32_SINT,
+ R32_UINT,
+ R4G4B4A4_UNORM,
+ R5G5B5A1_UNORM,
+ R5G6B5_UNORM,
+ R8G8B8A8_SINT,
+ R8G8B8A8_SNORM,
+ R8G8B8A8_UINT,
+ R8G8B8A8_UNORM,
+ R8G8B8A8_UNORM_SRGB,
+ R8G8B8_SINT,
+ R8G8B8_SNORM,
+ R8G8B8_UINT,
+ R8G8B8_UNORM,
+ R8G8B8_UNORM_SRGB,
+ R8G8_SINT,
+ R8G8_SNORM,
+ R8G8_UINT,
+ R8G8_UNORM,
+ R8_SINT,
+ R8_SNORM,
+ R8_UINT,
+ R8_UNORM,
+ R9G9B9E5_SHAREDEXP,
+ S8_UINT
+};
+
+} // namespace angle
diff --git a/gfx/angle/src/libANGLE/renderer/Format_table_autogen.cpp b/gfx/angle/src/libANGLE/renderer/Format_table_autogen.cpp
new file mode 100644
index 000000000..507827ff1
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/Format_table_autogen.cpp
@@ -0,0 +1,157 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_angle_format_table.py using data from angle_format_data.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.
+//
+// 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 = {GL_RGBA, GL_UNSIGNED_BYTE,
+ CopyBGRA8ToRGBA8};
+static constexpr rx::FastCopyFunctionMap BGRACopyFunctions = {&BGRAEntry, 1};
+static constexpr rx::FastCopyFunctionMap NoCopyFunctions;
+
+constexpr Format g_formatInfoTable[] = {
+ // clang-format off
+ { Format::ID::NONE, GL_NONE, GL_NONE, nullptr, NoCopyFunctions, nullptr, GL_NONE, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::A16_FLOAT, GL_ALPHA16F_EXT, GL_ALPHA16F_EXT, GenerateMip<A16F>, NoCopyFunctions, ReadColor<A16F, GLfloat>, GL_FLOAT, 0, 0, 0, 16, 0, 0 },
+ { Format::ID::A32_FLOAT, GL_ALPHA32F_EXT, GL_ALPHA32F_EXT, GenerateMip<A32F>, NoCopyFunctions, ReadColor<A32F, GLfloat>, GL_FLOAT, 0, 0, 0, 32, 0, 0 },
+ { Format::ID::A8_UNORM, GL_ALPHA8_EXT, GL_ALPHA8_EXT, GenerateMip<A8>, NoCopyFunctions, ReadColor<A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 8, 0, 0 },
+ { Format::ID::ASTC_10x10_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x10_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x8_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_12x10_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_12x10_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_12x12_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_12x12_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_4x4_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_4x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_5x4_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_5x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_5x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_5x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_6x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_6x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_6x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_6x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_8x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_8x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_8x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_8x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_8x8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_8x8_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::B4G4R4A4_UNORM, GL_BGRA4_ANGLEX, GL_RGBA4, GenerateMip<A4R4G4B4>, NoCopyFunctions, ReadColor<A4R4G4B4, GLfloat>, GL_UNSIGNED_NORMALIZED, 4, 4, 4, 4, 0, 0 },
+ { Format::ID::B5G5R5A1_UNORM, GL_BGR5_A1_ANGLEX, GL_RGB5_A1, GenerateMip<A1R5G5B5>, NoCopyFunctions, ReadColor<A1R5G5B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0 },
+ { Format::ID::B5G6R5_UNORM, GL_BGR565_ANGLEX, GL_RGB565, GenerateMip<B5G6R5>, NoCopyFunctions, ReadColor<B5G6R5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 6, 5, 0, 0, 0 },
+ { Format::ID::B8G8R8A8_UNORM, GL_BGRA8_EXT, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, BGRACopyFunctions, ReadColor<B8G8R8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::B8G8R8X8_UNORM, GL_BGRA8_EXT, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, NoCopyFunctions, ReadColor<B8G8R8X8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::BC1_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::BC1_RGB_UNORM_BLOCK, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::BC2_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::BC3_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::D16_UNORM, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT16, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 16, 0 },
+ { Format::ID::D24_UNORM, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT24, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 24, 0 },
+ { Format::ID::D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 24, 8 },
+ { Format::ID::D32_FLOAT, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32F, nullptr, NoCopyFunctions, nullptr, GL_FLOAT, 0, 0, 0, 0, 32, 0 },
+ { Format::ID::D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8, GL_DEPTH32F_STENCIL8, nullptr, NoCopyFunctions, nullptr, GL_FLOAT, 0, 0, 0, 0, 32, 8 },
+ { Format::ID::D32_UNORM, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT32_OES, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 32, 0 },
+ { Format::ID::EAC_R11G11_SNORM_BLOCK, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, nullptr, NoCopyFunctions, nullptr, GL_SIGNED_NORMALIZED, 11, 11, 0, 0, 0, 0 },
+ { Format::ID::EAC_R11G11_UNORM_BLOCK, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 11, 11, 0, 0, 0, 0 },
+ { Format::ID::EAC_R11_SNORM_BLOCK, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, nullptr, NoCopyFunctions, nullptr, GL_SIGNED_NORMALIZED, 11, 0, 0, 0, 0, 0 },
+ { Format::ID::EAC_R11_UNORM_BLOCK, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 11, 0, 0, 0, 0, 0 },
+ { Format::ID::ETC2_R8G8B8A1_SRGB_BLOCK, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 1, 0, 0 },
+ { Format::ID::ETC2_R8G8B8A1_UNORM_BLOCK, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 1, 0, 0 },
+ { Format::ID::ETC2_R8G8B8A8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::ETC2_R8G8B8A8_UNORM_BLOCK, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::ETC2_R8G8B8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::ETC2_R8G8B8_UNORM_BLOCK, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::L16A16_FLOAT, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA16F_EXT, GenerateMip<L16A16F>, NoCopyFunctions, ReadColor<L16A16F, GLfloat>, GL_FLOAT, 0, 0, 0, 16, 0, 0 },
+ { Format::ID::L16_FLOAT, GL_LUMINANCE16F_EXT, GL_LUMINANCE16F_EXT, GenerateMip<L16F>, NoCopyFunctions, ReadColor<L16F, GLfloat>, GL_FLOAT, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::L32A32_FLOAT, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA32F_EXT, GenerateMip<L32A32F>, NoCopyFunctions, ReadColor<L32A32F, GLfloat>, GL_FLOAT, 0, 0, 0, 32, 0, 0 },
+ { Format::ID::L32_FLOAT, GL_LUMINANCE32F_EXT, GL_LUMINANCE32F_EXT, GenerateMip<L32F>, NoCopyFunctions, ReadColor<L32F, GLfloat>, GL_FLOAT, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::L8A8_UNORM, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<L8A8>, NoCopyFunctions, ReadColor<L8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 8, 0, 0 },
+ { Format::ID::L8_UNORM, GL_LUMINANCE8_EXT, GL_LUMINANCE8_EXT, GenerateMip<L8>, NoCopyFunctions, ReadColor<L8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::R10G10B10A2_UINT, GL_RGB10_A2UI, GL_RGB10_A2UI, GenerateMip<R10G10B10A2>, NoCopyFunctions, ReadColor<R10G10B10A2, GLuint>, GL_UNSIGNED_INT, 10, 10, 10, 2, 0, 0 },
+ { Format::ID::R10G10B10A2_UNORM, GL_RGB10_A2, GL_RGB10_A2, GenerateMip<R10G10B10A2>, NoCopyFunctions, ReadColor<R10G10B10A2, GLfloat>, GL_UNSIGNED_NORMALIZED, 10, 10, 10, 2, 0, 0 },
+ { Format::ID::R11G11B10_FLOAT, GL_R11F_G11F_B10F, GL_R11F_G11F_B10F, GenerateMip<R11G11B10F>, NoCopyFunctions, ReadColor<R11G11B10F, GLfloat>, GL_FLOAT, 11, 11, 10, 0, 0, 0 },
+ { Format::ID::R16G16B16A16_FLOAT, GL_RGBA16F, GL_RGBA16F, GenerateMip<R16G16B16A16F>, NoCopyFunctions, ReadColor<R16G16B16A16F, GLfloat>, GL_FLOAT, 16, 16, 16, 16, 0, 0 },
+ { Format::ID::R16G16B16A16_SINT, GL_RGBA16I, GL_RGBA16I, GenerateMip<R16G16B16A16S>, NoCopyFunctions, ReadColor<R16G16B16A16S, GLint>, GL_INT, 16, 16, 16, 16, 0, 0 },
+ { Format::ID::R16G16B16A16_SNORM, GL_RGBA16_SNORM_EXT, GL_RGBA16_SNORM_EXT, GenerateMip<R16G16B16A16S>, NoCopyFunctions, ReadColor<R16G16B16A16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 16, 16, 16, 0, 0 },
+ { Format::ID::R16G16B16A16_UINT, GL_RGBA16UI, GL_RGBA16UI, GenerateMip<R16G16B16A16>, NoCopyFunctions, ReadColor<R16G16B16A16, GLuint>, GL_UNSIGNED_INT, 16, 16, 16, 16, 0, 0 },
+ { Format::ID::R16G16B16A16_UNORM, GL_RGBA16_EXT, GL_RGBA16_EXT, GenerateMip<R16G16B16A16>, NoCopyFunctions, ReadColor<R16G16B16A16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 16, 16, 16, 0, 0 },
+ { Format::ID::R16G16B16_FLOAT, GL_RGB16F, GL_RGB16F, GenerateMip<R16G16B16F>, NoCopyFunctions, ReadColor<R16G16B16F, GLfloat>, GL_FLOAT, 16, 16, 16, 0, 0, 0 },
+ { Format::ID::R16G16B16_SINT, GL_RGB16I, GL_RGB16I, GenerateMip<R16G16B16S>, NoCopyFunctions, ReadColor<R16G16B16S, GLint>, GL_INT, 16, 16, 16, 0, 0, 0 },
+ { Format::ID::R16G16B16_SNORM, GL_RGB16_SNORM_EXT, GL_RGB16_SNORM_EXT, GenerateMip<R16G16B16S>, NoCopyFunctions, ReadColor<R16G16B16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 16, 16, 0, 0, 0 },
+ { Format::ID::R16G16B16_UINT, GL_RGB16UI, GL_RGB16UI, GenerateMip<R16G16B16>, NoCopyFunctions, ReadColor<R16G16B16, GLuint>, GL_UNSIGNED_INT, 16, 16, 16, 0, 0, 0 },
+ { Format::ID::R16G16B16_UNORM, GL_RGB16_EXT, GL_RGB16_EXT, GenerateMip<R16G16B16>, NoCopyFunctions, ReadColor<R16G16B16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 16, 16, 0, 0, 0 },
+ { Format::ID::R16G16_FLOAT, GL_RG16F, GL_RG16F, GenerateMip<R16G16F>, NoCopyFunctions, ReadColor<R16G16F, GLfloat>, GL_FLOAT, 16, 16, 0, 0, 0, 0 },
+ { Format::ID::R16G16_SINT, GL_RG16I, GL_RG16I, GenerateMip<R16G16S>, NoCopyFunctions, ReadColor<R16G16S, GLint>, GL_INT, 16, 16, 0, 0, 0, 0 },
+ { Format::ID::R16G16_SNORM, GL_RG16_SNORM_EXT, GL_RG16_SNORM_EXT, GenerateMip<R16G16S>, NoCopyFunctions, ReadColor<R16G16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 16, 0, 0, 0, 0 },
+ { Format::ID::R16G16_UINT, GL_RG16UI, GL_RG16UI, GenerateMip<R16G16>, NoCopyFunctions, ReadColor<R16G16, GLuint>, GL_UNSIGNED_INT, 16, 16, 0, 0, 0, 0 },
+ { Format::ID::R16G16_UNORM, GL_RG16_EXT, GL_RG16_EXT, GenerateMip<R16G16>, NoCopyFunctions, ReadColor<R16G16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 16, 0, 0, 0, 0 },
+ { Format::ID::R16_FLOAT, GL_R16F, GL_R16F, GenerateMip<R16F>, NoCopyFunctions, ReadColor<R16F, GLfloat>, GL_FLOAT, 16, 0, 0, 0, 0, 0 },
+ { Format::ID::R16_SINT, GL_R16I, GL_R16I, GenerateMip<R16S>, NoCopyFunctions, ReadColor<R16S, GLint>, GL_INT, 16, 0, 0, 0, 0, 0 },
+ { Format::ID::R16_SNORM, GL_R16_SNORM_EXT, GL_R16_SNORM_EXT, GenerateMip<R16S>, NoCopyFunctions, ReadColor<R16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 0, 0, 0, 0, 0 },
+ { Format::ID::R16_UINT, GL_R16UI, GL_R16UI, GenerateMip<R16>, NoCopyFunctions, ReadColor<R16, GLuint>, GL_UNSIGNED_INT, 16, 0, 0, 0, 0, 0 },
+ { Format::ID::R16_UNORM, GL_R16_EXT, GL_R16_EXT, GenerateMip<R16>, NoCopyFunctions, ReadColor<R16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 0, 0, 0, 0, 0 },
+ { Format::ID::R32G32B32A32_FLOAT, GL_RGBA32F, GL_RGBA32F, GenerateMip<R32G32B32A32F>, NoCopyFunctions, ReadColor<R32G32B32A32F, GLfloat>, GL_FLOAT, 32, 32, 32, 32, 0, 0 },
+ { Format::ID::R32G32B32A32_SINT, GL_RGBA32I, GL_RGBA32I, GenerateMip<R32G32B32A32S>, NoCopyFunctions, ReadColor<R32G32B32A32S, GLint>, GL_INT, 32, 32, 32, 32, 0, 0 },
+ { Format::ID::R32G32B32A32_UINT, GL_RGBA32UI, GL_RGBA32UI, GenerateMip<R32G32B32A32>, NoCopyFunctions, ReadColor<R32G32B32A32, GLuint>, GL_UNSIGNED_INT, 32, 32, 32, 32, 0, 0 },
+ { Format::ID::R32G32B32_FLOAT, GL_RGB32F, GL_RGB32F, GenerateMip<R32G32B32F>, NoCopyFunctions, ReadColor<R32G32B32F, GLfloat>, GL_FLOAT, 32, 32, 32, 0, 0, 0 },
+ { Format::ID::R32G32B32_SINT, GL_RGB32I, GL_RGB32I, GenerateMip<R32G32B32S>, NoCopyFunctions, ReadColor<R32G32B32S, GLint>, GL_INT, 32, 32, 32, 0, 0, 0 },
+ { Format::ID::R32G32B32_UINT, GL_RGB32UI, GL_RGB32UI, GenerateMip<R32G32B32>, NoCopyFunctions, ReadColor<R32G32B32, GLuint>, GL_UNSIGNED_INT, 32, 32, 32, 0, 0, 0 },
+ { Format::ID::R32G32_FLOAT, GL_RG32F, GL_RG32F, GenerateMip<R32G32F>, NoCopyFunctions, ReadColor<R32G32F, GLfloat>, GL_FLOAT, 32, 32, 0, 0, 0, 0 },
+ { Format::ID::R32G32_SINT, GL_RG32I, GL_RG32I, GenerateMip<R32G32S>, NoCopyFunctions, ReadColor<R32G32S, GLint>, GL_INT, 32, 32, 0, 0, 0, 0 },
+ { Format::ID::R32G32_UINT, GL_RG32UI, GL_RG32UI, GenerateMip<R32G32>, NoCopyFunctions, ReadColor<R32G32, GLuint>, GL_UNSIGNED_INT, 32, 32, 0, 0, 0, 0 },
+ { Format::ID::R32_FLOAT, GL_R32F, GL_R32F, GenerateMip<R32F>, NoCopyFunctions, ReadColor<R32F, GLfloat>, GL_FLOAT, 32, 0, 0, 0, 0, 0 },
+ { Format::ID::R32_SINT, GL_R32I, GL_R32I, GenerateMip<R32S>, NoCopyFunctions, ReadColor<R32S, GLint>, GL_INT, 32, 0, 0, 0, 0, 0 },
+ { Format::ID::R32_UINT, GL_R32UI, GL_R32UI, GenerateMip<R32>, NoCopyFunctions, ReadColor<R32, GLuint>, GL_UNSIGNED_INT, 32, 0, 0, 0, 0, 0 },
+ { Format::ID::R4G4B4A4_UNORM, GL_RGBA4, GL_RGBA4, GenerateMip<R4G4B4A4>, NoCopyFunctions, ReadColor<R4G4B4A4, GLfloat>, GL_UNSIGNED_NORMALIZED, 4, 4, 4, 4, 0, 0 },
+ { Format::ID::R5G5B5A1_UNORM, GL_RGB5_A1, GL_RGB5_A1, GenerateMip<R5G5B5A1>, NoCopyFunctions, ReadColor<R5G5B5A1, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0 },
+ { Format::ID::R5G6B5_UNORM, GL_RGB565, GL_RGB565, GenerateMip<R5G6B5>, NoCopyFunctions, ReadColor<R5G6B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 6, 5, 0, 0, 0 },
+ { Format::ID::R8G8B8A8_SINT, GL_RGBA8I, GL_RGBA8I, GenerateMip<R8G8B8A8S>, NoCopyFunctions, ReadColor<R8G8B8A8S, GLint>, GL_INT, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::R8G8B8A8_SNORM, GL_RGBA8_SNORM, GL_RGBA8_SNORM, GenerateMip<R8G8B8A8S>, NoCopyFunctions, ReadColor<R8G8B8A8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::R8G8B8A8_UINT, GL_RGBA8UI, GL_RGBA8UI, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLuint>, GL_UNSIGNED_INT, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::R8G8B8A8_UNORM, GL_RGBA8, GL_RGBA8, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::R8G8B8_SINT, GL_RGB8I, GL_RGB8I, GenerateMip<R8G8B8S>, NoCopyFunctions, ReadColor<R8G8B8S, GLint>, GL_INT, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::R8G8B8_SNORM, GL_RGB8_SNORM, GL_RGB8_SNORM, GenerateMip<R8G8B8S>, NoCopyFunctions, ReadColor<R8G8B8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::R8G8B8_UINT, GL_RGB8UI, GL_RGB8UI, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLuint>, GL_UNSIGNED_INT, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::R8G8B8_UNORM, GL_RGB8, GL_RGB8, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::R8G8B8_UNORM_SRGB, GL_SRGB8, GL_SRGB8, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::R8G8_SINT, GL_RG8I, GL_RG8I, GenerateMip<R8G8S>, NoCopyFunctions, ReadColor<R8G8S, GLint>, GL_INT, 8, 8, 0, 0, 0, 0 },
+ { Format::ID::R8G8_SNORM, GL_RG8_SNORM, GL_RG8_SNORM, GenerateMip<R8G8S>, NoCopyFunctions, ReadColor<R8G8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 8, 0, 0, 0, 0 },
+ { Format::ID::R8G8_UINT, GL_RG8UI, GL_RG8UI, GenerateMip<R8G8>, NoCopyFunctions, ReadColor<R8G8, GLuint>, GL_UNSIGNED_INT, 8, 8, 0, 0, 0, 0 },
+ { Format::ID::R8G8_UNORM, GL_RG8, GL_RG8, GenerateMip<R8G8>, NoCopyFunctions, ReadColor<R8G8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 0, 0, 0, 0 },
+ { Format::ID::R8_SINT, GL_R8I, GL_R8I, GenerateMip<R8S>, NoCopyFunctions, ReadColor<R8S, GLint>, GL_INT, 8, 0, 0, 0, 0, 0 },
+ { Format::ID::R8_SNORM, GL_R8_SNORM, GL_R8_SNORM, GenerateMip<R8S>, NoCopyFunctions, ReadColor<R8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 0, 0, 0, 0, 0 },
+ { Format::ID::R8_UINT, GL_R8UI, GL_R8UI, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLuint>, GL_UNSIGNED_INT, 8, 0, 0, 0, 0, 0 },
+ { Format::ID::R8_UNORM, GL_R8, GL_R8, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 0, 0, 0, 0, 0 },
+ { Format::ID::R9G9B9E5_SHAREDEXP, GL_RGB9_E5, GL_RGB9_E5, GenerateMip<R9G9B9E5>, NoCopyFunctions, ReadColor<R9G9B9E5, GLfloat>, GL_FLOAT, 9, 9, 9, 0, 0, 0 },
+ { Format::ID::S8_UINT, GL_STENCIL_INDEX8, GL_STENCIL_INDEX8, nullptr, NoCopyFunctions, nullptr, GL_UNSIGNED_INT, 0, 0, 0, 0, 0, 8 },
+ // clang-format on
+};
+
+// static
+const Format &Format::Get(ID id)
+{
+ return g_formatInfoTable[static_cast<size_t>(id)];
+}
+
+} // namespace angle
diff --git a/gfx/angle/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h b/gfx/angle/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
new file mode 100755
index 000000000..5139ee5fd
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.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.
+//
+// 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/FramebufferAttachment.h"
+
+namespace rx
+{
+
+class FramebufferAttachmentObjectImpl : angle::NonCopyable
+{
+ public:
+ FramebufferAttachmentObjectImpl() {}
+ virtual ~FramebufferAttachmentObjectImpl() {}
+
+ virtual gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut)
+ {
+ UNIMPLEMENTED();
+ return gl::Error(GL_OUT_OF_MEMORY, "getAttachmentRenderTarget not supported.");
+ }
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_FRAMEBUFFER_ATTACHMENT_OBJECT_IMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/FramebufferImpl.h b/gfx/angle/src/libANGLE/renderer/FramebufferImpl.h
new file mode 100755
index 000000000..a61dbba53
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/FramebufferImpl.h
@@ -0,0 +1,83 @@
+//
+// 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"
+
+namespace gl
+{
+class State;
+class Framebuffer;
+class FramebufferAttachment;
+struct Rectangle;
+}
+
+namespace rx
+{
+
+class FramebufferImpl : angle::NonCopyable
+{
+ public:
+ explicit FramebufferImpl(const gl::FramebufferState &state) : mState(state) {}
+ virtual ~FramebufferImpl() { }
+
+ virtual gl::Error discard(size_t count, const GLenum *attachments) = 0;
+ virtual gl::Error invalidate(size_t count, const GLenum *attachments) = 0;
+ virtual gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) = 0;
+
+ virtual gl::Error clear(ContextImpl *context, GLbitfield mask) = 0;
+ virtual gl::Error clearBufferfv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values) = 0;
+ virtual gl::Error clearBufferuiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values) = 0;
+ virtual gl::Error clearBufferiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values) = 0;
+ virtual gl::Error clearBufferfi(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil) = 0;
+
+ virtual GLenum getImplementationColorReadFormat() const = 0;
+ virtual GLenum getImplementationColorReadType() const = 0;
+ virtual gl::Error readPixels(ContextImpl *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels) const = 0;
+
+ virtual gl::Error blit(ContextImpl *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter) = 0;
+
+ virtual bool checkStatus() const = 0;
+
+ virtual void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) = 0;
+
+ const gl::FramebufferState &getState() const { return mState; }
+
+ protected:
+ const gl::FramebufferState &mState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/FramebufferImpl_mock.h b/gfx/angle/src/libANGLE/renderer/FramebufferImpl_mock.h
new file mode 100755
index 000000000..9bf93db97
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/FramebufferImpl_mock.h
@@ -0,0 +1,67 @@
+//
+// 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.
+//
+// FramebufferImpl_mock.h:
+// Defines a mock of the FramebufferImpl class.
+//
+
+#ifndef LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_
+#define LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace rx
+{
+
+class MockFramebufferImpl : public rx::FramebufferImpl
+{
+ public:
+ MockFramebufferImpl() : rx::FramebufferImpl(gl::FramebufferState()) {}
+ virtual ~MockFramebufferImpl() { destroy(); }
+
+ MOCK_METHOD2(discard, gl::Error(size_t, const GLenum *));
+ MOCK_METHOD2(invalidate, gl::Error(size_t, const GLenum *));
+ MOCK_METHOD3(invalidateSub, gl::Error(size_t, const GLenum *, const gl::Rectangle &));
+
+ MOCK_METHOD2(clear, gl::Error(ContextImpl *, GLbitfield));
+ MOCK_METHOD4(clearBufferfv, gl::Error(ContextImpl *, GLenum, GLint, const GLfloat *));
+ MOCK_METHOD4(clearBufferuiv, gl::Error(ContextImpl *, GLenum, GLint, const GLuint *));
+ MOCK_METHOD4(clearBufferiv, gl::Error(ContextImpl *, GLenum, GLint, const GLint *));
+ MOCK_METHOD5(clearBufferfi, gl::Error(ContextImpl *, GLenum, GLint, GLfloat, GLint));
+
+ MOCK_CONST_METHOD0(getImplementationColorReadFormat, GLenum());
+ MOCK_CONST_METHOD0(getImplementationColorReadType, GLenum());
+ MOCK_CONST_METHOD5(readPixels,
+ gl::Error(ContextImpl *, const gl::Rectangle &, GLenum, GLenum, GLvoid *));
+
+ MOCK_METHOD5(
+ blit,
+ gl::Error(ContextImpl *, const gl::Rectangle &, const gl::Rectangle &, GLbitfield, GLenum));
+
+ MOCK_CONST_METHOD0(checkStatus, bool());
+
+ MOCK_METHOD1(syncState, void(const gl::Framebuffer::DirtyBits &));
+
+ MOCK_METHOD0(destroy, void());
+};
+
+inline ::testing::NiceMock<MockFramebufferImpl> *MakeFramebufferMock()
+{
+ ::testing::NiceMock<MockFramebufferImpl> *framebufferImpl =
+ new ::testing::NiceMock<MockFramebufferImpl>();
+ // TODO(jmadill): add ON_CALLS for other returning methods
+ ON_CALL(*framebufferImpl, checkStatus()).WillByDefault(::testing::Return(true));
+
+ // We must mock the destructor since NiceMock doesn't work for destructors.
+ EXPECT_CALL(*framebufferImpl, destroy()).Times(1).RetiresOnSaturation();
+
+ return framebufferImpl;
+}
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/GLImplFactory.h b/gfx/angle/src/libANGLE/renderer/GLImplFactory.h
new file mode 100755
index 000000000..20a48fc72
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/GLImplFactory.h
@@ -0,0 +1,88 @@
+//
+// 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/Program.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/VertexArray.h"
+
+namespace gl
+{
+class ContextState;
+}
+
+namespace rx
+{
+class BufferImpl;
+class CompilerImpl;
+class ContextImpl;
+class FenceNVImpl;
+class FenceSyncImpl;
+class FramebufferImpl;
+class PathImpl;
+class ProgramImpl;
+class QueryImpl;
+class RenderbufferImpl;
+class SamplerImpl;
+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() = 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(GLenum type) = 0;
+ virtual FenceNVImpl *createFenceNV() = 0;
+ virtual FenceSyncImpl *createFenceSync() = 0;
+
+ // Transform Feedback creation
+ virtual TransformFeedbackImpl *createTransformFeedback(
+ const gl::TransformFeedbackState &state) = 0;
+
+ // Sampler object creation
+ virtual SamplerImpl *createSampler() = 0;
+
+ virtual std::vector<PathImpl *> createPaths(GLsizei range) = 0;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GLIMPLFACTORY_H_
diff --git a/gfx/angle/src/libANGLE/renderer/ImageImpl.h b/gfx/angle/src/libANGLE/renderer/ImageImpl.h
new file mode 100755
index 000000000..e48f1946a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/ImageImpl.h
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 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"
+
+namespace egl
+{
+class ImageSibling;
+}
+
+namespace rx
+{
+class ImageImpl : angle::NonCopyable
+{
+ public:
+ virtual ~ImageImpl() {}
+ virtual egl::Error initialize() = 0;
+
+ virtual gl::Error orphan(egl::ImageSibling *sibling) = 0;
+};
+}
+
+#endif // LIBANGLE_RENDERER_IMAGEIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/ImageImpl_mock.h b/gfx/angle/src/libANGLE/renderer/ImageImpl_mock.h
new file mode 100755
index 000000000..27fe6a394
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/ImageImpl_mock.h
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 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_mock.h: Defines a mock of the ImageImpl class.
+
+#ifndef LIBANGLE_RENDERER_IMAGEIMPLMOCK_H_
+#define LIBANGLE_RENDERER_IMAGEIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace rx
+{
+class MockImageImpl : public ImageImpl
+{
+ public:
+ virtual ~MockImageImpl() { destructor(); }
+ MOCK_METHOD0(initialize, egl::Error(void));
+ MOCK_METHOD1(orphan, gl::Error(egl::ImageSibling *));
+ MOCK_METHOD0(destructor, void());
+};
+}
+
+#endif // LIBANGLE_RENDERER_IMAGEIMPLMOCK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/PathImpl.h b/gfx/angle/src/libANGLE/renderer/PathImpl.h
new file mode 100755
index 000000000..3607f69a2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/PathImpl.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// PathImpl.h: Defines the Path implementation interface for
+// CHROMIUM_path_rendering path objects.
+
+#ifndef LIBANGLE_RENDERER_PATHIMPL_H_
+#define LIBANGLE_RENDERER_PATHIMPL_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+namespace rx
+{
+
+class PathImpl : angle::NonCopyable
+{
+ public:
+ virtual ~PathImpl() {}
+
+ virtual gl::Error setCommands(GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords) = 0;
+
+ virtual void setPathParameter(GLenum pname, GLfloat value) = 0;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_PATHIMPL_H_ \ No newline at end of file
diff --git a/gfx/angle/src/libANGLE/renderer/ProgramImpl.h b/gfx/angle/src/libANGLE/renderer/ProgramImpl.h
new file mode 100755
index 000000000..065f6a338
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/ProgramImpl.h
@@ -0,0 +1,88 @@
+//
+// 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 sh
+{
+struct BlockMemberInfo;
+}
+
+namespace rx
+{
+using LinkResult = gl::ErrorOrResult<bool>;
+
+class ProgramImpl : angle::NonCopyable
+{
+ public:
+ ProgramImpl(const gl::ProgramState &state) : mState(state) {}
+ virtual ~ProgramImpl() {}
+
+ virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
+ virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
+ virtual void setBinaryRetrievableHint(bool retrievable) = 0;
+
+ virtual LinkResult link(const gl::ContextState &data, gl::InfoLog &infoLog) = 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;
+
+ // TODO: synchronize in syncState when dirty bits exist.
+ virtual void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0;
+
+ // May only be called after a successful link operation.
+ // Return false for inactive blocks.
+ virtual bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const = 0;
+
+ // May only be called after a successful link operation.
+ // Returns false for inactive members.
+ virtual bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const = 0;
+ // CHROMIUM_path_rendering
+ // Set parameters to control fragment shader input variable interpolation
+ virtual void setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs) = 0;
+
+ protected:
+ const gl::ProgramState &mState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_PROGRAMIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/ProgramImpl_mock.h b/gfx/angle/src/libANGLE/renderer/ProgramImpl_mock.h
new file mode 100755
index 000000000..1bc20bbef
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/ProgramImpl_mock.h
@@ -0,0 +1,77 @@
+//
+// 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.
+//
+// ProgramImpl_mock.h:
+// Defines a mock of the ProgramImpl class.
+//
+
+#ifndef LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_
+#define LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/ProgramImpl.h"
+
+namespace rx
+{
+
+class MockProgramImpl : public rx::ProgramImpl
+{
+ public:
+ MockProgramImpl() : ProgramImpl(gl::ProgramState()) {}
+ virtual ~MockProgramImpl() { destroy(); }
+
+ MOCK_METHOD2(load, LinkResult(gl::InfoLog &, gl::BinaryInputStream *));
+ MOCK_METHOD1(save, gl::Error(gl::BinaryOutputStream *));
+ MOCK_METHOD1(setBinaryRetrievableHint, void(bool));
+
+ MOCK_METHOD2(link, LinkResult(const gl::ContextState &, gl::InfoLog &));
+ MOCK_METHOD2(validate, GLboolean(const gl::Caps &, gl::InfoLog *));
+
+ MOCK_METHOD3(setUniform1fv, void(GLint, GLsizei, const GLfloat *));
+ MOCK_METHOD3(setUniform2fv, void(GLint, GLsizei, const GLfloat *));
+ MOCK_METHOD3(setUniform3fv, void(GLint, GLsizei, const GLfloat *));
+ MOCK_METHOD3(setUniform4fv, void(GLint, GLsizei, const GLfloat *));
+ MOCK_METHOD3(setUniform1iv, void(GLint, GLsizei, const GLint *));
+ MOCK_METHOD3(setUniform2iv, void(GLint, GLsizei, const GLint *));
+ MOCK_METHOD3(setUniform3iv, void(GLint, GLsizei, const GLint *));
+ MOCK_METHOD3(setUniform4iv, void(GLint, GLsizei, const GLint *));
+ MOCK_METHOD3(setUniform1uiv, void(GLint, GLsizei, const GLuint *));
+ MOCK_METHOD3(setUniform2uiv, void(GLint, GLsizei, const GLuint *));
+ MOCK_METHOD3(setUniform3uiv, void(GLint, GLsizei, const GLuint *));
+ MOCK_METHOD3(setUniform4uiv, void(GLint, GLsizei, const GLuint *));
+
+ MOCK_METHOD4(setUniformMatrix2fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix3fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix4fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix2x3fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix3x2fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix2x4fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix4x2fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix3x4fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix4x3fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+
+ MOCK_METHOD2(setUniformBlockBinding, void(GLuint, GLuint));
+ MOCK_CONST_METHOD2(getUniformBlockSize, bool(const std::string &, size_t *));
+ MOCK_CONST_METHOD2(getUniformBlockMemberInfo, bool(const std::string &, sh::BlockMemberInfo *));
+ MOCK_METHOD4(setPathFragmentInputGen,
+ void(const std::string &, GLenum, GLint, const GLfloat *));
+
+ MOCK_METHOD0(destroy, void());
+};
+
+inline ::testing::NiceMock<MockProgramImpl> *MakeProgramMock()
+{
+ ::testing::NiceMock<MockProgramImpl> *programImpl = new ::testing::NiceMock<MockProgramImpl>();
+ // TODO(jmadill): add ON_CALLS for returning methods
+ // We must mock the destructor since NiceMock doesn't work for destructors.
+ EXPECT_CALL(*programImpl, destroy()).Times(1).RetiresOnSaturation();
+
+ return programImpl;
+}
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/QueryImpl.h b/gfx/angle/src/libANGLE/renderer/QueryImpl.h
new file mode 100755
index 000000000..d738eb4ff
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/QueryImpl.h
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 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 "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+#include <GLES2/gl2.h>
+
+namespace rx
+{
+
+class QueryImpl : angle::NonCopyable
+{
+ public:
+ explicit QueryImpl(GLenum type) { mType = type; }
+ virtual ~QueryImpl() { }
+
+ virtual gl::Error begin() = 0;
+ virtual gl::Error end() = 0;
+ virtual gl::Error queryCounter() = 0;
+ virtual gl::Error getResult(GLint *params) = 0;
+ virtual gl::Error getResult(GLuint *params) = 0;
+ virtual gl::Error getResult(GLint64 *params) = 0;
+ virtual gl::Error getResult(GLuint64 *params) = 0;
+ virtual gl::Error isResultAvailable(bool *available) = 0;
+
+ GLenum getType() const { return mType; }
+
+ private:
+ GLenum mType;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_QUERYIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/RenderbufferImpl.h b/gfx/angle/src/libANGLE/renderer/RenderbufferImpl.h
new file mode 100755
index 000000000..3f8bad535
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/RenderbufferImpl.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 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/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace egl
+{
+class Image;
+}
+
+namespace rx
+{
+
+class RenderbufferImpl : public FramebufferAttachmentObjectImpl
+{
+ public:
+ RenderbufferImpl() {}
+ virtual ~RenderbufferImpl() {}
+
+ virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) = 0;
+ virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) = 0;
+ virtual gl::Error setStorageEGLImageTarget(egl::Image *image) = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h b/gfx/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h
new file mode 100755
index 000000000..c2c67cc76
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 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.
+//
+
+// RenderbufferImpl_mock.h: Defines a mock of the RenderbufferImpl class.
+
+#ifndef LIBANGLE_RENDERER_RENDERBUFFERIMPLMOCK_H_
+#define LIBANGLE_RENDERER_RENDERBUFFERIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/Image.h"
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+
+class MockRenderbufferImpl : public RenderbufferImpl
+{
+ public:
+ virtual ~MockRenderbufferImpl() { destructor(); }
+ MOCK_METHOD3(setStorage, gl::Error(GLenum, size_t, size_t));
+ MOCK_METHOD4(setStorageMultisample, gl::Error(size_t, GLenum, size_t, size_t));
+ MOCK_METHOD1(setStorageEGLImageTarget, gl::Error(egl::Image *));
+
+ MOCK_METHOD2(getAttachmentRenderTarget, gl::Error(const gl::FramebufferAttachment::Target &, FramebufferAttachmentRenderTarget **));
+
+ MOCK_METHOD0(destructor, void());
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_RENDERBUFFERIMPLMOCK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/SamplerImpl.h b/gfx/angle/src/libANGLE/renderer/SamplerImpl.h
new file mode 100755
index 000000000..85383cf8e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/SamplerImpl.h
@@ -0,0 +1,25 @@
+//
+// 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"
+
+namespace rx
+{
+
+class SamplerImpl : public angle::NonCopyable
+{
+ public:
+ SamplerImpl() {}
+ virtual ~SamplerImpl() {}
+};
+}
+
+#endif // LIBANGLE_RENDERER_SAMPLERIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/ShaderImpl.h b/gfx/angle/src/libANGLE/renderer/ShaderImpl.h
new file mode 100755
index 000000000..77e02d023
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/ShaderImpl.h
@@ -0,0 +1,40 @@
+//
+// 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 "common/angleutils.h"
+#include "libANGLE/Shader.h"
+
+namespace rx
+{
+
+class ShaderImpl : angle::NonCopyable
+{
+ public:
+ ShaderImpl(const gl::ShaderState &data) : mData(data) {}
+ virtual ~ShaderImpl() { }
+
+ // Returns additional sh::Compile options.
+ virtual ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string *sourcePath) = 0;
+ // Returns success for compiling on the driver. Returns success.
+ virtual bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) = 0;
+
+ virtual std::string getDebugInfo() const = 0;
+
+ const gl::ShaderState &getData() const { return mData; }
+
+ protected:
+ const gl::ShaderState &mData;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_SHADERIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/StreamProducerImpl.h b/gfx/angle/src/libANGLE/renderer/StreamProducerImpl.h
new file mode 100755
index 000000000..1915bf75d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/StreamProducerImpl.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 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 validateD3DNV12Texture(void *pointer) 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 postD3DNV12Texture(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/src/libANGLE/renderer/SurfaceImpl.cpp b/gfx/angle/src/libANGLE/renderer/SurfaceImpl.cpp
new file mode 100755
index 000000000..e4b3d7c8b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/SurfaceImpl.cpp
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 2002-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.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::swapWithDamage(EGLint *rects, EGLint n_rects)
+{
+ UNREACHABLE();
+ return egl::Error(EGL_BAD_SURFACE, "swapWithDamage implementation missing.");
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/SurfaceImpl.h b/gfx/angle/src/libANGLE/renderer/SurfaceImpl.h
new file mode 100755
index 000000000..177e788d8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/SurfaceImpl.h
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 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 "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace gl
+{
+class FramebufferState;
+}
+
+namespace egl
+{
+class Display;
+struct Config;
+struct SurfaceState;
+}
+
+namespace rx
+{
+class FramebufferImpl;
+
+class SurfaceImpl : public FramebufferAttachmentObjectImpl
+{
+ public:
+ SurfaceImpl(const egl::SurfaceState &surfaceState);
+ virtual ~SurfaceImpl();
+
+ virtual egl::Error initialize() = 0;
+ virtual FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) = 0;
+ virtual egl::Error swap() = 0;
+ virtual egl::Error swapWithDamage(EGLint *rects, EGLint n_rects);
+ virtual egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
+ virtual egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) = 0;
+ virtual egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) = 0;
+ virtual egl::Error releaseTexImage(EGLint buffer) = 0;
+ virtual void setSwapInterval(EGLint interval) = 0;
+
+ // width and height can change with client window resizing
+ virtual EGLint getWidth() const = 0;
+ virtual EGLint getHeight() const = 0;
+
+ virtual EGLint isPostSubBufferSupported() const = 0;
+ virtual EGLint getSwapBehavior() const = 0;
+
+ protected:
+ const egl::SurfaceState &mState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_SURFACEIMPL_H_
+
diff --git a/gfx/angle/src/libANGLE/renderer/TextureImpl.cpp b/gfx/angle/src/libANGLE/renderer/TextureImpl.cpp
new file mode 100755
index 000000000..af4796371
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/TextureImpl.cpp
@@ -0,0 +1,50 @@
+//
+// 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()
+{
+}
+
+gl::Error TextureImpl::copyTexture(GLenum internalFormat,
+ GLenum type,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION, "CHROMIUM_copy_texture exposed but not implemented.");
+}
+
+gl::Error TextureImpl::copySubTexture(const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION, "CHROMIUM_copy_texture exposed but not implemented.");
+}
+
+gl::Error TextureImpl::copyCompressedTexture(const gl::Texture *source)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION,
+ "CHROMIUM_copy_compressed_texture exposed but not implemented.");
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/TextureImpl.h b/gfx/angle/src/libANGLE/renderer/TextureImpl.h
new file mode 100755
index 000000000..7d0ebe2f1
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/TextureImpl.h
@@ -0,0 +1,101 @@
+//
+// 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/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace egl
+{
+class Surface;
+class Image;
+}
+
+namespace gl
+{
+struct Box;
+struct Extents;
+struct Offset;
+struct Rectangle;
+class Framebuffer;
+struct PixelUnpackState;
+struct TextureState;
+}
+
+namespace rx
+{
+
+class TextureImpl : public FramebufferAttachmentObjectImpl
+{
+ public:
+ TextureImpl(const gl::TextureState &state);
+ virtual ~TextureImpl();
+
+ virtual gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0;
+ virtual gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0;
+
+ virtual gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) = 0;
+ virtual gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) = 0;
+
+ virtual gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source) = 0;
+ virtual gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) = 0;
+
+ virtual gl::Error copyTexture(GLenum internalFormat,
+ GLenum type,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source);
+ virtual gl::Error copySubTexture(const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source);
+
+ virtual gl::Error copyCompressedTexture(const gl::Texture *source);
+
+ virtual gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) = 0;
+
+ virtual gl::Error setEGLImageTarget(GLenum target, egl::Image *image) = 0;
+
+ virtual gl::Error setImageExternal(GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) = 0;
+
+ virtual gl::Error generateMipmap() = 0;
+
+ virtual void setBaseLevel(GLuint baseLevel) = 0;
+
+ virtual void bindTexImage(egl::Surface *surface) = 0;
+ virtual void releaseTexImage() = 0;
+
+ virtual void syncState(const gl::Texture::DirtyBits &dirtyBits) = 0;
+
+ protected:
+ const gl::TextureState &mState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_TEXTUREIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/TextureImpl_mock.h b/gfx/angle/src/libANGLE/renderer/TextureImpl_mock.h
new file mode 100755
index 000000000..c8d05d202
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/TextureImpl_mock.h
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 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.
+//
+
+// TextureImpl_mock.h: Defines a mock of the TextureImpl class.
+
+#ifndef LIBANGLE_RENDERER_TEXTUREIMPLMOCK_H_
+#define LIBANGLE_RENDERER_TEXTUREIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace rx
+{
+
+class MockTextureImpl : public TextureImpl
+{
+ public:
+ MockTextureImpl() : TextureImpl(mMockState), mMockState(GL_TEXTURE_2D) {}
+ virtual ~MockTextureImpl() { destructor(); }
+ MOCK_METHOD8(setImage, gl::Error(GLenum, size_t, GLenum, const gl::Extents &, GLenum, GLenum, const gl::PixelUnpackState &, const uint8_t *));
+ MOCK_METHOD7(setSubImage, gl::Error(GLenum, size_t, const gl::Box &, GLenum, GLenum, const gl::PixelUnpackState &, const uint8_t *));
+ MOCK_METHOD7(setCompressedImage, gl::Error(GLenum, size_t, GLenum, const gl::Extents &, const gl::PixelUnpackState &, size_t, const uint8_t *));
+ MOCK_METHOD7(setCompressedSubImage, gl::Error(GLenum, size_t, const gl::Box &, GLenum, const gl::PixelUnpackState &, size_t, const uint8_t *));
+ MOCK_METHOD5(copyImage, gl::Error(GLenum, size_t, const gl::Rectangle &, GLenum, const gl::Framebuffer *));
+ MOCK_METHOD5(copySubImage, gl::Error(GLenum, size_t, const gl::Offset &, const gl::Rectangle &, const gl::Framebuffer *));
+ MOCK_METHOD6(copyTexture, gl::Error(GLenum, GLenum, bool, bool, bool, const gl::Texture *));
+ MOCK_METHOD6(copySubTexture,
+ gl::Error(const gl::Offset &,
+ const gl::Rectangle &,
+ bool,
+ bool,
+ bool,
+ const gl::Texture *));
+ MOCK_METHOD1(copyCompressedTexture, gl::Error(const gl::Texture *source));
+ MOCK_METHOD4(setStorage, gl::Error(GLenum, size_t, GLenum, const gl::Extents &));
+ MOCK_METHOD3(setImageExternal,
+ gl::Error(GLenum, egl::Stream *, const egl::Stream::GLTextureDescription &));
+ MOCK_METHOD2(setEGLImageTarget, gl::Error(GLenum, egl::Image *));
+ MOCK_METHOD0(generateMipmap, gl::Error());
+ MOCK_METHOD1(bindTexImage, void(egl::Surface *));
+ MOCK_METHOD0(releaseTexImage, void(void));
+
+ MOCK_METHOD2(getAttachmentRenderTarget, gl::Error(const gl::FramebufferAttachment::Target &, FramebufferAttachmentRenderTarget **));
+
+ MOCK_METHOD1(setBaseLevel, void(GLuint));
+
+ MOCK_METHOD1(syncState, void(const gl::Texture::DirtyBits &));
+
+ MOCK_METHOD0(destructor, void());
+
+ protected:
+ gl::TextureState mMockState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_TEXTUREIMPLMOCK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/TransformFeedbackImpl.h b/gfx/angle/src/libANGLE/renderer/TransformFeedbackImpl.h
new file mode 100755
index 000000000..71e6374e7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/TransformFeedbackImpl.h
@@ -0,0 +1,38 @@
+//
+// 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 begin(GLenum primitiveMode) = 0;
+ virtual void end() = 0;
+ virtual void pause() = 0;
+ virtual void resume() = 0;
+
+ virtual void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) = 0;
+ virtual void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) = 0;
+
+ protected:
+ const gl::TransformFeedbackState &mState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h b/gfx/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h
new file mode 100755
index 000000000..18832acc7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 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.
+//
+
+// TransformFeedbackImpl_mock.h: Defines a mock of the TransformFeedbackImpl class.
+
+#ifndef LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPLMOCK_H_
+#define LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace rx
+{
+
+class MockTransformFeedbackImpl : public TransformFeedbackImpl
+{
+ public:
+ MockTransformFeedbackImpl(const gl::TransformFeedbackState &state)
+ : TransformFeedbackImpl(state)
+ {
+ }
+ ~MockTransformFeedbackImpl() { destructor(); }
+
+ MOCK_METHOD1(begin, void(GLenum primitiveMode));
+ MOCK_METHOD0(end, void());
+ MOCK_METHOD0(pause, void());
+ MOCK_METHOD0(resume, void());
+
+ MOCK_METHOD1(bindGenericBuffer, void(const BindingPointer<gl::Buffer> &));
+ MOCK_METHOD2(bindIndexedBuffer, void(size_t, const OffsetBindingPointer<gl::Buffer> &));
+
+ MOCK_METHOD0(destructor, void());
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPLMOCK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/VertexArrayImpl.h b/gfx/angle/src/libANGLE/renderer/VertexArrayImpl.h
new file mode 100755
index 000000000..b1be3691a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/VertexArrayImpl.h
@@ -0,0 +1,31 @@
+//
+// 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"
+
+namespace rx
+{
+
+class VertexArrayImpl : angle::NonCopyable
+{
+ public:
+ VertexArrayImpl(const gl::VertexArrayState &data) : mData(data) {}
+ virtual ~VertexArrayImpl() { }
+ virtual void syncState(const gl::VertexArray::DirtyBits &dirtyBits) {}
+ protected:
+ const gl::VertexArrayState &mData;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/angle_format.py b/gfx/angle/src/libANGLE/renderer/angle_format.py
new file mode 100755
index 000000000..e46bc7dba
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/angle_format.py
@@ -0,0 +1,45 @@
+#!/usr/bin/python
+# 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.
+#
+# angle_format.py:
+# Utils for ANGLE formats.
+
+import json
+import os
+
+def reject_duplicate_keys(pairs):
+ found_keys = {}
+ for key, value in pairs:
+ if key in found_keys:
+ raise ValueError("duplicate key: %r" % (key,))
+ else:
+ found_keys[key] = value
+ return found_keys
+
+def load_json(path):
+ with open(path) as map_file:
+ file_data = map_file.read()
+ map_file.close()
+ return json.loads(file_data, object_pairs_hook=reject_duplicate_keys)
+
+def load_forward_table(path):
+ pairs = load_json(path)
+ reject_duplicate_keys(pairs)
+ return { gl: angle for gl, angle in pairs }
+
+def load_inverse_table(path):
+ pairs = load_json(path)
+ reject_duplicate_keys(pairs)
+ return { angle: gl for gl, angle in pairs }
+
+def load_with_override(override_path):
+ map_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'angle_format_map.json')
+ results = load_forward_table(map_path)
+ overrides = load_json(override_path)
+
+ for k, v in overrides.iteritems():
+ results[k] = v
+
+ return results
diff --git a/gfx/angle/src/libANGLE/renderer/angle_format_data.json b/gfx/angle/src/libANGLE/renderer/angle_format_data.json
new file mode 100755
index 000000000..b243520d2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/angle_format_data.json
@@ -0,0 +1,21 @@
+{
+ "B5G6R5_UNORM": {
+ "fboImplementationInternalFormat": "GL_RGB565"
+ },
+ "B5G5R5A1_UNORM": {
+ "fboImplementationInternalFormat": "GL_RGB5_A1",
+ "channelStruct": "A1R5G5B5"
+ },
+ "B8G8R8X8_UNORM": {
+ "glInternalFormat": "GL_BGRA8_EXT",
+ "channelStruct": "B8G8R8X8"
+ },
+ "R9G9B9E5_SHAREDEXP": {
+ "componentType": "float",
+ "channelStruct": "R9G9B9E5"
+ },
+ "B4G4R4A4_UNORM": {
+ "fboImplementationInternalFormat": "GL_RGBA4",
+ "channelStruct": "A4R4G4B4"
+ }
+}
diff --git a/gfx/angle/src/libANGLE/renderer/angle_format_map.json b/gfx/angle/src/libANGLE/renderer/angle_format_map.json
new file mode 100755
index 000000000..064c400ac
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/angle_format_map.json
@@ -0,0 +1,127 @@
+[
+ [ "GL_ALPHA16F_EXT", "A16_FLOAT" ],
+ [ "GL_ALPHA32F_EXT", "A32_FLOAT" ],
+ [ "GL_ALPHA8_EXT", "A8_UNORM" ],
+ [ "GL_BGR565_ANGLEX", "B5G6R5_UNORM" ],
+ [ "GL_BGR5_A1_ANGLEX", "B5G5R5A1_UNORM" ],
+ [ "GL_BGRA4_ANGLEX", "B4G4R4A4_UNORM" ],
+ [ "GL_BGRA8_EXT", "B8G8R8A8_UNORM" ],
+ [ "GL_BGRX8_ANGLEX", "B8G8R8X8_UNORM" ],
+ [ "GL_COMPRESSED_R11_EAC", "EAC_R11_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RG11_EAC", "EAC_R11G11_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGB8_ETC2", "ETC2_R8G8B8_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2", "ETC2_R8G8B8A1_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA8_ETC2_EAC", "ETC2_R8G8B8A8_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT", "BC1_RGBA_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE", "BC2_RGBA_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE", "BC3_RGBA_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_4x4_KHR", "ASTC_4x4_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_5x4_KHR", "ASTC_5x4_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_5x5_KHR", "ASTC_5x5_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_6x5_KHR", "ASTC_6x5_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_6x6_KHR", "ASTC_6x6_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_8x5_KHR", "ASTC_8x5_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_8x6_KHR", "ASTC_8x6_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_8x8_KHR", "ASTC_8x8_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_10x5_KHR", "ASTC_10x5_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_10x6_KHR", "ASTC_10x6_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_10x8_KHR", "ASTC_10x8_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_10x10_KHR", "ASTC_10x10_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_12x10_KHR", "ASTC_12x10_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_12x12_KHR", "ASTC_12x12_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGB_S3TC_DXT1_EXT", "BC1_RGB_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_SIGNED_R11_EAC", "EAC_R11_SNORM_BLOCK" ],
+ [ "GL_COMPRESSED_SIGNED_RG11_EAC", "EAC_R11G11_SNORM_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR", "ASTC_4x4_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR", "ASTC_5x4_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR", "ASTC_5x5_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR", "ASTC_6x5_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR", "ASTC_6x6_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR", "ASTC_8x5_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR", "ASTC_8x6_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR", "ASTC_8x8_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR", "ASTC_10x5_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR", "ASTC_10x6_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR", "ASTC_10x8_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR", "ASTC_10x10_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR", "ASTC_12x10_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR", "ASTC_12x12_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC", "ETC2_R8G8B8A8_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ETC2", "ETC2_R8G8B8_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2", "ETC2_R8G8B8A1_SRGB_BLOCK" ],
+ [ "GL_DEPTH24_STENCIL8", "D24_UNORM_S8_UINT" ],
+ [ "GL_DEPTH32F_STENCIL8", "D32_FLOAT_S8X24_UINT" ],
+ [ "GL_DEPTH_COMPONENT16", "D16_UNORM" ],
+ [ "GL_DEPTH_COMPONENT24", "D24_UNORM" ],
+ [ "GL_DEPTH_COMPONENT32F", "D32_FLOAT" ],
+ [ "GL_DEPTH_COMPONENT32_OES", "D32_UNORM" ],
+ [ "GL_ETC1_RGB8_OES", "NONE" ],
+ [ "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE", "NONE" ],
+ [ "GL_LUMINANCE16F_EXT", "L16_FLOAT" ],
+ [ "GL_LUMINANCE32F_EXT", "L32_FLOAT" ],
+ [ "GL_LUMINANCE8_ALPHA8_EXT", "L8A8_UNORM" ],
+ [ "GL_LUMINANCE8_EXT", "L8_UNORM" ],
+ [ "GL_LUMINANCE_ALPHA16F_EXT", "L16A16_FLOAT" ],
+ [ "GL_LUMINANCE_ALPHA32F_EXT", "L32A32_FLOAT" ],
+ [ "GL_NONE", "NONE" ],
+ [ "GL_R11F_G11F_B10F", "R11G11B10_FLOAT" ],
+ [ "GL_R16F", "R16_FLOAT" ],
+ [ "GL_R16I", "R16_SINT" ],
+ [ "GL_R16UI", "R16_UINT" ],
+ [ "GL_R32F", "R32_FLOAT" ],
+ [ "GL_R32I", "R32_SINT" ],
+ [ "GL_R32UI", "R32_UINT" ],
+ [ "GL_R8", "R8_UNORM" ],
+ [ "GL_R8I", "R8_SINT" ],
+ [ "GL_R8UI", "R8_UINT" ],
+ [ "GL_R8_SNORM", "R8_SNORM" ],
+ [ "GL_RG16F", "R16G16_FLOAT" ],
+ [ "GL_RG16I", "R16G16_SINT" ],
+ [ "GL_RG16UI", "R16G16_UINT" ],
+ [ "GL_RG32F", "R32G32_FLOAT" ],
+ [ "GL_RG32I", "R32G32_SINT" ],
+ [ "GL_RG32UI", "R32G32_UINT" ],
+ [ "GL_RG8", "R8G8_UNORM" ],
+ [ "GL_RG8I", "R8G8_SINT" ],
+ [ "GL_RG8UI", "R8G8_UINT" ],
+ [ "GL_RG8_SNORM", "R8G8_SNORM" ],
+ [ "GL_RGB", "R8G8B8_UNORM" ],
+ [ "GL_RGB10_A2", "R10G10B10A2_UNORM" ],
+ [ "GL_RGB10_A2UI", "R10G10B10A2_UINT" ],
+ [ "GL_RGB16F", "R16G16B16_FLOAT" ],
+ [ "GL_RGB16I", "R16G16B16_SINT" ],
+ [ "GL_RGB16UI", "R16G16B16_UINT" ],
+ [ "GL_RGB32F", "R32G32B32_FLOAT" ],
+ [ "GL_RGB32I", "R32G32B32_SINT" ],
+ [ "GL_RGB32UI", "R32G32B32_UINT" ],
+ [ "GL_RGB565", "R5G6B5_UNORM" ],
+ [ "GL_RGB5_A1", "R5G5B5A1_UNORM" ],
+ [ "GL_RGB8", "R8G8B8_UNORM" ],
+ [ "GL_RGB8I", "R8G8B8_SINT" ],
+ [ "GL_RGB8UI", "R8G8B8_UINT" ],
+ [ "GL_RGB8_SNORM", "R8G8B8_SNORM" ],
+ [ "GL_RGB9_E5", "R9G9B9E5_SHAREDEXP" ],
+ [ "GL_RGBA", "R8G8B8A8_UNORM" ],
+ [ "GL_RGBA16F", "R16G16B16A16_FLOAT" ],
+ [ "GL_RGBA16I", "R16G16B16A16_SINT" ],
+ [ "GL_RGBA16UI", "R16G16B16A16_UINT" ],
+ [ "GL_RGBA32F", "R32G32B32A32_FLOAT" ],
+ [ "GL_RGBA32I", "R32G32B32A32_SINT" ],
+ [ "GL_RGBA32UI", "R32G32B32A32_UINT" ],
+ [ "GL_RGBA4", "R4G4B4A4_UNORM" ],
+ [ "GL_RGBA8", "R8G8B8A8_UNORM" ],
+ [ "GL_RGBA8I", "R8G8B8A8_SINT" ],
+ [ "GL_RGBA8UI", "R8G8B8A8_UINT" ],
+ [ "GL_RGBA8_SNORM", "R8G8B8A8_SNORM" ],
+ [ "GL_SRGB8", "R8G8B8_UNORM_SRGB" ],
+ [ "GL_SRGB8_ALPHA8", "R8G8B8A8_UNORM_SRGB" ],
+ [ "GL_STENCIL_INDEX8", "S8_UINT" ],
+ [ "GL_R16_EXT", "R16_UNORM" ],
+ [ "GL_RG16_EXT", "R16G16_UNORM" ],
+ [ "GL_RGB16_EXT", "R16G16B16_UNORM" ],
+ [ "GL_RGBA16_EXT", "R16G16B16A16_UNORM" ],
+ [ "GL_R16_SNORM_EXT", "R16_SNORM" ],
+ [ "GL_RG16_SNORM_EXT", "R16G16_SNORM" ],
+ [ "GL_RGB16_SNORM_EXT", "R16G16B16_SNORM" ],
+ [ "GL_RGBA16_SNORM_EXT", "R16G16B16A16_SNORM" ]
+]
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp
new file mode 100755
index 000000000..250162726
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp
@@ -0,0 +1,188 @@
+//
+// 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/VertexBuffer.h"
+#include "libANGLE/renderer/d3d/RendererD3D.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(GLenum usage)
+{
+ switch (usage)
+ {
+ case GL_STATIC_DRAW:
+ case GL_STATIC_READ:
+ case GL_STATIC_COPY:
+ mUsage = D3DBufferUsage::STATIC;
+ initializeStaticData();
+ break;
+
+ case GL_STREAM_DRAW:
+ case GL_STREAM_READ:
+ case GL_STREAM_COPY:
+ case GL_DYNAMIC_READ:
+ case GL_DYNAMIC_COPY:
+ case GL_DYNAMIC_DRAW:
+ mUsage = D3DBufferUsage::DYNAMIC;
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+void BufferD3D::initializeStaticData()
+{
+ if (mStaticVertexBuffers.empty())
+ {
+ auto 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)
+{
+ 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))
+ {
+ 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.
+ auto newStaticBuffer = new StaticVertexBufferInterface(mFactory);
+ newStaticBuffer->setAttribute(attribute);
+ mStaticVertexBuffers.push_back(std::unique_ptr<StaticVertexBufferInterface>(newStaticBuffer));
+ return newStaticBuffer;
+}
+
+void BufferD3D::invalidateStaticData()
+{
+ 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();
+ }
+
+ mUnmodifiedDataUse = 0;
+}
+
+// Creates static buffers if sufficient used data has been left unmodified
+void BufferD3D::promoteStaticUsage(int dataSize)
+{
+ if (mUsage == D3DBufferUsage::DYNAMIC)
+ {
+ mUnmodifiedDataUse += dataSize;
+
+ if (mUnmodifiedDataUse > 3 * getSize())
+ {
+ updateD3DBufferUsage(GL_STATIC_DRAW);
+ }
+ }
+}
+
+gl::Error BufferD3D::getIndexRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ gl::IndexRange *outRange)
+{
+ const uint8_t *data = nullptr;
+ ANGLE_TRY(getData(&data));
+
+ *outRange = gl::ComputeIndexRange(type, data + offset, count, primitiveRestartEnabled);
+ return gl::Error(GL_NO_ERROR);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/BufferD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/BufferD3D.h
new file mode 100755
index 000000000..fdabe7b7e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/BufferD3D.h
@@ -0,0 +1,79 @@
+//
+// 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 rx
+{
+class BufferFactoryD3D;
+class StaticIndexBufferInterface;
+class StaticVertexBufferInterface;
+
+enum class D3DBufferUsage
+{
+ STATIC,
+ DYNAMIC,
+};
+
+class BufferD3D : public BufferImpl
+{
+ public:
+ BufferD3D(const gl::BufferState &state, BufferFactoryD3D *factory);
+ virtual ~BufferD3D();
+
+ unsigned int getSerial() const { return mSerial; }
+
+ virtual size_t getSize() const = 0;
+ virtual bool supportsDirectBinding() const = 0;
+ virtual gl::Error markTransformFeedbackUsage() = 0;
+ virtual gl::Error getData(const uint8_t **outData) = 0;
+
+ StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute);
+ StaticIndexBufferInterface *getStaticIndexBuffer();
+
+ virtual void initializeStaticData();
+ virtual void invalidateStaticData();
+
+ void promoteStaticUsage(int dataSize);
+
+ gl::Error getIndexRange(GLenum 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(GLenum 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;
+ unsigned int mUnmodifiedDataUse;
+ D3DBufferUsage mUsage;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_BUFFERD3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp
new file mode 100755
index 000000000..6f8d1717c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp
@@ -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.
+//
+// CompilerD3D:
+// Implementation of the D3D compiler methods.
+//
+
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+
+namespace rx
+{
+
+CompilerD3D::CompilerD3D(ShShaderOutput translatorOutputType)
+ : mTranslatorOutputType(translatorOutputType)
+{
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.h
new file mode 100755
index 000000000..8f4334963
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 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 {}
+
+ gl::Error release() override { return gl::Error(GL_NO_ERROR); }
+ ShShaderOutput getTranslatorOutputType() const override { return mTranslatorOutputType; }
+
+ private:
+ ShShaderOutput mTranslatorOutputType;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_COMPILERD3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp
new file mode 100755
index 000000000..f40e6e6ca
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp
@@ -0,0 +1,102 @@
+//
+// Copyright (c) 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/renderer/d3d/RendererD3D.h"
+
+#include "libANGLE/Device.h"
+#include "libANGLE/Display.h"
+
+#include <EGL/eglext.h>
+
+namespace rx
+{
+
+DeviceD3D::DeviceD3D()
+ : mDevice(0), mDeviceType(0), mDeviceExternallySourced(false), mIsInitialized(false)
+{
+}
+
+DeviceD3D::~DeviceD3D()
+{
+#if defined(ANGLE_ENABLE_D3D11)
+ if (mDeviceType == EGL_D3D11_DEVICE_ANGLE)
+ {
+ // DeviceD3D holds a ref to an externally-sourced D3D11 device. We must release it.
+ ID3D11Device *device = reinterpret_cast<ID3D11Device *>(mDevice);
+ device->Release();
+ }
+#endif
+}
+
+egl::Error DeviceD3D::getDevice(void **outValue)
+{
+ if (!mIsInitialized)
+ {
+ *outValue = nullptr;
+ return egl::Error(EGL_BAD_DEVICE_EXT);
+ }
+
+ *outValue = mDevice;
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DeviceD3D::initialize(void *device,
+ EGLint deviceType,
+ EGLBoolean deviceExternallySourced)
+{
+ ASSERT(!mIsInitialized);
+ if (mIsInitialized)
+ {
+ return egl::Error(EGL_BAD_DEVICE_EXT);
+ }
+
+ mDevice = device;
+ mDeviceType = deviceType;
+ mDeviceExternallySourced = !!deviceExternallySourced;
+
+#if defined(ANGLE_ENABLE_D3D11)
+ if (mDeviceType == EGL_D3D11_DEVICE_ANGLE)
+ {
+ // Validate the device
+ IUnknown *iunknown = reinterpret_cast<IUnknown *>(device);
+
+ ID3D11Device *d3dDevice = nullptr;
+ HRESULT hr =
+ iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void **>(&d3dDevice));
+ if (FAILED(hr))
+ {
+ return egl::Error(EGL_BAD_ATTRIBUTE, "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.
+ }
+ else
+#endif
+ {
+ ASSERT(!mDeviceExternallySourced);
+ }
+
+ mIsInitialized = true;
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+EGLint DeviceD3D::getType()
+{
+ return mDeviceType;
+}
+
+void DeviceD3D::generateExtensions(egl::DeviceExtensions *outExtensions) const
+{
+ outExtensions->deviceD3D = true;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.h
new file mode 100755
index 000000000..1dd997970
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/DeviceD3D.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 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();
+ ~DeviceD3D() override;
+
+ egl::Error initialize(void *device, EGLint deviceType, EGLBoolean external);
+ egl::Error getDevice(void **outValue) override;
+ EGLint getType() override;
+ void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
+ bool deviceExternallySourced() override { return mDeviceExternallySourced; }
+
+ private:
+ void *mDevice;
+ EGLint mDeviceType;
+ bool mDeviceExternallySourced;
+ bool mIsInitialized;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_DEVICED3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
new file mode 100755
index 000000000..474a08c65
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
@@ -0,0 +1,371 @@
+//
+// Copyright (c) 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/Context.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/histogram_macros.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"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+
+#if defined (ANGLE_ENABLE_D3D9)
+# include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#endif // ANGLE_ENABLE_D3D9
+
+#if defined (ANGLE_ENABLE_D3D11)
+# include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#endif // ANGLE_ENABLE_D3D11
+
+#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
+{
+
+typedef RendererD3D *(*CreateRendererD3DFunction)(egl::Display*);
+
+template <typename RendererType>
+static RendererD3D *CreateTypedRendererD3D(egl::Display *display)
+{
+ return new RendererType(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)
+ if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+ nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE ||
+ requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
+ }
+# endif
+
+# if defined(ANGLE_ENABLE_D3D9)
+ if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+ requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
+ {
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
+ }
+# 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(CreateTypedRendererD3D<Renderer11>);
+# endif
+# if defined(ANGLE_ENABLE_D3D9)
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
+# endif
+# else
+# if defined(ANGLE_ENABLE_D3D9)
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
+# endif
+# if defined(ANGLE_ENABLE_D3D11)
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
+# 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(CreateTypedRendererD3D<Renderer11>);
+ }
+#endif
+ }
+ else
+ {
+ UNIMPLEMENTED();
+ }
+
+ egl::Error result(EGL_NOT_INITIALIZED, "No available renderers.");
+ for (size_t i = 0; i < rendererCreationFunctions.size(); i++)
+ {
+ RendererD3D *renderer = rendererCreationFunctions[i](display);
+ 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;
+ break;
+ }
+ else
+ {
+ // Failed to create the renderer, try the next
+ SafeDelete(renderer);
+ }
+ }
+
+ return result;
+}
+
+DisplayD3D::DisplayD3D() : mRenderer(nullptr)
+{
+}
+
+SurfaceImpl *DisplayD3D::createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(mRenderer != nullptr);
+ return new WindowSurfaceD3D(state, mRenderer, mDisplay, configuration, window, attribs);
+}
+
+SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(mRenderer != nullptr);
+ return new PbufferSurfaceD3D(state, mRenderer, mDisplay, configuration, 0, nullptr, attribs);
+}
+
+SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(mRenderer != nullptr);
+ return new PbufferSurfaceD3D(state, mRenderer, mDisplay, configuration, buftype, clientBuffer,
+ attribs);
+}
+
+SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+ImageImpl *DisplayD3D::createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs)
+{
+ return new EGLImageD3D(mRenderer, target, buffer, attribs);
+}
+
+egl::Error DisplayD3D::getDevice(DeviceImpl **device)
+{
+ return mRenderer->getEGLDevice(device);
+}
+
+ContextImpl *DisplayD3D::createContext(const gl::ContextState &state)
+{
+ ASSERT(mRenderer != nullptr);
+ return mRenderer->createContext(state);
+}
+
+StreamProducerImpl *DisplayD3D::createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(mRenderer != nullptr);
+ return mRenderer->createStreamProducerD3DTextureNV12(consumerType, attribs);
+}
+
+egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayD3D::initialize(egl::Display *display)
+{
+ ASSERT(mRenderer == nullptr && display != nullptr);
+ mDisplay = display;
+ ANGLE_TRY(CreateRendererD3D(display, &mRenderer));
+ return egl::Error(EGL_SUCCESS);
+}
+
+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()
+{
+ // Release surface resources to make the Reset() succeed
+ for (auto &surface : mSurfaceSet)
+ {
+ if (surface->getBoundTexture())
+ {
+ surface->releaseTexImage(EGL_BACK_BUFFER);
+ }
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ surfaceD3D->releaseSwapChain();
+ }
+
+ if (!mRenderer->resetDevice())
+ {
+ return egl::Error(EGL_BAD_ALLOC);
+ }
+
+ // Restore any surfaces that may have been lost
+ for (const auto &surface : mSurfaceSet)
+ {
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+
+ egl::Error error = surfaceD3D->resetSwapChain();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return mRenderer->isValidNativeWindow(window);
+}
+
+egl::Error DisplayD3D::validateClientBuffer(const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ switch (buftype)
+ {
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ return mRenderer->validateShareHandle(configuration, static_cast<HANDLE>(clientBuffer),
+ attribs);
+
+ case EGL_D3D_TEXTURE_ANGLE:
+ return mRenderer->getD3DTextureInfo(static_cast<IUnknown *>(clientBuffer), nullptr,
+ nullptr, nullptr);
+
+ default:
+ return DisplayImpl::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
+ }
+}
+
+void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ mRenderer->generateDisplayExtensions(outExtensions);
+}
+
+std::string DisplayD3D::getVendorString() const
+{
+ std::string vendorString = "Google Inc.";
+ if (mRenderer)
+ {
+ vendorString += " " + mRenderer->getVendorString();
+ }
+
+ return vendorString;
+}
+
+void DisplayD3D::generateCaps(egl::Caps *outCaps) const
+{
+ // Display must be initialized to generate caps
+ ASSERT(mRenderer != nullptr);
+
+ outCaps->textureNPOT = mRenderer->getNativeExtensions().textureNPOT;
+}
+
+egl::Error DisplayD3D::waitClient() const
+{
+ for (auto &surface : getSurfaceSet())
+ {
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ surfaceD3D->checkForOutOfDateSwapChain();
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayD3D::waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const
+{
+ if (drawSurface != nullptr)
+ {
+ SurfaceD3D *drawSurfaceD3D = GetImplAs<SurfaceD3D>(drawSurface);
+ drawSurfaceD3D->checkForOutOfDateSwapChain();
+ }
+
+ if (readSurface != nullptr)
+ {
+ SurfaceD3D *readurfaceD3D = GetImplAs<SurfaceD3D>(readSurface);
+ readurfaceD3D->checkForOutOfDateSwapChain();
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+gl::Version DisplayD3D::getMaxSupportedESVersion() const
+{
+ return mRenderer->getMaxSupportedESVersion();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
new file mode 100755
index 000000000..3801a8eb1
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 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/renderer/DisplayImpl.h"
+#include "libANGLE/Device.h"
+
+namespace rx
+{
+class RendererD3D;
+
+class DisplayD3D : public DisplayImpl
+{
+ public:
+ DisplayD3D();
+
+ egl::Error initialize(egl::Display *display) override;
+ virtual void terminate() override;
+
+ // Surface creation
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ ImageImpl *createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs) override;
+
+ ContextImpl *createContext(const gl::ContextState &state) override;
+
+ StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) override;
+
+ egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() 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 getDevice(DeviceImpl **device) override;
+
+ std::string getVendorString() const override;
+
+ egl::Error waitClient() const override;
+ egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const override;
+ gl::Version getMaxSupportedESVersion() const override;
+
+ private:
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+ void generateCaps(egl::Caps *outCaps) const override;
+
+ egl::Display *mDisplay;
+
+ rx::RendererD3D *mRenderer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
new file mode 100755
index 000000000..1946585c1
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
@@ -0,0 +1,1087 @@
+//
+// Copyright (c) 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/utilities.h"
+#include "compiler/translator/blocklayoutHLSL.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/VaryingPacking.h"
+
+using namespace gl;
+
+namespace rx
+{
+
+namespace
+{
+
+std::string 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";
+ }
+}
+
+std::string HLSLComponentTypeString(GLenum componentType, int componentCount)
+{
+ return HLSLComponentTypeString(componentType) + (componentCount > 1 ? Str(componentCount) : "");
+}
+
+std::string 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";
+ }
+}
+
+std::string HLSLTypeString(GLenum type)
+{
+ if (gl::IsMatrixType(type))
+ {
+ return HLSLMatrixTypeString(type);
+ }
+
+ return HLSLComponentTypeString(gl::VariableComponentType(type),
+ gl::VariableComponentCount(type));
+}
+
+const PixelShaderOutputVariable *FindOutputAtLocation(
+ const std::vector<PixelShaderOutputVariable> &outputVariables,
+ unsigned int location)
+{
+ for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex)
+ {
+ if (outputVariables[variableIndex].outputIndex == location)
+ {
+ return &outputVariables[variableIndex];
+ }
+ }
+
+ return nullptr;
+}
+
+void WriteArrayString(std::stringstream &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 << "]";
+}
+
+constexpr const char *VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
+constexpr const char *PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@";
+} // anonymous namespace
+
+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");
+}
+
+// DynamicHLSL implementation
+
+DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer)
+{
+}
+
+void DynamicHLSL::generateVaryingHLSL(const VaryingPacking &varyingPacking,
+ std::stringstream &hlslStream) const
+{
+ std::string varyingSemantic =
+ GetVaryingSemantic(mRenderer->getMajorShaderModel(), varyingPacking.usesPointSize());
+
+ for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
+ {
+ 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;
+ default:
+ UNREACHABLE();
+ }
+
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ GLenum componentType = gl::VariableComponentType(transposedType);
+ int columnCount = gl::VariableColumnCount(transposedType);
+ hlslStream << HLSLComponentTypeString(componentType, columnCount);
+ unsigned int semanticIndex = registerInfo.semanticIndex;
+ hlslStream << " v" << semanticIndex << " : " << varyingSemantic << semanticIndex << ";\n";
+ }
+}
+
+std::string DynamicHLSL::generateVertexShaderForInputLayout(
+ const std::string &sourceShader,
+ const InputLayout &inputLayout,
+ const std::vector<sh::Attribute> &shaderAttributes) const
+{
+ std::stringstream structStream;
+ std::stringstream 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->getWorkarounds().useInstancedPointSpriteEmulation;
+
+ // 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::Attribute &shaderAttribute = shaderAttributes[attributeIndex];
+ if (!shaderAttribute.name.empty())
+ {
+ ASSERT(inputIndex < MAX_VERTEX_ATTRIBS);
+ VertexFormatType vertexFormatType =
+ inputIndex < inputLayout.size() ? inputLayout[inputIndex] : VERTEX_FORMAT_INVALID;
+
+ // HLSL code for input structure
+ if (IsMatrixType(shaderAttribute.type))
+ {
+ // Matrix types are always transposed
+ structStream << " "
+ << HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type));
+ }
+ else
+ {
+ GLenum componentType = mRenderer->getVertexComponentType(vertexFormatType);
+
+ 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
+ {
+ structStream << " " << HLSLComponentTypeString(
+ 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(vertexFormatType) & VERTEX_CONVERT_GPU) != 0)
+ {
+ initStream << generateAttributeConversionHLSL(vertexFormatType, shaderAttribute);
+ }
+ else
+ {
+ initStream << "input." << decorateVariable(shaderAttribute.name);
+ }
+
+ initStream << ";\n";
+
+ inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type));
+ }
+ }
+
+ structStream << "};\n"
+ "\n"
+ "void initAttributes(VS_INPUT input)\n"
+ "{\n"
+ << initStream.str() << "}\n";
+
+ std::string vertexHLSL(sourceShader);
+
+ size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING);
+ vertexHLSL.replace(copyInsertionPos, strlen(VERTEX_ATTRIBUTE_STUB_STRING), structStream.str());
+
+ return vertexHLSL;
+}
+
+std::string DynamicHLSL::generatePixelShaderForOutputSignature(
+ const std::string &sourceShader,
+ const std::vector<PixelShaderOutputVariable> &outputVariables,
+ bool usesFragDepth,
+ const std::vector<GLenum> &outputLayout) const
+{
+ const int shaderModel = mRenderer->getMajorShaderModel();
+ std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR";
+ std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
+
+ std::stringstream declarationStream;
+ std::stringstream copyStream;
+
+ declarationStream << "struct PS_OUTPUT\n"
+ "{\n";
+
+ for (size_t layoutIndex = 0; layoutIndex < outputLayout.size(); ++layoutIndex)
+ {
+ GLenum binding = outputLayout[layoutIndex];
+
+ if (binding != GL_NONE)
+ {
+ unsigned int location = (binding - GL_COLOR_ATTACHMENT0);
+
+ const PixelShaderOutputVariable *outputVariable =
+ FindOutputAtLocation(outputVariables, location);
+
+ // 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(outputVariable->type) << " "
+ << 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);
+
+ size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING);
+ pixelHLSL.replace(outputInsertionPos, strlen(PIXEL_OUTPUT_STUB_STRING),
+ declarationStream.str());
+
+ return pixelHLSL;
+}
+
+void DynamicHLSL::generateVaryingLinkHLSL(ShaderType shaderType,
+ const VaryingPacking &varyingPacking,
+ std::stringstream &linkStream) const
+{
+ const auto &builtins = varyingPacking.builtins(shaderType);
+ ASSERT(builtins.dxPosition.enabled);
+ linkStream << "{\n"
+ << " float4 dx_Position : " << builtins.dxPosition.str() << ";\n";
+
+ if (builtins.glPosition.enabled)
+ {
+ linkStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n";
+ }
+
+ if (builtins.glFragCoord.enabled)
+ {
+ linkStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n";
+ }
+
+ if (builtins.glPointCoord.enabled)
+ {
+ linkStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n";
+ }
+
+ if (builtins.glPointSize.enabled)
+ {
+ linkStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n";
+ }
+
+ // Do this after gl_PointSize, to potentially combine gl_PointCoord and gl_PointSize into the
+ // same register.
+ generateVaryingHLSL(varyingPacking, linkStream);
+
+ linkStream << "};\n";
+}
+
+bool DynamicHLSL::generateShaderLinkHLSL(const gl::ContextState &data,
+ const gl::ProgramState &programData,
+ const ProgramD3DMetadata &programMetadata,
+ const VaryingPacking &varyingPacking,
+ std::string *pixelHLSL,
+ std::string *vertexHLSL) const
+{
+ ASSERT(pixelHLSL->empty() && vertexHLSL->empty());
+
+ const gl::Shader *vertexShaderGL = programData.getAttachedVertexShader();
+ const gl::Shader *fragmentShaderGL = programData.getAttachedFragmentShader();
+ const ShaderD3D *fragmentShader = GetImplAs<ShaderD3D>(fragmentShaderGL);
+ const int shaderModel = mRenderer->getMajorShaderModel();
+
+ // usesViewScale() isn't supported in the D3D9 renderer
+ ASSERT(shaderModel >= 4 || !programMetadata.usesViewScale());
+
+ bool useInstancedPointSpriteEmulation =
+ programMetadata.usesPointSize() &&
+ mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
+
+ // Validation done in the compiler
+ ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData());
+
+ std::stringstream vertexStream;
+ vertexStream << vertexShaderGL->getTranslatedSource();
+
+ // 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>(data.getCaps().minAliasedPointSize) << ".0f;\n"
+ << "static float maxPointSize = "
+ << static_cast<int>(data.getCaps().maxAliasedPointSize) << ".0f;\n";
+ }
+
+ // Add stub string to be replaced when shader is dynamically defined by its layout
+ vertexStream << "\n" << std::string(VERTEX_ATTRIBUTE_STUB_STRING) << "\n";
+
+ // Write the HLSL input/output declarations
+ vertexStream << "struct VS_OUTPUT\n";
+ generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, vertexStream);
+ vertexStream << "\n"
+ << "VS_OUTPUT main(VS_INPUT input)\n"
+ << "{\n"
+ << " initAttributes(input);\n";
+
+ vertexStream << "\n"
+ << " gl_main();\n"
+ << "\n"
+ << " VS_OUTPUT output;\n";
+
+ const auto &vertexBuiltins = varyingPacking.builtins(SHADER_VERTEX);
+
+ if (vertexBuiltins.glPosition.enabled)
+ {
+ vertexStream << " output.gl_Position = gl_Position;\n";
+ }
+
+ // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust.
+ if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
+ {
+ vertexStream << " 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.
+ vertexStream << " output.dx_Position.y = dx_ViewScale.y * gl_Position.y;\n";
+ }
+ else
+ {
+ vertexStream << " output.dx_Position.y = - gl_Position.y;\n";
+ }
+
+ vertexStream << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+ << " output.dx_Position.w = gl_Position.w;\n";
+ }
+ else
+ {
+ vertexStream << " 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() != ""))
+ {
+ vertexStream << " output.dx_Position.y = dx_ViewScale.y * (gl_Position.y * "
+ "dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n";
+ }
+ else
+ {
+ vertexStream << " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + "
+ "dx_ViewAdjust.y * gl_Position.w);\n";
+ }
+
+ vertexStream << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+ << " 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)
+ {
+ vertexStream << " output.gl_PointSize = gl_PointSize;\n";
+ }
+
+ if (vertexBuiltins.glFragCoord.enabled)
+ {
+ vertexStream << " output.gl_FragCoord = gl_Position;\n";
+ }
+
+ for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
+ {
+ const auto &packedVarying = *registerInfo.packedVarying;
+ const auto &varying = *packedVarying.varying;
+ ASSERT(!varying.isStruct());
+
+ vertexStream << " output.v" << registerInfo.semanticIndex << " = ";
+
+ if (packedVarying.isStructField())
+ {
+ vertexStream << decorateVariable(packedVarying.parentStructName) << ".";
+ }
+
+ vertexStream << decorateVariable(varying.name);
+
+ if (varying.isArray())
+ {
+ WriteArrayString(vertexStream, registerInfo.varyingArrayIndex);
+ }
+
+ if (VariableRowCount(varying.type) > 1)
+ {
+ WriteArrayString(vertexStream, registerInfo.varyingRowIndex);
+ }
+
+ vertexStream << ";\n";
+ }
+
+ // Instanced PointSprite emulation requires additional entries to calculate
+ // the final output vertex positions of the quad that represents each sprite.
+ if (useInstancedPointSpriteEmulation)
+ {
+ vertexStream << "\n"
+ << " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n";
+
+ vertexStream << " 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
+ vertexStream << " output.dx_Position.y += (-dx_ViewScale.y * "
+ "input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2)) * "
+ "output.dx_Position.w;";
+ }
+ else
+ {
+ vertexStream << " output.dx_Position.y += (input.spriteVertexPos.y * gl_PointSize / "
+ "(dx_ViewCoords.y*2)) * output.dx_Position.w;";
+ }
+
+ vertexStream
+ << " output.dx_Position.z += input.spriteVertexPos.z * output.dx_Position.w;\n";
+
+ if (programMetadata.usesPointCoord())
+ {
+ vertexStream << "\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);
+ vertexStream << "\n"
+ << " output.gl_PointCoord = float2(0.5, 0.5);\n";
+ }
+
+ vertexStream << "\n"
+ << " return output;\n"
+ << "}\n";
+
+ std::stringstream pixelStream;
+ pixelStream << fragmentShaderGL->getTranslatedSource();
+ pixelStream << "struct PS_INPUT\n";
+ generateVaryingLinkHLSL(SHADER_PIXEL, varyingPacking, pixelStream);
+ pixelStream << "\n";
+
+ pixelStream << std::string(PIXEL_OUTPUT_STUB_STRING) << "\n";
+
+ if (fragmentShader->usesFrontFacing())
+ {
+ if (shaderModel >= 4)
+ {
+ pixelStream << "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
+ << "{\n";
+ }
+ else
+ {
+ pixelStream << "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
+ << "{\n";
+ }
+ }
+ else
+ {
+ pixelStream << "PS_OUTPUT main(PS_INPUT input)\n"
+ << "{\n";
+ }
+
+ const auto &pixelBuiltins = varyingPacking.builtins(SHADER_PIXEL);
+
+ if (pixelBuiltins.glFragCoord.enabled)
+ {
+ pixelStream << " 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.
+ if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
+ {
+ pixelStream << " gl_FragCoord.x = input.dx_Position.x;\n"
+ << " gl_FragCoord.y = input.dx_Position.y;\n";
+ }
+ else if (shaderModel == 3)
+ {
+ pixelStream << " gl_FragCoord.x = input.dx_Position.x + 0.5;\n"
+ << " gl_FragCoord.y = input.dx_Position.y + 0.5;\n";
+ }
+ else
+ {
+ // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See
+ // Renderer::setViewport()
+ pixelStream << " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + "
+ "dx_ViewCoords.z;\n"
+ << " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + "
+ "dx_ViewCoords.w;\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:
+ pixelStream
+ << " 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";
+ }
+ }
+
+ pixelStream << " 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)
+ {
+ pixelStream << " gl_PointCoord.x = input.gl_PointCoord.x;\n"
+ << " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
+ }
+
+ if (fragmentShader->usesFrontFacing())
+ {
+ if (shaderModel <= 3)
+ {
+ pixelStream << " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
+ }
+ else
+ {
+ pixelStream << " gl_FrontFacing = isFrontFace;\n";
+ }
+ }
+
+ for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
+ {
+ const auto &packedVarying = *registerInfo.packedVarying;
+ const auto &varying = *packedVarying.varying;
+ ASSERT(!varying.isBuiltIn() && !varying.isStruct());
+
+ // Don't reference VS-only transform feedback varyings in the PS.
+ // TODO: Consider updating the fragment shader's varyings with a parameter signaling that a
+ // varying is only used in the vertex shader in MergeVaryings
+ if (packedVarying.vertexOnly || (!varying.staticUse && !packedVarying.isStructField()))
+ continue;
+
+ pixelStream << " ";
+
+ if (packedVarying.isStructField())
+ {
+ pixelStream << decorateVariable(packedVarying.parentStructName) << ".";
+ }
+
+ pixelStream << decorateVariable(varying.name);
+
+ if (varying.isArray())
+ {
+ WriteArrayString(pixelStream, registerInfo.varyingArrayIndex);
+ }
+
+ GLenum transposedType = TransposeMatrixType(varying.type);
+ if (VariableRowCount(transposedType) > 1)
+ {
+ WriteArrayString(pixelStream, registerInfo.varyingRowIndex);
+ }
+
+ pixelStream << " = input.v" << registerInfo.semanticIndex;
+
+ switch (VariableColumnCount(transposedType))
+ {
+ case 1:
+ pixelStream << ".x";
+ break;
+ case 2:
+ pixelStream << ".xy";
+ break;
+ case 3:
+ pixelStream << ".xyz";
+ break;
+ case 4:
+ break;
+ default:
+ UNREACHABLE();
+ }
+ pixelStream << ";\n";
+ }
+
+ pixelStream << "\n"
+ << " gl_main();\n"
+ << "\n"
+ << " return generateOutput();\n"
+ << "}\n";
+
+ *vertexHLSL = vertexStream.str();
+ *pixelHLSL = pixelStream.str();
+
+ return true;
+}
+
+std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const
+{
+ ASSERT(mRenderer->getMajorShaderModel() >= 4);
+
+ std::stringstream preambleStream;
+
+ const auto &builtins = varyingPacking.builtins(SHADER_VERTEX);
+
+ preambleStream << "struct GS_INPUT\n";
+ generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, preambleStream);
+ preambleStream << "\n"
+ << "struct GS_OUTPUT\n";
+ generateVaryingLinkHLSL(SHADER_GEOMETRY, varyingPacking, 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 (builtins.glPointSize.enabled)
+ {
+ preambleStream << " output.gl_PointSize = input.gl_PointSize;\n";
+ }
+
+ for (const PackedVaryingRegister &varyingRegister : varyingPacking.getRegisterList())
+ {
+ preambleStream << " output.v" << varyingRegister.semanticIndex << " = ";
+ if (varyingRegister.packedVarying->interpolation == sh::INTERPOLATION_FLAT)
+ {
+ preambleStream << "flat";
+ }
+ preambleStream << "input.v" << varyingRegister.semanticIndex << "; \n";
+ }
+
+ if (builtins.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";
+
+ return preambleStream.str();
+}
+
+std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
+ const gl::ContextState &data,
+ const gl::ProgramState &programData,
+ const bool useViewScale,
+ const std::string &preambleString) const
+{
+ ASSERT(mRenderer->getMajorShaderModel() >= 4);
+
+ std::stringstream shaderStream;
+
+ const bool pointSprites = (primitiveType == PRIMITIVE_POINTS);
+ 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 PRIMITIVE_POINTS:
+ inputPT = "point";
+ outputPT = "Triangle";
+ inputSize = 1;
+ maxVertexOutput = 4;
+ break;
+
+ case PRIMITIVE_LINES:
+ case PRIMITIVE_LINE_STRIP:
+ case PRIMITIVE_LINE_LOOP:
+ inputPT = "line";
+ outputPT = "Line";
+ inputSize = 2;
+ maxVertexOutput = 2;
+ break;
+
+ case PRIMITIVE_TRIANGLES:
+ case PRIMITIVE_TRIANGLE_STRIP:
+ case PRIMITIVE_TRIANGLE_FAN:
+ inputPT = "triangle";
+ outputPT = "Triangle";
+ inputSize = 3;
+ maxVertexOutput = 3;
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ if (pointSprites)
+ {
+ shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n"
+ "\n"
+ "uniform float4 dx_ViewCoords : register(c1);\n";
+
+ if (useViewScale)
+ {
+ shaderStream << "uniform float2 dx_ViewScale : register(c3);\n";
+ }
+
+ shaderStream << "\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>(data.getCaps().minAliasedPointSize)
+ << ".0f;\n"
+ "static float maxPointSize = "
+ << static_cast<int>(data.getCaps().maxAliasedPointSize) << ".0f;\n"
+ << "\n";
+ }
+
+ shaderStream << preambleString << "\n"
+ << "[maxvertexcount(" << maxVertexOutput << ")]\n"
+ << "void main(" << inputPT << " GS_INPUT input[" << inputSize << "], ";
+
+ if (primitiveType == PRIMITIVE_TRIANGLE_STRIP)
+ {
+ shaderStream << "uint primitiveID : SV_PrimitiveID, ";
+ }
+
+ shaderStream << " inout " << outputPT << "Stream<GS_OUTPUT> outStream)\n"
+ << "{\n"
+ << " GS_OUTPUT output = (GS_OUTPUT)0;\n";
+
+ if (primitiveType == PRIMITIVE_TRIANGLE_STRIP)
+ {
+ 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 (!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();
+}
+
+// This method needs to match OutputHLSL::decorate
+std::string DynamicHLSL::decorateVariable(const std::string &name)
+{
+ if (name.compare(0, 3, "gl_") != 0)
+ {
+ return "_" + name;
+ }
+
+ return name;
+}
+
+std::string DynamicHLSL::generateAttributeConversionHLSL(
+ gl::VertexFormatType vertexFormatType,
+ const sh::ShaderVariable &shaderAttrib) const
+{
+ const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType);
+ std::string attribString = "input." + decorateVariable(shaderAttrib.name);
+
+ // Matrix
+ if (IsMatrixType(shaderAttrib.type))
+ {
+ return "transpose(" + attribString + ")";
+ }
+
+ GLenum shaderComponentType = VariableComponentType(shaderAttrib.type);
+ int shaderComponentCount = VariableComponentCount(shaderAttrib.type);
+
+ // Perform integer to float conversion (if necessary)
+ bool requiresTypeConversion =
+ (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT);
+
+ if (requiresTypeConversion)
+ {
+ // TODO: normalization for 32-bit integer formats
+ ASSERT(!vertexFormat.normalized && !vertexFormat.pureInteger);
+ return "float" + Str(shaderComponentCount) + "(" + attribString + ")";
+ }
+
+ // No conversion necessary
+ return attribString;
+}
+
+void DynamicHLSL::getPixelShaderOutputKey(const gl::ContextState &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() ? data.getCaps().maxDrawBuffers : 1);
+
+ if (metadata.getMajorShaderVersion() < 300)
+ {
+ 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.outputIndex = renderTargetIndex;
+
+ outPixelShaderKey->push_back(outputKeyVariable);
+ }
+ }
+ else
+ {
+ const auto &shaderOutputVars =
+ metadata.getFragmentShader()->getData().getActiveOutputVariables();
+
+ for (auto outputPair : programData.getOutputVariables())
+ {
+ const VariableLocation &outputLocation = outputPair.second;
+ const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
+ const std::string &variableName = "out_" + outputLocation.name;
+ const std::string &elementString =
+ (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
+
+ ASSERT(outputVariable.staticUse);
+
+ PixelShaderOutputVariable outputKeyVariable;
+ outputKeyVariable.type = outputVariable.type;
+ outputKeyVariable.name = variableName + elementString;
+ outputKeyVariable.source = variableName + ArrayString(outputLocation.element);
+ outputKeyVariable.outputIndex = outputPair.first;
+
+ outPixelShaderKey->push_back(outputKeyVariable);
+ }
+ }
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h b/gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
new file mode 100755
index 000000000..98e6384e2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
@@ -0,0 +1,103 @@
+//
+// Copyright (c) 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/formatutils.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace sh
+{
+struct Attribute;
+struct ShaderVariable;
+}
+
+namespace gl
+{
+class InfoLog;
+struct VariableLocation;
+struct VertexAttribute;
+}
+
+namespace rx
+{
+struct PackedVarying;
+class ProgramD3DMetadata;
+class ShaderD3D;
+class VaryingPacking;
+
+struct PixelShaderOutputVariable
+{
+ GLenum type;
+ std::string name;
+ std::string source;
+ size_t outputIndex;
+};
+
+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::Attribute> &shaderAttributes) const;
+ std::string generatePixelShaderForOutputSignature(
+ const std::string &sourceShader,
+ const std::vector<PixelShaderOutputVariable> &outputVariables,
+ bool usesFragDepth,
+ const std::vector<GLenum> &outputLayout) const;
+ bool generateShaderLinkHLSL(const gl::ContextState &data,
+ const gl::ProgramState &programData,
+ const ProgramD3DMetadata &programMetadata,
+ const VaryingPacking &varyingPacking,
+ std::string *pixelHLSL,
+ std::string *vertexHLSL) const;
+
+ std::string generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const;
+
+ std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
+ const gl::ContextState &data,
+ const gl::ProgramState &programData,
+ const bool useViewScale,
+ const std::string &preambleString) const;
+
+ void getPixelShaderOutputKey(const gl::ContextState &data,
+ const gl::ProgramState &programData,
+ const ProgramD3DMetadata &metadata,
+ std::vector<PixelShaderOutputVariable> *outPixelShaderKey);
+
+ private:
+ RendererD3D *const mRenderer;
+
+ void generateVaryingLinkHLSL(ShaderType shaderType,
+ const VaryingPacking &varyingPacking,
+ std::stringstream &linkStream) const;
+ void generateVaryingHLSL(const VaryingPacking &varyingPacking,
+ std::stringstream &hlslStream) const;
+
+ // Prepend an underscore
+ static std::string decorateVariable(const std::string &name);
+
+ std::string generateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType,
+ const sh::ShaderVariable &shaderAttrib) const;
+};
+
+std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize);
+}
+
+#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
new file mode 100755
index 000000000..30cc4d5ff
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
@@ -0,0 +1,135 @@
+//
+// Copyright (c) 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/Texture.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+
+#include <EGL/eglext.h>
+
+namespace rx
+{
+static gl::ImageIndex GetImageIndex(GLenum target, size_t mip, size_t layer)
+{
+ if (target == GL_TEXTURE_3D)
+ {
+ return gl::ImageIndex::Make3D(static_cast<GLint>(mip), static_cast<GLint>(layer));
+ }
+ else
+ {
+ ASSERT(layer == 0);
+ return gl::ImageIndex::MakeGeneric(target, static_cast<GLint>(mip));
+ }
+}
+
+EGLImageD3D::EGLImageD3D(RendererD3D *renderer,
+ EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs)
+ : mRenderer(renderer), mBuffer(buffer), mAttachmentBuffer(nullptr), mRenderTarget(nullptr)
+{
+ ASSERT(renderer != nullptr);
+ ASSERT(buffer != nullptr);
+
+ if (egl::IsTextureTarget(target))
+ {
+ mAttachmentBuffer = GetImplAs<TextureD3D>(GetAs<gl::Texture>(buffer));
+ mAttachmentTarget = gl::FramebufferAttachment::Target(
+ GL_NONE, GetImageIndex(egl_gl::EGLImageTargetToGLTextureTarget(target),
+ attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0),
+ attribs.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0)));
+ }
+ else if (egl::IsRenderbufferTarget(target))
+ {
+ mAttachmentBuffer = GetImplAs<RenderbufferD3D>(GetAs<gl::Renderbuffer>(buffer));
+ mAttachmentTarget =
+ gl::FramebufferAttachment::Target(GL_NONE, gl::ImageIndex::MakeInvalid());
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+}
+
+EGLImageD3D::~EGLImageD3D()
+{
+ SafeDelete(mRenderTarget);
+}
+
+egl::Error EGLImageD3D::initialize()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+gl::Error EGLImageD3D::orphan(egl::ImageSibling *sibling)
+{
+ if (sibling == mBuffer)
+ {
+ gl::Error error = copyToLocalRendertarget();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error EGLImageD3D::getRenderTarget(RenderTargetD3D **outRT) const
+{
+ if (mAttachmentBuffer)
+ {
+ FramebufferAttachmentRenderTarget *rt = nullptr;
+ gl::Error error = mAttachmentBuffer->getAttachmentRenderTarget(mAttachmentTarget, &rt);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *outRT = static_cast<RenderTargetD3D *>(rt);
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ ASSERT(mRenderTarget);
+ *outRT = mRenderTarget;
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+gl::Error EGLImageD3D::copyToLocalRendertarget()
+{
+ ASSERT(mBuffer != nullptr);
+ ASSERT(mAttachmentBuffer != nullptr);
+ ASSERT(mRenderTarget == nullptr);
+
+ RenderTargetD3D *curRenderTarget = nullptr;
+ gl::Error error = getRenderTarget(&curRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // This only currently applies do D3D11, where it invalidates FBOs with this Image attached.
+ curRenderTarget->signalDirty();
+
+ // Clear the source image buffers
+ mBuffer = nullptr;
+ mAttachmentBuffer = nullptr;
+
+ return mRenderer->createRenderTargetCopy(curRenderTarget, &mRenderTarget);
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h
new file mode 100755
index 000000000..6ec33e08f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h
@@ -0,0 +1,56 @@
+//
+// Copyright (c) 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/FramebufferAttachment.h"
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace egl
+{
+class AttributeMap;
+}
+
+namespace rx
+{
+class TextureD3D;
+class RenderbufferD3D;
+class RendererD3D;
+class RenderTargetD3D;
+
+class EGLImageD3D final : public ImageImpl
+{
+ public:
+ EGLImageD3D(RendererD3D *renderer,
+ EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs);
+ ~EGLImageD3D() override;
+
+ egl::Error initialize() override;
+
+ gl::Error orphan(egl::ImageSibling *sibling) override;
+
+ gl::Error getRenderTarget(RenderTargetD3D **outRT) const;
+
+ private:
+ gl::Error copyToLocalRendertarget();
+
+ RendererD3D *mRenderer;
+
+ egl::ImageSibling *mBuffer;
+
+ gl::FramebufferAttachment::Target mAttachmentTarget;
+ FramebufferAttachmentObjectImpl *mAttachmentBuffer;
+
+ RenderTargetD3D *mRenderTarget;
+};
+}
+
+#endif // LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
new file mode 100755
index 000000000..cc8bb0ea7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -0,0 +1,381 @@
+//
+// 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/BitSetIterator.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.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));
+
+ const auto &blendState = state.getBlendState();
+
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = false;
+ }
+ clearParams.colorFClearValue = state.getColorClearValue();
+ clearParams.colorClearType = GL_FLOAT;
+ clearParams.colorMaskRed = blendState.colorMaskRed;
+ clearParams.colorMaskGreen = blendState.colorMaskGreen;
+ clearParams.colorMaskBlue = blendState.colorMaskBlue;
+ clearParams.colorMaskAlpha = blendState.colorMaskAlpha;
+ clearParams.clearDepth = false;
+ clearParams.depthClearValue = state.getDepthClearValue();
+ clearParams.clearStencil = false;
+ clearParams.stencilClearValue = state.getStencilClearValue();
+ clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
+ clearParams.scissorEnabled = state.isScissorTestEnabled();
+ clearParams.scissor = state.getScissor();
+
+ const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ if (framebufferObject->hasEnabledDrawBuffer())
+ {
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = true;
+ }
+ }
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT)
+ {
+ if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL)
+ {
+ clearParams.clearDepth = true;
+ }
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT)
+ {
+ if (framebufferObject->getStencilbuffer() != NULL &&
+ framebufferObject->getStencilbuffer()->getStencilSize() > 0)
+ {
+ clearParams.clearStencil = true;
+ }
+ }
+
+ return clearParams;
+}
+
+}
+
+FramebufferD3D::FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer)
+ : FramebufferImpl(data), mRenderer(renderer)
+{
+}
+
+FramebufferD3D::~FramebufferD3D()
+{
+}
+
+gl::Error FramebufferD3D::clear(ContextImpl *context, GLbitfield mask)
+{
+ ClearParameters clearParams = GetClearParameters(context->getGLState(), mask);
+ return clearImpl(context, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferfv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values)
+{
+ // glClearBufferfv can be called to clear the color buffer or depth buffer
+ ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
+
+ if (buffer == GL_COLOR)
+ {
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
+ clearParams.colorClearType = GL_FLOAT;
+ }
+
+ if (buffer == GL_DEPTH)
+ {
+ clearParams.clearDepth = true;
+ clearParams.depthClearValue = values[0];
+ }
+
+ return clearImpl(context, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferuiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values)
+{
+ // glClearBufferuiv can only be called to clear a color buffer
+ ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
+ clearParams.colorClearType = GL_UNSIGNED_INT;
+
+ return clearImpl(context, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values)
+{
+ // glClearBufferiv can be called to clear the color buffer or stencil buffer
+ ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
+
+ if (buffer == GL_COLOR)
+ {
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
+ clearParams.colorClearType = GL_INT;
+ }
+
+ if (buffer == GL_STENCIL)
+ {
+ clearParams.clearStencil = true;
+ clearParams.stencilClearValue = values[1];
+ }
+
+ return clearImpl(context, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferfi(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
+{
+ // glClearBufferfi can only be called to clear a depth stencil buffer
+ ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
+ clearParams.clearDepth = true;
+ clearParams.depthClearValue = depth;
+ clearParams.clearStencil = true;
+ clearParams.stencilClearValue = stencil;
+
+ return clearImpl(context, clearParams);
+}
+
+GLenum FramebufferD3D::getImplementationColorReadFormat() const
+{
+ const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
+
+ if (readAttachment == nullptr)
+ {
+ return GL_NONE;
+ }
+
+ RenderTargetD3D *attachmentRenderTarget = NULL;
+ gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget);
+ if (error.isError())
+ {
+ return GL_NONE;
+ }
+
+ GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
+ const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
+
+ return implementationFormatInfo.getReadPixelsFormat();
+}
+
+GLenum FramebufferD3D::getImplementationColorReadType() const
+{
+ const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
+
+ if (readAttachment == nullptr)
+ {
+ return GL_NONE;
+ }
+
+ RenderTargetD3D *attachmentRenderTarget = NULL;
+ gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget);
+ if (error.isError())
+ {
+ return GL_NONE;
+ }
+
+ GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
+ const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
+
+ return implementationFormatInfo.getReadPixelsType();
+}
+
+gl::Error FramebufferD3D::readPixels(ContextImpl *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels) const
+{
+ const gl::PixelPackState &packState = context->getGLState().getPackState();
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
+
+ GLuint outputPitch = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeRowPitch(area.width, packState.alignment, packState.rowLength),
+ outputPitch);
+ GLuint outputSkipBytes = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeSkipBytes(outputPitch, 0, packState, false),
+ outputSkipBytes);
+
+ return readPixelsImpl(area, format, type, outputPitch, packState,
+ reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
+}
+
+gl::Error FramebufferD3D::blit(ContextImpl *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter)
+{
+ const auto &glState = context->getGLState();
+ const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer();
+ bool blitRenderTarget = false;
+ if ((mask & GL_COLOR_BUFFER_BIT) && sourceFramebuffer->getReadColorbuffer() != nullptr &&
+ mState.getFirstColorAttachment() != nullptr)
+ {
+ blitRenderTarget = true;
+ }
+
+ bool blitStencil = false;
+ if ((mask & GL_STENCIL_BUFFER_BIT) && sourceFramebuffer->getStencilbuffer() != nullptr &&
+ mState.getStencilAttachment() != nullptr)
+ {
+ blitStencil = true;
+ }
+
+ bool blitDepth = false;
+ if ((mask & GL_DEPTH_BUFFER_BIT) && sourceFramebuffer->getDepthbuffer() != nullptr &&
+ mState.getDepthAttachment() != nullptr)
+ {
+ blitDepth = true;
+ }
+
+ if (blitRenderTarget || blitDepth || blitStencil)
+ {
+ const gl::Rectangle *scissor =
+ glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr;
+ gl::Error error = blitImpl(sourceArea, destArea, scissor, blitRenderTarget, blitDepth,
+ blitStencil, filter, sourceFramebuffer);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+bool FramebufferD3D::checkStatus() 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.getDepthAttachment() != nullptr && mState.getStencilAttachment() != nullptr &&
+ mState.getDepthStencilAttachment() == nullptr)
+ {
+ return false;
+ }
+
+ // D3D11 does not allow for overlapping RenderTargetViews
+ if (!mState.colorAttachmentsAreUniqueImages())
+ {
+ return false;
+ }
+
+ // D3D requires all render targets to have the same dimensions.
+ if (!mState.attachmentsHaveSameDimensions())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
+{
+ bool invalidateColorAttachmentCache = false;
+
+ if (!mColorAttachmentsForRender.valid())
+ {
+ invalidateColorAttachmentCache = true;
+ }
+
+ for (auto dirtyBit : angle::IterateBitSet(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)
+ {
+ invalidateColorAttachmentCache = true;
+ }
+ }
+
+ if (!invalidateColorAttachmentCache)
+ {
+ return;
+ }
+
+ // Does not actually free memory
+ gl::AttachmentList colorAttachmentsForRender;
+
+ const auto &colorAttachments = mState.getColorAttachments();
+ const auto &drawBufferStates = mState.getDrawBufferStates();
+ const auto &workarounds = mRenderer->getWorkarounds();
+
+ 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)
+ {
+ ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
+ colorAttachmentsForRender.push_back(&colorAttachment);
+ }
+ else if (!workarounds.mrtPerfWorkaround)
+ {
+ colorAttachmentsForRender.push_back(nullptr);
+ }
+ }
+
+ mColorAttachmentsForRender = std::move(colorAttachmentsForRender);
+}
+
+const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender() const
+{
+ ASSERT(mColorAttachmentsForRender.valid());
+ return mColorAttachmentsForRender.value();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
new file mode 100755
index 000000000..e56ee7c0b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
@@ -0,0 +1,130 @@
+//
+// 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 <vector>
+#include <cstdint>
+
+#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 rx
+{
+class RendererD3D;
+class RenderTargetD3D;
+struct WorkaroundsD3D;
+
+struct ClearParameters
+{
+ bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
+ gl::ColorF colorFClearValue;
+ gl::ColorI colorIClearValue;
+ gl::ColorUI colorUIClearValue;
+ GLenum colorClearType;
+ bool colorMaskRed;
+ bool colorMaskGreen;
+ bool colorMaskBlue;
+ bool colorMaskAlpha;
+
+ bool clearDepth;
+ float depthClearValue;
+
+ bool clearStencil;
+ GLint stencilClearValue;
+ GLuint stencilWriteMask;
+
+ bool scissorEnabled;
+ gl::Rectangle scissor;
+};
+
+class FramebufferD3D : public FramebufferImpl
+{
+ public:
+ FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer);
+ virtual ~FramebufferD3D();
+
+ gl::Error clear(ContextImpl *impl, GLbitfield mask) override;
+ gl::Error clearBufferfv(ContextImpl *impl,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values) override;
+ gl::Error clearBufferuiv(ContextImpl *impl,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values) override;
+ gl::Error clearBufferiv(ContextImpl *impl,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values) override;
+ gl::Error clearBufferfi(ContextImpl *impl,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil) override;
+
+ GLenum getImplementationColorReadFormat() const override;
+ GLenum getImplementationColorReadType() const override;
+ gl::Error readPixels(ContextImpl *impl,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels) const override;
+
+ gl::Error blit(ContextImpl *impl,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter) override;
+
+ bool checkStatus() const override;
+
+ void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
+
+ const gl::AttachmentList &getColorAttachmentsForRender() const;
+
+ private:
+ virtual gl::Error clearImpl(ContextImpl *impl, const ClearParameters &clearParams) = 0;
+
+ virtual gl::Error readPixelsImpl(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixels) const = 0;
+
+ virtual gl::Error blitImpl(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;
+
+ virtual GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const = 0;
+
+ RendererD3D *mRenderer;
+ Optional<gl::AttachmentList> mColorAttachmentsForRender;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/gfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
new file mode 100755
index 000000000..305b6c4e4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
@@ -0,0 +1,333 @@
+//
+// 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 "common/utilities.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/features.h"
+#include "libANGLE/histogram_macros.h"
+#include "third_party/trace_event/trace_event.h"
+
+#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
+namespace
+{
+#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;
+ }
+}
+} // anonymous namespace
+#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
+
+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();
+}
+
+gl::Error HLSLCompiler::initialize()
+{
+ if (mInitialized)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ TRACE_EVENT0("gpu.angle", "HLSLCompiler::initialize");
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+#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 = LoadLibrary(D3DCOMPILER_DLL);
+ }
+
+ if (!mD3DCompilerModule)
+ {
+ ERR("D3D compiler module not found.");
+ return gl::Error(GL_OUT_OF_MEMORY, "D3D compiler module not found.");
+ }
+
+ 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
+
+ if (mD3DCompileFunc == nullptr)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Error finding D3DCompile entry point.");
+ }
+
+ mInitialized = true;
+ return gl::Error(GL_NO_ERROR);
+}
+
+void HLSLCompiler::release()
+{
+ if (mInitialized)
+ {
+ FreeLibrary(mD3DCompilerModule);
+ mD3DCompilerModule = nullptr;
+ mD3DCompileFunc = nullptr;
+ mD3DDisassembleFunc = nullptr;
+ mInitialized = false;
+ }
+}
+
+gl::Error HLSLCompiler::compileToBinary(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)
+{
+ gl::Error error = initialize();
+ if (error.isError())
+ {
+ return error;
+ }
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ ASSERT(mD3DCompilerModule);
+#endif
+ ASSERT(mD3DCompileFunc);
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ if (gl::DebugAnnotationsActive())
+ {
+ std::string sourcePath = getTempPath();
+ std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_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;
+
+ {
+ TRACE_EVENT0("gpu.angle", "D3DCompile");
+ SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3DCompileMS");
+ 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 = reinterpret_cast<const char*>(errorMessage->GetBufferPointer());
+ SafeRelease(errorMessage);
+
+ infoLog.appendSanitized(message.c_str());
+ TRACE("\n%s", hlsl.c_str());
+ TRACE("\n%s", message.c_str());
+
+ if ((message.find("error X3531:") != std::string::npos || // "can't unroll loops marked with loop attribute"
+ message.find("error X4014:") != std::string::npos) && // "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.
+ macros != nullptr)
+ {
+ macros = nullptr; // Disable [loop] and [flatten]
+
+ // 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;
+ error = disassembleBinary(binary, &disassembly);
+ if (error.isError())
+ {
+ return error;
+ }
+ (*outDebugInfo) += "\n" + disassembly + "\n// ASSEMBLY END\n";
+#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ if (result == E_OUTOFMEMORY)
+ {
+ *outCompiledBlob = nullptr;
+ return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result);
+ }
+
+ 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 gl::Error(GL_NO_ERROR);
+}
+
+gl::Error HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut)
+{
+ gl::Error error = initialize();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // 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(reinterpret_cast<const char*>(disassembly->GetBufferPointer()));
+ }
+ else
+ {
+ *disassemblyOut = "";
+ }
+
+ SafeRelease(disassembly);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h b/gfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h
new file mode 100755
index 000000000..3c0d2adca
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h
@@ -0,0 +1,56 @@
+#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 <vector>
+#include <string>
+
+namespace gl
+{
+class InfoLog;
+}
+
+namespace rx
+{
+
+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.
+ gl::Error compileToBinary(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);
+
+ gl::Error disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut);
+
+ private:
+ gl::Error initialize();
+
+ bool mInitialized;
+ HMODULE mD3DCompilerModule;
+ pD3DCompile mD3DCompileFunc;
+ pD3DDisassemble mD3DDisassembleFunc;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
new file mode 100755
index 000000000..c9581ccaa
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
@@ -0,0 +1,42 @@
+//
+// Copyright (c) 2002-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: 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"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+
+namespace rx
+{
+
+ImageD3D::ImageD3D()
+ : mWidth(0),
+ mHeight(0),
+ mDepth(0),
+ mInternalFormat(GL_NONE),
+ mRenderable(false),
+ mTarget(GL_NONE),
+ mDirty(false)
+{
+}
+
+GLenum
+ImageD3D::getSizedInputFormat(GLenum inputType) const
+{
+ const auto &internalFormat = gl::GetInternalFormatInfo(mInternalFormat);
+ const auto &unsizedInternalFormat = internalFormat.format;
+ const auto &sizedInputFormat = gl::GetSizedInternalFormat(unsizedInternalFormat, inputType);
+ return sizedInputFormat;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.h
new file mode 100755
index 000000000..79840c15b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.h
@@ -0,0 +1,88 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 "libANGLE/Error.h"
+
+namespace gl
+{
+class Framebuffer;
+struct ImageIndex;
+struct Box;
+struct Extents;
+struct Offset;
+struct Rectangle;
+struct PixelUnpackState;
+}
+
+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; }
+ GLenum getTarget() const { return mTarget; }
+ bool isRenderableFormat() const { return mRenderable; }
+
+ void markDirty() { mDirty = true; }
+ void markClean() { mDirty = false; }
+ virtual bool isDirty() const = 0;
+
+ virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0;
+
+ GLenum getSizedInputFormat(GLenum inputType) const;
+
+ virtual gl::Error loadData(const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages) = 0;
+ virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0;
+
+ virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); };
+ virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level) { return gl::Error(GL_NO_ERROR); };
+ virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); };
+ virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level) { return gl::Error(GL_NO_ERROR); };
+ virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
+
+ virtual gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex,
+ TextureStorage *source) = 0;
+ virtual gl::Error copyFromFramebuffer(const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) = 0;
+
+ protected:
+ GLsizei mWidth;
+ GLsizei mHeight;
+ GLsizei mDepth;
+ GLenum mInternalFormat;
+ bool mRenderable;
+ GLenum mTarget;
+
+ bool mDirty;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_IMAGED3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp b/gfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp
new file mode 100755
index 000000000..677b8bb24
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp
@@ -0,0 +1,196 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/renderer/d3d/RendererD3D.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;
+ }
+}
+
+GLenum IndexBufferInterface::getIndexType() const
+{
+ return mIndexBuffer->getIndexType();
+}
+
+unsigned int IndexBufferInterface::getBufferSize() const
+{
+ return mIndexBuffer->getBufferSize();
+}
+
+unsigned int IndexBufferInterface::getSerial() const
+{
+ return mIndexBuffer->getSerial();
+}
+
+gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMemory, unsigned int *streamOffset)
+{
+ // Protect against integer overflow
+ if (mWritePosition + size < mWritePosition)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Mapping of internal index buffer would cause an integer overflow.");
+ }
+
+ gl::Error error = mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory);
+ if (error.isError())
+ {
+ if (outMappedMemory)
+ {
+ *outMappedMemory = NULL;
+ }
+ return error;
+ }
+
+ if (streamOffset)
+ {
+ *streamOffset = mWritePosition;
+ }
+
+ mWritePosition += size;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error IndexBufferInterface::unmapBuffer()
+{
+ return mIndexBuffer->unmapBuffer();
+}
+
+IndexBuffer * IndexBufferInterface::getIndexBuffer() const
+{
+ return mIndexBuffer;
+}
+
+unsigned int IndexBufferInterface::getWritePosition() const
+{
+ return mWritePosition;
+}
+
+void IndexBufferInterface::setWritePosition(unsigned int writePosition)
+{
+ mWritePosition = writePosition;
+}
+
+gl::Error IndexBufferInterface::discard()
+{
+ return mIndexBuffer->discard();
+}
+
+gl::Error IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType)
+{
+ if (mIndexBuffer->getBufferSize() == 0)
+ {
+ return mIndexBuffer->initialize(bufferSize, indexType, mDynamic);
+ }
+ else
+ {
+ return mIndexBuffer->setSize(bufferSize, indexType);
+ }
+}
+
+StreamingIndexBufferInterface::StreamingIndexBufferInterface(BufferFactoryD3D *factory)
+ : IndexBufferInterface(factory, true)
+{
+}
+
+StreamingIndexBufferInterface::~StreamingIndexBufferInterface()
+{
+}
+
+gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
+{
+ unsigned int curBufferSize = getBufferSize();
+ unsigned int writePos = getWritePosition();
+ if (size > curBufferSize)
+ {
+ gl::Error error = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
+ if (error.isError())
+ {
+ return error;
+ }
+ setWritePosition(0);
+ }
+ else if (writePos + size > curBufferSize || writePos + size < writePos)
+ {
+ gl::Error error = discard();
+ if (error.isError())
+ {
+ return error;
+ }
+ setWritePosition(0);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+
+StaticIndexBufferInterface::StaticIndexBufferInterface(BufferFactoryD3D *factory)
+ : IndexBufferInterface(factory, false)
+{
+}
+
+StaticIndexBufferInterface::~StaticIndexBufferInterface()
+{
+}
+
+gl::Error StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
+{
+ unsigned int curSize = getBufferSize();
+ if (curSize == 0)
+ {
+ return setBufferSize(size, indexType);
+ }
+ else if (curSize >= size && indexType == getIndexType())
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION, "Internal static index buffers can't be resized");
+ }
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.h b/gfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.h
new file mode 100755
index 000000000..0b7b28ddf
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/IndexBuffer.h
@@ -0,0 +1,100 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/angleutils.h"
+#include "libANGLE/Error.h"
+
+namespace rx
+{
+class BufferFactoryD3D;
+
+class IndexBuffer : angle::NonCopyable
+{
+ public:
+ IndexBuffer();
+ virtual ~IndexBuffer();
+
+ virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0;
+
+ virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0;
+ virtual gl::Error unmapBuffer() = 0;
+
+ virtual gl::Error discard() = 0;
+
+ virtual GLenum getIndexType() const = 0;
+ virtual unsigned int getBufferSize() const = 0;
+ virtual gl::Error setSize(unsigned int bufferSize, GLenum 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 gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) = 0;
+
+ GLenum getIndexType() const;
+ unsigned int getBufferSize() const;
+
+ unsigned int getSerial() const;
+
+ gl::Error mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset);
+ gl::Error unmapBuffer();
+
+ IndexBuffer *getIndexBuffer() const;
+
+ protected:
+ unsigned int getWritePosition() const;
+ void setWritePosition(unsigned int writePosition);
+
+ gl::Error discard();
+
+ gl::Error setBufferSize(unsigned int bufferSize, GLenum indexType);
+
+ private:
+ IndexBuffer *mIndexBuffer;
+
+ unsigned int mWritePosition;
+ bool mDynamic;
+};
+
+class StreamingIndexBufferInterface : public IndexBufferInterface
+{
+ public:
+ explicit StreamingIndexBufferInterface(BufferFactoryD3D *factory);
+ ~StreamingIndexBufferInterface();
+
+ gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override;
+};
+
+class StaticIndexBufferInterface : public IndexBufferInterface
+{
+ public:
+ explicit StaticIndexBufferInterface(BufferFactoryD3D *factory);
+ ~StaticIndexBufferInterface();
+
+ gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp b/gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
new file mode 100755
index 000000000..474c77fce
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
@@ -0,0 +1,354 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/formatutils.h"
+
+namespace rx
+{
+
+namespace
+{
+
+template <typename InputT, typename DestT>
+void ConvertIndexArray(const void *input,
+ GLenum sourceType,
+ void *output,
+ GLenum 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(GLenum sourceType,
+ GLenum destinationType,
+ const void *input,
+ GLsizei count,
+ void *output,
+ bool usePrimitiveRestartFixedIndex)
+{
+ if (sourceType == destinationType)
+ {
+ const gl::Type &typeInfo = gl::GetTypeInfo(destinationType);
+ memcpy(output, input, count * typeInfo.bytes);
+ return;
+ }
+
+ if (sourceType == GL_UNSIGNED_BYTE)
+ {
+ ASSERT(destinationType == GL_UNSIGNED_SHORT);
+ ConvertIndexArray<GLubyte, GLushort>(input, sourceType, output, destinationType, count,
+ usePrimitiveRestartFixedIndex);
+ }
+ else if (sourceType == GL_UNSIGNED_SHORT)
+ {
+ ASSERT(destinationType == GL_UNSIGNED_INT);
+ ConvertIndexArray<GLushort, GLuint>(input, sourceType, output, destinationType, count,
+ usePrimitiveRestartFixedIndex);
+ }
+ else UNREACHABLE();
+}
+
+gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer,
+ const GLvoid *data,
+ unsigned int count,
+ GLenum srcType,
+ GLenum dstType,
+ bool usePrimitiveRestartFixedIndex,
+ unsigned int *offset)
+{
+ const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType);
+
+ if (count > (std::numeric_limits<unsigned int>::max() >> dstTypeInfo.bytesShift))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Reserving %u indices of %u bytes each exceeds the maximum buffer size.",
+ count, dstTypeInfo.bytes);
+ }
+
+ unsigned int bufferSizeRequired = count << dstTypeInfo.bytesShift;
+ gl::Error error = buffer->reserveBufferSpace(bufferSizeRequired, dstType);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ void *output = nullptr;
+ error = buffer->mapBuffer(bufferSizeRequired, &output, offset);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ConvertIndices(srcType, dstType, data, count, output, usePrimitiveRestartFixedIndex);
+
+ error = buffer->unmapBuffer();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+} // anonymous namespace
+
+IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass)
+ : mFactory(factory),
+ mRendererClass(rendererClass),
+ mStreamingBufferShort(nullptr),
+ mStreamingBufferInt(nullptr)
+{
+}
+
+IndexDataManager::~IndexDataManager()
+{
+ SafeDelete(mStreamingBufferShort);
+ SafeDelete(mStreamingBufferInt);
+}
+
+// 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.
+gl::Error IndexDataManager::prepareIndexData(GLenum srcType,
+ GLsizei count,
+ gl::Buffer *glBuffer,
+ const GLvoid *indices,
+ TranslatedIndexData *translated,
+ bool primitiveRestartFixedIndexEnabled)
+{
+ // Avoid D3D11's primitive restart index value
+ // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
+ bool hasPrimitiveRestartIndex =
+ translated->indexRange.vertexIndexCount < static_cast<size_t>(count) ||
+ translated->indexRange.end == gl::GetPrimitiveRestartIndex(srcType);
+ bool primitiveRestartWorkaround = mRendererClass == RENDERER_D3D11 &&
+ !primitiveRestartFixedIndexEnabled &&
+ hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_SHORT;
+
+ // We should never have to deal with MAX_UINT indices, since we restrict it via
+ // MAX_ELEMENT_INDEX.
+ ASSERT(!(mRendererClass == RENDERER_D3D11 && !primitiveRestartFixedIndexEnabled &&
+ hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_INT));
+
+ const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround) ?
+ GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
+
+ const gl::Type &srcTypeInfo = gl::GetTypeInfo(srcType);
+ const gl::Type &dstTypeInfo = gl::GetTypeInfo(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;
+
+ // Case 1: the indices are passed by pointer, which forces the streaming of index data
+ if (glBuffer == nullptr)
+ {
+ translated->storage = nullptr;
+ return streamIndexData(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(srcTypeInfo.bytes * static_cast<unsigned int>(count) + offset <= buffer->getSize());
+
+ bool offsetAligned;
+ switch (srcType)
+ {
+ case GL_UNSIGNED_BYTE: offsetAligned = (offset % sizeof(GLubyte) == 0); break;
+ case GL_UNSIGNED_SHORT: offsetAligned = (offset % sizeof(GLushort) == 0); break;
+ case GL_UNSIGNED_INT: offsetAligned = (offset % sizeof(GLuint) == 0); break;
+ default: UNREACHABLE(); offsetAligned = false;
+ }
+
+ // Case 2a: the buffer can be used directly
+ if (offsetAligned && buffer->supportsDirectBinding() &&
+ dstType == srcType && !primitiveRestartWorkaround)
+ {
+ translated->storage = buffer;
+ translated->indexBuffer = nullptr;
+ translated->serial = buffer->getSerial();
+ translated->startIndex = (offset >> srcTypeInfo.bytesShift);
+ translated->startOffset = offset;
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ 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();
+ staticBuffer = nullptr;
+ }
+
+ if (staticBuffer == nullptr || !offsetAligned)
+ {
+ const uint8_t *bufferData = nullptr;
+ gl::Error error = buffer->getData(&bufferData);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(bufferData != nullptr);
+
+ error = streamIndexData(bufferData + offset, count, srcType, dstType,
+ primitiveRestartFixedIndexEnabled, translated);
+ if (error.isError())
+ {
+ return error;
+ }
+ buffer->promoteStaticUsage(count << srcTypeInfo.bytesShift);
+ }
+ else
+ {
+ if (!staticBufferInitialized)
+ {
+ const uint8_t *bufferData = nullptr;
+ gl::Error error = buffer->getData(&bufferData);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(bufferData != nullptr);
+
+ unsigned int convertCount =
+ static_cast<unsigned int>(buffer->getSize()) >> srcTypeInfo.bytesShift;
+ error = StreamInIndexBuffer(staticBuffer, bufferData, convertCount, srcType, dstType,
+ primitiveRestartFixedIndexEnabled, nullptr);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ ASSERT(offsetAligned && staticBuffer->getIndexType() == dstType);
+
+ translated->indexBuffer = staticBuffer->getIndexBuffer();
+ translated->serial = staticBuffer->getSerial();
+ translated->startIndex = (offset >> srcTypeInfo.bytesShift);
+ translated->startOffset = (offset >> srcTypeInfo.bytesShift) << dstTypeInfo.bytesShift;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error IndexDataManager::streamIndexData(const GLvoid *data,
+ unsigned int count,
+ GLenum srcType,
+ GLenum dstType,
+ bool usePrimitiveRestartFixedIndex,
+ TranslatedIndexData *translated)
+{
+ const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType);
+
+ IndexBufferInterface *indexBuffer = nullptr;
+ gl::Error error = getStreamingIndexBuffer(dstType, &indexBuffer);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(indexBuffer != nullptr);
+
+ unsigned int offset;
+ StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, usePrimitiveRestartFixedIndex,
+ &offset);
+
+ translated->indexBuffer = indexBuffer->getIndexBuffer();
+ translated->serial = indexBuffer->getSerial();
+ translated->startIndex = (offset >> dstTypeInfo.bytesShift);
+ translated->startOffset = offset;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType,
+ IndexBufferInterface **outBuffer)
+{
+ ASSERT(outBuffer);
+ if (destinationIndexType == GL_UNSIGNED_INT)
+ {
+ if (!mStreamingBufferInt)
+ {
+ mStreamingBufferInt = new StreamingIndexBufferInterface(mFactory);
+ gl::Error error = mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE,
+ GL_UNSIGNED_INT);
+ if (error.isError())
+ {
+ SafeDelete(mStreamingBufferInt);
+ return error;
+ }
+ }
+
+ *outBuffer = mStreamingBufferInt;
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ ASSERT(destinationIndexType == GL_UNSIGNED_SHORT);
+
+ if (!mStreamingBufferShort)
+ {
+ mStreamingBufferShort = new StreamingIndexBufferInterface(mFactory);
+ gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE,
+ GL_UNSIGNED_SHORT);
+ if (error.isError())
+ {
+ SafeDelete(mStreamingBufferShort);
+ return error;
+ }
+ }
+
+ *outBuffer = mStreamingBufferShort;
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.h b/gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
new file mode 100755
index 000000000..44eb68c07
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 GLvoid *srcIndices;
+ unsigned int srcCount;
+ GLenum srcIndexType;
+ bool srcIndicesChanged;
+};
+
+struct TranslatedIndexData
+{
+ gl::IndexRange indexRange;
+ unsigned int startIndex;
+ unsigned int startOffset; // In bytes
+
+ IndexBuffer *indexBuffer;
+ BufferD3D *storage;
+ GLenum indexType;
+ unsigned int serial;
+
+ SourceIndexData srcIndexData;
+};
+
+class IndexDataManager : angle::NonCopyable
+{
+ public:
+ explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass);
+ virtual ~IndexDataManager();
+
+ gl::Error prepareIndexData(GLenum srcType,
+ GLsizei count,
+ gl::Buffer *glBuffer,
+ const GLvoid *indices,
+ TranslatedIndexData *translated,
+ bool primitiveRestartFixedIndexEnabled);
+
+ private:
+ gl::Error streamIndexData(const GLvoid *data,
+ unsigned int count,
+ GLenum srcType,
+ GLenum dstType,
+ bool usePrimitiveRestartFixedIndex,
+ TranslatedIndexData *translated);
+ gl::Error getStreamingIndexBuffer(GLenum destinationIndexType,
+ IndexBufferInterface **outBuffer);
+
+ BufferFactoryD3D *const mFactory;
+ RendererClass mRendererClass;
+ StreamingIndexBufferInterface *mStreamingBufferShort;
+ StreamingIndexBufferInterface *mStreamingBufferInt;
+};
+
+}
+
+#endif // LIBANGLE_INDEXDATAMANAGER_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp
new file mode 100755
index 000000000..113bad647
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 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/src/libANGLE/renderer/d3d/NativeWindowD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h
new file mode 100755
index 000000000..365448488
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 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/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
new file mode 100755
index 000000000..d00a8738e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -0,0 +1,2301 @@
+//
+// Copyright (c) 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/BitSetIterator.h"
+#include "common/utilities.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+#include "libANGLE/renderer/d3d/VaryingPacking.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+
+namespace rx
+{
+
+namespace
+{
+
+gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
+{
+ gl::InputLayout defaultLayout;
+ for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes())
+ {
+ 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::VertexFormatType defaultType =
+ gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt);
+
+ defaultLayout.push_back(defaultType);
+ }
+ }
+ }
+
+ return defaultLayout;
+}
+
+std::vector<GLenum> GetDefaultOutputLayoutFromShader(
+ const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
+{
+ std::vector<GLenum> defaultPixelOutput;
+
+ if (!shaderOutputVars.empty())
+ {
+ defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 +
+ static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
+ }
+
+ return defaultPixelOutput;
+}
+
+bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
+{
+ return var.isRowMajorLayout;
+}
+
+bool IsRowMajorLayout(const sh::ShaderVariable &var)
+{
+ return false;
+}
+
+// true if varying x has a higher priority in packing than y
+bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
+{
+ return gl::CompareShaderVar(*x.varying, *y.varying);
+}
+
+std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
+ const gl::Shader &fragmentShader,
+ const std::vector<std::string> &tfVaryings)
+{
+ std::vector<PackedVarying> packedVaryings;
+
+ for (const sh::Varying &output : vertexShader.getVaryings())
+ {
+ bool packed = false;
+
+ // Built-in varyings obey special rules
+ if (output.isBuiltIn())
+ {
+ continue;
+ }
+
+ for (const sh::Varying &input : fragmentShader.getVaryings())
+ {
+ if (output.name == input.name)
+ {
+ if (output.isStruct())
+ {
+ ASSERT(!output.isArray());
+ for (const auto &field : output.fields)
+ {
+ ASSERT(!field.isStruct() && !field.isArray());
+ packedVaryings.push_back(
+ PackedVarying(field, input.interpolation, input.name));
+ }
+ }
+ else
+ {
+ packedVaryings.push_back(PackedVarying(input, input.interpolation));
+ }
+ packed = true;
+ break;
+ }
+ }
+
+ // Keep Transform FB varyings in the merged list always.
+ if (!packed)
+ {
+ for (const std::string &tfVarying : tfVaryings)
+ {
+ if (tfVarying == output.name)
+ {
+ // Transform feedback for varying structs is underspecified.
+ // See Khronos bug 9856.
+ // TODO(jmadill): Figure out how to be spec-compliant here.
+ if (!output.isStruct())
+ {
+ packedVaryings.push_back(PackedVarying(output, output.interpolation));
+ packedVaryings.back().vertexOnly = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ std::sort(packedVaryings.begin(), packedVaryings.end(), ComparePackedVarying);
+
+ return packedVaryings;
+}
+
+template <typename VarT>
+void GetUniformBlockInfo(const std::vector<VarT> &fields,
+ const std::string &prefix,
+ sh::BlockLayoutEncoder *encoder,
+ bool inRowMajorLayout,
+ std::map<std::string, sh::BlockMemberInfo> *blockInfoOut)
+{
+ for (const VarT &field : fields)
+ {
+ const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
+
+ if (field.isStruct())
+ {
+ bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
+
+ for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
+ {
+ encoder->enterAggregateType();
+
+ const std::string uniformElementName =
+ fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
+ GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout,
+ blockInfoOut);
+
+ encoder->exitAggregateType();
+ }
+ }
+ else
+ {
+ bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
+ (*blockInfoOut)[fieldName] =
+ encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
+ }
+ }
+}
+
+template <typename T>
+static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag)
+{
+ ASSERT(dest != NULL);
+ ASSERT(dirtyFlag != NULL);
+
+ *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
+ *dest = source;
+}
+
+template <typename T>
+bool TransposeMatrix(T *target,
+ const GLfloat *value,
+ int targetWidth,
+ int targetHeight,
+ int srcWidth,
+ int srcHeight)
+{
+ bool dirty = false;
+ int copyWidth = std::min(targetHeight, srcWidth);
+ int copyHeight = std::min(targetWidth, srcHeight);
+
+ for (int x = 0; x < copyWidth; x++)
+ {
+ for (int y = 0; y < copyHeight; y++)
+ {
+ SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]),
+ &dirty);
+ }
+ }
+ // clear unfilled right side
+ for (int y = 0; y < copyWidth; y++)
+ {
+ for (int x = copyHeight; x < targetWidth; x++)
+ {
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+ }
+ }
+ // clear unfilled bottom.
+ for (int y = copyWidth; y < targetHeight; y++)
+ {
+ for (int x = 0; x < targetWidth; x++)
+ {
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+ }
+ }
+
+ return dirty;
+}
+
+template <typename T>
+bool ExpandMatrix(T *target,
+ const GLfloat *value,
+ int targetWidth,
+ int targetHeight,
+ int srcWidth,
+ int srcHeight)
+{
+ bool dirty = false;
+ int copyWidth = std::min(targetWidth, srcWidth);
+ int copyHeight = std::min(targetHeight, srcHeight);
+
+ for (int y = 0; y < copyHeight; y++)
+ {
+ for (int x = 0; x < copyWidth; x++)
+ {
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]),
+ &dirty);
+ }
+ }
+ // clear unfilled right side
+ for (int y = 0; y < copyHeight; y++)
+ {
+ for (int x = copyWidth; x < targetWidth; x++)
+ {
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+ }
+ }
+ // clear unfilled bottom.
+ for (int y = copyHeight; y < targetHeight; y++)
+ {
+ for (int x = 0; x < targetWidth; x++)
+ {
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+ }
+ }
+
+ return dirty;
+}
+
+gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode)
+{
+ switch (drawMode)
+ {
+ // Uses the point sprite geometry shader.
+ case GL_POINTS:
+ return gl::PRIMITIVE_POINTS;
+
+ // All line drawing uses the same geometry shader.
+ case GL_LINES:
+ case GL_LINE_STRIP:
+ case GL_LINE_LOOP:
+ return gl::PRIMITIVE_LINES;
+
+ // The triangle fan primitive is emulated with strips in D3D11.
+ case GL_TRIANGLES:
+ case GL_TRIANGLE_FAN:
+ return gl::PRIMITIVE_TRIANGLES;
+
+ // Special case for triangle strips.
+ case GL_TRIANGLE_STRIP:
+ return gl::PRIMITIVE_TRIANGLE_STRIP;
+
+ default:
+ UNREACHABLE();
+ return gl::PRIMITIVE_TYPE_MAX;
+ }
+}
+
+} // anonymous namespace
+
+// D3DUniform Implementation
+
+D3DUniform::D3DUniform(GLenum typeIn,
+ const std::string &nameIn,
+ unsigned int arraySizeIn,
+ bool defaultBlock)
+ : type(typeIn),
+ name(nameIn),
+ arraySize(arraySizeIn),
+ data(nullptr),
+ dirty(true),
+ vsRegisterIndex(GL_INVALID_INDEX),
+ psRegisterIndex(GL_INVALID_INDEX),
+ registerCount(0),
+ registerElement(0)
+{
+ // 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)
+ {
+ size_t bytes = gl::VariableInternalSize(type) * elementCount();
+ data = new uint8_t[bytes];
+ memset(data, 0, bytes);
+
+ // TODO(jmadill): is this correct with non-square matrices?
+ registerCount = gl::VariableRowCount(type) * elementCount();
+ }
+}
+
+D3DUniform::~D3DUniform()
+{
+ SafeDeleteArray(data);
+}
+
+bool D3DUniform::isSampler() const
+{
+ return gl::IsSamplerType(type);
+}
+
+bool D3DUniform::isReferencedByVertexShader() const
+{
+ return vsRegisterIndex != GL_INVALID_INDEX;
+}
+
+bool D3DUniform::isReferencedByFragmentShader() const
+{
+ return psRegisterIndex != GL_INVALID_INDEX;
+}
+
+// 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 ShaderD3D *vertexShader,
+ const ShaderD3D *fragmentShader)
+ : mRendererMajorShaderModel(renderer->getMajorShaderModel()),
+ mShaderModelSuffix(renderer->getShaderModelSuffix()),
+ mUsesInstancedPointSpriteEmulation(
+ renderer->getWorkarounds().useInstancedPointSpriteEmulation),
+ mUsesViewScale(renderer->presentPathFastEnabled()),
+ mVertexShader(vertexShader),
+ mFragmentShader(fragmentShader)
+{
+}
+
+int ProgramD3DMetadata::getRendererMajorShaderModel() const
+{
+ return mRendererMajorShaderModel;
+}
+
+bool ProgramD3DMetadata::usesBroadcast(const gl::ContextState &data) const
+{
+ return (mFragmentShader->usesFragColor() && data.getClientMajorVersion() < 3);
+}
+
+bool ProgramD3DMetadata::usesFragDepth() const
+{
+ return mFragmentShader->usesFragDepth();
+}
+
+bool ProgramD3DMetadata::usesPointCoord() const
+{
+ return mFragmentShader->usesPointCoord();
+}
+
+bool ProgramD3DMetadata::usesFragCoord() const
+{
+ return mFragmentShader->usesFragCoord();
+}
+
+bool ProgramD3DMetadata::usesPointSize() const
+{
+ return mVertexShader->usesPointSize();
+}
+
+bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
+{
+ return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() &&
+ mRendererMajorShaderModel >= 4;
+}
+
+bool ProgramD3DMetadata::usesViewScale() const
+{
+ return mUsesViewScale;
+}
+
+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 dummy 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
+{
+ return mFragmentShader->usesMultipleRenderTargets();
+}
+
+GLint ProgramD3DMetadata::getMajorShaderVersion() const
+{
+ return mVertexShader->getData().getShaderVersion();
+}
+
+const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
+{
+ return mFragmentShader;
+}
+
+// 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)
+ {
+ gl::VertexFormatType vertexFormatType = inputLayout[index];
+ if (vertexFormatType == gl::VERTEX_FORMAT_INVALID)
+ continue;
+
+ VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatType);
+ if ((conversionType & VERTEX_CONVERT_GPU) == 0)
+ continue;
+
+ GLenum componentType = renderer->getVertexComponentType(vertexFormatType);
+ (*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::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
+{
+}
+
+unsigned int ProgramD3D::mCurrentSerial = 1;
+
+ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
+ : ProgramImpl(state),
+ mRenderer(renderer),
+ mDynamicHLSL(NULL),
+ mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX, nullptr),
+ mUsesPointSize(false),
+ mUsesFlatInterpolation(false),
+ mVertexUniformStorage(NULL),
+ mFragmentUniformStorage(NULL),
+ mUsedVertexSamplerRange(0),
+ mUsedPixelSamplerRange(0),
+ mDirtySamplerMapping(true),
+ mSerial(issueSerial())
+{
+ mDynamicHLSL = new DynamicHLSL(renderer);
+}
+
+ProgramD3D::~ProgramD3D()
+{
+ reset();
+ SafeDelete(mDynamicHLSL);
+}
+
+bool ProgramD3D::usesPointSpriteEmulation() const
+{
+ return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
+}
+
+bool ProgramD3D::usesGeometryShader(GLenum drawMode) const
+{
+ if (drawMode != GL_POINTS)
+ {
+ return mUsesFlatInterpolation;
+ }
+
+ return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
+}
+
+bool ProgramD3D::usesInstancedPointSpriteEmulation() const
+{
+ return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
+}
+
+GLint ProgramD3D::getSamplerMapping(gl::SamplerType type,
+ unsigned int samplerIndex,
+ const gl::Caps &caps) const
+{
+ GLint logicalTextureUnit = -1;
+
+ switch (type)
+ {
+ case gl::SAMPLER_PIXEL:
+ ASSERT(samplerIndex < caps.maxTextureImageUnits);
+ if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
+ {
+ logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
+ }
+ break;
+ case gl::SAMPLER_VERTEX:
+ ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
+ if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
+ {
+ logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ if (logicalTextureUnit >= 0 &&
+ logicalTextureUnit < static_cast<GLint>(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).
+GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
+{
+ switch (type)
+ {
+ case gl::SAMPLER_PIXEL:
+ ASSERT(samplerIndex < mSamplersPS.size());
+ ASSERT(mSamplersPS[samplerIndex].active);
+ return mSamplersPS[samplerIndex].textureType;
+ case gl::SAMPLER_VERTEX:
+ ASSERT(samplerIndex < mSamplersVS.size());
+ ASSERT(mSamplersVS[samplerIndex].active);
+ return mSamplersVS[samplerIndex].textureType;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_TEXTURE_2D;
+}
+
+GLuint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
+{
+ switch (type)
+ {
+ case gl::SAMPLER_PIXEL:
+ return mUsedPixelSamplerRange;
+ case gl::SAMPLER_VERTEX:
+ return mUsedVertexSamplerRange;
+ default:
+ UNREACHABLE();
+ return 0u;
+ }
+}
+
+void ProgramD3D::updateSamplerMapping()
+{
+ if (!mDirtySamplerMapping)
+ {
+ return;
+ }
+
+ mDirtySamplerMapping = false;
+
+ // Retrieve sampler uniform values
+ for (const D3DUniform *d3dUniform : mD3DUniforms)
+ {
+ if (!d3dUniform->dirty)
+ continue;
+
+ if (!d3dUniform->isSampler())
+ continue;
+
+ int count = d3dUniform->elementCount();
+ const GLint(*v)[4] = reinterpret_cast<const GLint(*)[4]>(d3dUniform->data);
+
+ if (d3dUniform->isReferencedByFragmentShader())
+ {
+ unsigned int firstIndex = d3dUniform->psRegisterIndex;
+
+ for (int i = 0; i < count; i++)
+ {
+ unsigned int samplerIndex = firstIndex + i;
+
+ if (samplerIndex < mSamplersPS.size())
+ {
+ ASSERT(mSamplersPS[samplerIndex].active);
+ mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
+ }
+ }
+ }
+
+ if (d3dUniform->isReferencedByVertexShader())
+ {
+ unsigned int firstIndex = d3dUniform->vsRegisterIndex;
+
+ for (int i = 0; i < count; i++)
+ {
+ unsigned int samplerIndex = firstIndex + i;
+
+ if (samplerIndex < mSamplersVS.size())
+ {
+ ASSERT(mSamplersVS[samplerIndex].active);
+ mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
+ }
+ }
+ }
+ }
+}
+
+LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
+{
+ reset();
+
+ DeviceIdentifier binaryDeviceIdentifier = {0};
+ 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 false;
+ }
+
+ int compileFlags = stream->readInt<int>();
+ if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+ {
+ infoLog << "Mismatched compilation flags.";
+ return false;
+ }
+
+ for (int &index : mAttribLocationToD3DSemantic)
+ {
+ stream->readInt(&index);
+ }
+
+ const unsigned int psSamplerCount = stream->readInt<unsigned int>();
+ for (unsigned int i = 0; i < psSamplerCount; ++i)
+ {
+ Sampler sampler;
+ stream->readBool(&sampler.active);
+ stream->readInt(&sampler.logicalTextureUnit);
+ stream->readInt(&sampler.textureType);
+ mSamplersPS.push_back(sampler);
+ }
+ const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
+ for (unsigned int i = 0; i < vsSamplerCount; ++i)
+ {
+ Sampler sampler;
+ stream->readBool(&sampler.active);
+ stream->readInt(&sampler.logicalTextureUnit);
+ stream->readInt(&sampler.textureType);
+ mSamplersVS.push_back(sampler);
+ }
+
+ stream->readInt(&mUsedVertexSamplerRange);
+ stream->readInt(&mUsedPixelSamplerRange);
+
+ const unsigned int uniformCount = stream->readInt<unsigned int>();
+ if (stream->error())
+ {
+ infoLog << "Invalid program binary.";
+ return false;
+ }
+
+ const auto &linkedUniforms = mState.getUniforms();
+ ASSERT(mD3DUniforms.empty());
+ for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
+ {
+ const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
+
+ D3DUniform *d3dUniform =
+ new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize,
+ linkedUniform.isInDefaultBlock());
+ stream->readInt(&d3dUniform->psRegisterIndex);
+ stream->readInt(&d3dUniform->vsRegisterIndex);
+ stream->readInt(&d3dUniform->registerCount);
+ stream->readInt(&d3dUniform->registerElement);
+
+ mD3DUniforms.push_back(d3dUniform);
+ }
+
+ const unsigned int blockCount = stream->readInt<unsigned int>();
+ if (stream->error())
+ {
+ infoLog << "Invalid program binary.";
+ return false;
+ }
+
+ ASSERT(mD3DUniformBlocks.empty());
+ for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ D3DUniformBlock uniformBlock;
+ stream->readInt(&uniformBlock.psRegisterIndex);
+ stream->readInt(&uniformBlock.vsRegisterIndex);
+ mD3DUniformBlocks.push_back(uniformBlock);
+ }
+
+ const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>();
+ mStreamOutVaryings.resize(streamOutVaryingCount);
+ for (unsigned int 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);
+ }
+
+ stream->readString(&mVertexHLSL);
+ stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
+ sizeof(D3DCompilerWorkarounds));
+ stream->readString(&mPixelHLSL);
+ stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
+ sizeof(D3DCompilerWorkarounds));
+ stream->readBool(&mUsesFragDepth);
+ stream->readBool(&mUsesPointSize);
+ stream->readBool(&mUsesFlatInterpolation);
+
+ const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
+ 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].outputIndex);
+ }
+
+ stream->readString(&mGeometryShaderPreamble);
+
+ const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
+
+ bool separateAttribs = (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
+
+ const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
+ for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
+ vertexShaderIndex++)
+ {
+ size_t inputLayoutSize = stream->readInt<size_t>();
+ gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
+
+ for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
+ {
+ inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
+ }
+
+ unsigned int vertexShaderSize = stream->readInt<unsigned int>();
+ const unsigned char *vertexShaderFunction = binary + stream->offset();
+
+ ShaderExecutableD3D *shaderExecutable = nullptr;
+
+ ANGLE_TRY(mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize, SHADER_VERTEX,
+ mStreamOutVaryings, separateAttribs,
+ &shaderExecutable));
+
+ if (!shaderExecutable)
+ {
+ infoLog << "Could not create vertex shader.";
+ return false;
+ }
+
+ // generated converted input layout
+ VertexExecutable::Signature signature;
+ VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
+
+ // add new binary
+ mVertexExecutables.push_back(
+ new VertexExecutable(inputLayout, signature, shaderExecutable));
+
+ stream->skip(vertexShaderSize);
+ }
+
+ const size_t pixelShaderCount = stream->readInt<unsigned int>();
+ for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
+ {
+ const size_t outputCount = stream->readInt<unsigned int>();
+ std::vector<GLenum> outputs(outputCount);
+ for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
+ {
+ stream->readInt(&outputs[outputIndex]);
+ }
+
+ const size_t pixelShaderSize = stream->readInt<unsigned int>();
+ const unsigned char *pixelShaderFunction = binary + stream->offset();
+ ShaderExecutableD3D *shaderExecutable = nullptr;
+
+ ANGLE_TRY(mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL,
+ mStreamOutVaryings, separateAttribs,
+ &shaderExecutable));
+
+ if (!shaderExecutable)
+ {
+ infoLog << "Could not create pixel shader.";
+ return false;
+ }
+
+ // add new binary
+ mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
+
+ stream->skip(pixelShaderSize);
+ }
+
+ for (unsigned int geometryExeIndex = 0; geometryExeIndex < gl::PRIMITIVE_TYPE_MAX;
+ ++geometryExeIndex)
+ {
+ unsigned int geometryShaderSize = stream->readInt<unsigned int>();
+ if (geometryShaderSize == 0)
+ {
+ mGeometryExecutables[geometryExeIndex] = nullptr;
+ continue;
+ }
+
+ const unsigned char *geometryShaderFunction = binary + stream->offset();
+
+ ANGLE_TRY(mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize,
+ SHADER_GEOMETRY, mStreamOutVaryings, separateAttribs,
+ &mGeometryExecutables[geometryExeIndex]));
+
+ if (!mGeometryExecutables[geometryExeIndex])
+ {
+ infoLog << "Could not create geometry shader.";
+ return false;
+ }
+ stream->skip(geometryShaderSize);
+ }
+
+ initializeUniformStorage();
+
+ return true;
+}
+
+gl::Error ProgramD3D::save(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);
+ }
+
+ stream->writeInt(mSamplersPS.size());
+ for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
+ {
+ stream->writeInt(mSamplersPS[i].active);
+ stream->writeInt(mSamplersPS[i].logicalTextureUnit);
+ stream->writeInt(mSamplersPS[i].textureType);
+ }
+
+ stream->writeInt(mSamplersVS.size());
+ for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
+ {
+ stream->writeInt(mSamplersVS[i].active);
+ stream->writeInt(mSamplersVS[i].logicalTextureUnit);
+ stream->writeInt(mSamplersVS[i].textureType);
+ }
+
+ stream->writeInt(mUsedVertexSamplerRange);
+ stream->writeInt(mUsedPixelSamplerRange);
+
+ stream->writeInt(mD3DUniforms.size());
+ for (const D3DUniform *uniform : mD3DUniforms)
+ {
+ // Type, name and arraySize are redundant, so aren't stored in the binary.
+ stream->writeIntOrNegOne(uniform->psRegisterIndex);
+ stream->writeIntOrNegOne(uniform->vsRegisterIndex);
+ stream->writeInt(uniform->registerCount);
+ stream->writeInt(uniform->registerElement);
+ }
+
+ stream->writeInt(mD3DUniformBlocks.size());
+ for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
+ {
+ stream->writeIntOrNegOne(uniformBlock.psRegisterIndex);
+ stream->writeIntOrNegOne(uniformBlock.vsRegisterIndex);
+ }
+
+ stream->writeInt(mStreamOutVaryings.size());
+ for (const auto &varying : mStreamOutVaryings)
+ {
+ stream->writeString(varying.semanticName);
+ stream->writeInt(varying.semanticIndex);
+ stream->writeInt(varying.componentCount);
+ stream->writeInt(varying.outputSlot);
+ }
+
+ stream->writeString(mVertexHLSL);
+ stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
+ sizeof(D3DCompilerWorkarounds));
+ stream->writeString(mPixelHLSL);
+ stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
+ sizeof(D3DCompilerWorkarounds));
+ stream->writeInt(mUsesFragDepth);
+ stream->writeInt(mUsesPointSize);
+ stream->writeInt(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.outputIndex);
+ }
+
+ stream->writeString(mGeometryShaderPreamble);
+
+ stream->writeInt(mVertexExecutables.size());
+ for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
+ vertexExecutableIndex++)
+ {
+ VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
+
+ const auto &inputLayout = vertexExecutable->inputs();
+ stream->writeInt(inputLayout.size());
+
+ for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
+ {
+ stream->writeInt(static_cast<unsigned int>(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];
+
+ 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 (const ShaderExecutableD3D *geometryExe : mGeometryExecutables)
+ {
+ if (geometryExe == nullptr)
+ {
+ stream->writeInt(0);
+ continue;
+ }
+
+ size_t geometryShaderSize = geometryExe->getLength();
+ stream->writeInt(geometryShaderSize);
+ stream->writeBytes(geometryExe->getFunction(), geometryShaderSize);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */)
+{
+}
+
+gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
+ ShaderExecutableD3D **outExecutable)
+{
+ mPixelShaderOutputFormatCache.clear();
+
+ const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
+ const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender();
+
+ for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
+ {
+ const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
+
+ if (colorbuffer)
+ {
+ mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK
+ ? GL_COLOR_ATTACHMENT0
+ : colorbuffer->getBinding());
+ }
+ else
+ {
+ mPixelShaderOutputFormatCache.push_back(GL_NONE);
+ }
+ }
+
+ return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
+}
+
+gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
+ ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog)
+{
+ for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
+ {
+ if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
+ {
+ *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
+ return gl::Error(GL_NO_ERROR);
+ }
+ }
+
+ std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
+ mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature);
+
+ // Generate new pixel executable
+ ShaderExecutableD3D *pixelExecutable = NULL;
+
+ gl::InfoLog tempInfoLog;
+ gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+ gl::Error error = mRenderer->compileToExecutable(
+ *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mStreamOutVaryings,
+ (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
+ &pixelExecutable);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (pixelExecutable)
+ {
+ mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
+ }
+ else if (!infoLog)
+ {
+ std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
+ tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
+ ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
+ }
+
+ *outExectuable = pixelExecutable;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
+ ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog)
+{
+ VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature);
+
+ for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
+ {
+ if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
+ {
+ *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
+ return gl::Error(GL_NO_ERROR);
+ }
+ }
+
+ // Generate new dynamic layout with attribute conversions
+ std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
+ mVertexHLSL, inputLayout, mState.getAttributes());
+
+ // Generate new vertex executable
+ ShaderExecutableD3D *vertexExecutable = NULL;
+
+ gl::InfoLog tempInfoLog;
+ gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+ gl::Error error = mRenderer->compileToExecutable(
+ *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mStreamOutVaryings,
+ (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
+ &vertexExecutable);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (vertexExecutable)
+ {
+ mVertexExecutables.push_back(
+ new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable));
+ }
+ else if (!infoLog)
+ {
+ std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
+ tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
+ ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
+ }
+
+ *outExectuable = vertexExecutable;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::ContextState &data,
+ GLenum 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(drawMode))
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
+
+ if (mGeometryExecutables[geometryShaderType] != nullptr)
+ {
+ if (outExecutable)
+ {
+ *outExecutable = mGeometryExecutables[geometryShaderType];
+ }
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
+ geometryShaderType, data, mState, mRenderer->presentPathFastEnabled(),
+ mGeometryShaderPreamble);
+
+ gl::InfoLog tempInfoLog;
+ gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+ gl::Error error = mRenderer->compileToExecutable(
+ *currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mStreamOutVaryings,
+ (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), D3DCompilerWorkarounds(),
+ &mGeometryExecutables[geometryShaderType]);
+
+ if (!infoLog && error.isError())
+ {
+ std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
+ tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
+ ERR("Error compiling dynamic geometry executable:\n%s\n", &tempCharBuffer[0]);
+ }
+
+ if (outExecutable)
+ {
+ *outExecutable = mGeometryExecutables[geometryShaderType];
+ }
+ return error;
+}
+
+LinkResult ProgramD3D::compileProgramExecutables(const gl::ContextState &data, gl::InfoLog &infoLog)
+{
+ const gl::InputLayout &defaultInputLayout =
+ GetDefaultInputLayoutFromShader(mState.getAttachedVertexShader());
+ ShaderExecutableD3D *defaultVertexExecutable = nullptr;
+ ANGLE_TRY(
+ getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog));
+
+ std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
+ ShaderExecutableD3D *defaultPixelExecutable = nullptr;
+ ANGLE_TRY(
+ getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog));
+
+ // Auto-generate the geometry shader here, if we expect to be using point rendering in D3D11.
+ ShaderExecutableD3D *pointGS = nullptr;
+ if (usesGeometryShader(GL_POINTS))
+ {
+ getGeometryExecutableForPrimitiveType(data, GL_POINTS, &pointGS, &infoLog);
+ }
+
+ const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
+
+ if (usesGeometryShader(GL_POINTS) && 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.
+ vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
+ vertexShaderD3D->appendDebugInfo(pointGS->getDebugInfo());
+ vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
+ }
+
+ if (defaultVertexExecutable)
+ {
+ vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
+ }
+
+ if (defaultPixelExecutable)
+ {
+ const ShaderD3D *fragmentShaderD3D =
+ GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
+ fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
+ }
+
+ return (defaultVertexExecutable && defaultPixelExecutable &&
+ (!usesGeometryShader(GL_POINTS) || pointGS));
+}
+
+LinkResult ProgramD3D::link(const gl::ContextState &data, gl::InfoLog &infoLog)
+{
+ reset();
+
+ const gl::Shader *vertexShader = mState.getAttachedVertexShader();
+ const gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
+
+ const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
+ const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
+
+ mSamplersVS.resize(data.getCaps().maxVertexTextureImageUnits);
+ mSamplersPS.resize(data.getCaps().maxTextureImageUnits);
+
+ vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
+ fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
+
+ if (mRenderer->getNativeLimitations().noFrontFacingSupport)
+ {
+ if (fragmentShaderD3D->usesFrontFacing())
+ {
+ infoLog << "The current renderer doesn't support gl_FrontFacing";
+ return false;
+ }
+ }
+
+ std::vector<PackedVarying> packedVaryings =
+ MergeVaryings(*vertexShader, *fragmentShader, mState.getTransformFeedbackVaryingNames());
+
+ // Map the varyings to the register file
+ VaryingPacking varyingPacking(data.getCaps().maxVaryingVectors);
+ if (!varyingPacking.packVaryings(infoLog, packedVaryings,
+ mState.getTransformFeedbackVaryingNames()))
+ {
+ return false;
+ }
+
+ ProgramD3DMetadata metadata(mRenderer, vertexShaderD3D, fragmentShaderD3D);
+
+ varyingPacking.enableBuiltins(SHADER_VERTEX, metadata);
+ varyingPacking.enableBuiltins(SHADER_PIXEL, metadata);
+
+ if (static_cast<GLuint>(varyingPacking.getRegisterCount()) > data.getCaps().maxVaryingVectors)
+ {
+ infoLog << "No varying registers left to support gl_FragCoord/gl_PointCoord";
+ return false;
+ }
+
+ // TODO(jmadill): Implement more sophisticated component packing in D3D9.
+ // We can fail here because we use one semantic per GLSL varying. D3D11 can pack varyings
+ // intelligently, but D3D9 assumes one semantic per register.
+ if (mRenderer->getRendererClass() == RENDERER_D3D9 &&
+ varyingPacking.getMaxSemanticIndex() > data.getCaps().maxVaryingVectors)
+ {
+ infoLog << "Cannot pack these varyings on D3D9.";
+ return false;
+ }
+
+ if (!mDynamicHLSL->generateShaderLinkHLSL(data, mState, metadata, varyingPacking, &mPixelHLSL,
+ &mVertexHLSL))
+ {
+ return false;
+ }
+
+ mUsesPointSize = vertexShaderD3D->usesPointSize();
+ mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey);
+ mUsesFragDepth = metadata.usesFragDepth();
+
+ // Cache if we use flat shading
+ mUsesFlatInterpolation = false;
+ for (const auto &varying : packedVaryings)
+ {
+ if (varying.interpolation == sh::INTERPOLATION_FLAT)
+ {
+ mUsesFlatInterpolation = true;
+ break;
+ }
+ }
+
+ if (mRenderer->getMajorShaderModel() >= 4)
+ {
+ varyingPacking.enableBuiltins(SHADER_GEOMETRY, metadata);
+ mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(varyingPacking);
+ }
+
+ initAttribLocationsToD3DSemantic();
+
+ defineUniformsAndAssignRegisters();
+
+ gatherTransformFeedbackVaryings(varyingPacking);
+
+ LinkResult result = compileProgramExecutables(data, infoLog);
+ if (result.isError())
+ {
+ infoLog << result.getError().getMessage();
+ return result;
+ }
+ else if (!result.getResult())
+ {
+ infoLog << "Failed to create D3D shaders.";
+ return result;
+ }
+
+ initUniformBlockInfo();
+
+ return true;
+}
+
+GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
+{
+ // TODO(jmadill): Do something useful here?
+ return GL_TRUE;
+}
+
+void ProgramD3D::initUniformBlockInfo()
+{
+ const gl::Shader *vertexShader = mState.getAttachedVertexShader();
+
+ for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
+ {
+ if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
+ continue;
+
+ if (mBlockDataSizes.count(vertexBlock.name) > 0)
+ continue;
+
+ size_t dataSize = getUniformBlockInfo(vertexBlock);
+ mBlockDataSizes[vertexBlock.name] = dataSize;
+ }
+
+ const gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
+
+ for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
+ {
+ if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
+ continue;
+
+ if (mBlockDataSizes.count(fragmentBlock.name) > 0)
+ continue;
+
+ size_t dataSize = getUniformBlockInfo(fragmentBlock);
+ mBlockDataSizes[fragmentBlock.name] = dataSize;
+ }
+}
+
+void ProgramD3D::assignUniformBlockRegisters()
+{
+ mD3DUniformBlocks.clear();
+
+ // Assign registers and update sizes.
+ const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
+ const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
+
+ for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
+ {
+ unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
+
+ D3DUniformBlock d3dUniformBlock;
+
+ if (uniformBlock.vertexStaticUse)
+ {
+ unsigned int baseRegister =
+ vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
+ d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
+ }
+
+ if (uniformBlock.fragmentStaticUse)
+ {
+ unsigned int baseRegister =
+ fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
+ d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
+ }
+
+ mD3DUniformBlocks.push_back(d3dUniformBlock);
+ }
+}
+
+void ProgramD3D::initializeUniformStorage()
+{
+ // Compute total default block size
+ unsigned int vertexRegisters = 0;
+ unsigned int fragmentRegisters = 0;
+ for (const D3DUniform *d3dUniform : mD3DUniforms)
+ {
+ if (!d3dUniform->isSampler())
+ {
+ if (d3dUniform->isReferencedByVertexShader())
+ {
+ vertexRegisters = std::max(vertexRegisters,
+ d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
+ }
+ if (d3dUniform->isReferencedByFragmentShader())
+ {
+ fragmentRegisters = std::max(
+ fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
+ }
+ }
+ }
+
+ mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
+ mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
+}
+
+gl::Error ProgramD3D::applyUniforms(GLenum drawMode)
+{
+ ASSERT(!mDirtySamplerMapping);
+
+ gl::Error error = mRenderer->applyUniforms(*this, drawMode, mD3DUniforms);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ for (D3DUniform *d3dUniform : mD3DUniforms)
+ {
+ d3dUniform->dirty = false;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error ProgramD3D::applyUniformBuffers(const gl::ContextState &data)
+{
+ if (mState.getUniformBlocks().empty())
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ // Lazy init.
+ if (mD3DUniformBlocks.empty())
+ {
+ assignUniformBlockRegisters();
+ }
+
+ mVertexUBOCache.clear();
+ mFragmentUBOCache.clear();
+
+ const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
+ const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
+
+ 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
+ if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
+ {
+ continue;
+ }
+
+ if (uniformBlock.vertexStaticUse())
+ {
+ unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
+ ASSERT(registerIndex < data.getCaps().maxVertexUniformBlocks);
+
+ if (mVertexUBOCache.size() <= registerIndex)
+ {
+ mVertexUBOCache.resize(registerIndex + 1, -1);
+ }
+
+ ASSERT(mVertexUBOCache[registerIndex] == -1);
+ mVertexUBOCache[registerIndex] = blockBinding;
+ }
+
+ if (uniformBlock.fragmentStaticUse())
+ {
+ unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
+ ASSERT(registerIndex < data.getCaps().maxFragmentUniformBlocks);
+
+ if (mFragmentUBOCache.size() <= registerIndex)
+ {
+ mFragmentUBOCache.resize(registerIndex + 1, -1);
+ }
+
+ ASSERT(mFragmentUBOCache[registerIndex] == -1);
+ mFragmentUBOCache[registerIndex] = blockBinding;
+ }
+ }
+
+ return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
+}
+
+void ProgramD3D::dirtyAllUniforms()
+{
+ for (D3DUniform *d3dUniform : mD3DUniforms)
+ {
+ d3dUniform->dirty = true;
+ }
+}
+
+void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ setUniform(location, count, v, GL_FLOAT);
+}
+
+void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ setUniform(location, count, v, GL_FLOAT_VEC2);
+}
+
+void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ setUniform(location, count, v, GL_FLOAT_VEC3);
+}
+
+void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ setUniform(location, count, v, GL_FLOAT_VEC4);
+}
+
+void ProgramD3D::setUniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
+}
+
+void ProgramD3D::setUniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
+}
+
+void ProgramD3D::setUniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
+}
+
+void ProgramD3D::setUniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
+}
+
+void ProgramD3D::setUniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
+}
+
+void ProgramD3D::setUniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
+}
+
+void ProgramD3D::setUniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
+}
+
+void ProgramD3D::setUniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
+}
+
+void ProgramD3D::setUniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
+}
+
+void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+ setUniform(location, count, v, GL_INT);
+}
+
+void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+ setUniform(location, count, v, GL_INT_VEC2);
+}
+
+void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+ setUniform(location, count, v, GL_INT_VEC3);
+}
+
+void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+ setUniform(location, count, v, GL_INT_VEC4);
+}
+
+void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ setUniform(location, count, v, GL_UNSIGNED_INT);
+}
+
+void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
+}
+
+void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
+}
+
+void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
+}
+
+void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
+ GLuint /*uniformBlockBinding*/)
+{
+}
+
+void ProgramD3D::defineUniformsAndAssignRegisters()
+{
+ D3DUniformMap uniformMap;
+ const gl::Shader *vertexShader = mState.getAttachedVertexShader();
+ for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
+
+ {
+ if (vertexUniform.staticUse)
+ {
+ defineUniformBase(vertexShader, vertexUniform, &uniformMap);
+ }
+ }
+
+ const gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
+ for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
+ {
+ if (fragmentUniform.staticUse)
+ {
+ defineUniformBase(fragmentShader, fragmentUniform, &uniformMap);
+ }
+ }
+
+ // Initialize the D3DUniform list to mirror the indexing of the GL layer.
+ for (const gl::LinkedUniform &glUniform : mState.getUniforms())
+ {
+ if (!glUniform.isInDefaultBlock())
+ continue;
+
+ auto mapEntry = uniformMap.find(glUniform.name);
+ ASSERT(mapEntry != uniformMap.end());
+ mD3DUniforms.push_back(mapEntry->second);
+ }
+
+ assignAllSamplerRegisters();
+ initializeUniformStorage();
+}
+
+void ProgramD3D::defineUniformBase(const gl::Shader *shader,
+ const sh::Uniform &uniform,
+ D3DUniformMap *uniformMap)
+{
+ // Samplers get their registers assigned in assignAllSamplerRegisters.
+ if (uniform.isBuiltIn() || gl::IsSamplerType(uniform.type))
+ {
+ defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap);
+ 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));
+ encoder.skipRegisters(startRegister);
+
+ defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap);
+}
+
+D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
+{
+ for (D3DUniform *d3dUniform : mD3DUniforms)
+ {
+ if (d3dUniform->name == name)
+ {
+ return d3dUniform;
+ }
+ }
+
+ return nullptr;
+}
+
+void ProgramD3D::defineUniform(GLenum shaderType,
+ const sh::ShaderVariable &uniform,
+ const std::string &fullName,
+ sh::HLSLBlockEncoder *encoder,
+ D3DUniformMap *uniformMap)
+{
+ if (uniform.isStruct())
+ {
+ for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
+ {
+ const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
+
+ if (encoder)
+ encoder->enterAggregateType();
+
+ for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
+ {
+ const sh::ShaderVariable &field = uniform.fields[fieldIndex];
+ const std::string &fieldFullName = (fullName + elementString + "." + field.name);
+
+ // Samplers get their registers assigned in assignAllSamplerRegisters.
+ // Also they couldn't use the same encoder as the rest of the struct, since they are
+ // extracted out of the struct by the shader translator.
+ if (gl::IsSamplerType(field.type))
+ {
+ defineUniform(shaderType, field, fieldFullName, nullptr, uniformMap);
+ }
+ else
+ {
+ defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
+ }
+ }
+
+ if (encoder)
+ encoder->exitAggregateType();
+ }
+ return;
+ }
+
+ // Not a struct. Arrays are treated as aggregate types.
+ if (uniform.isArray() && encoder)
+ {
+ encoder->enterAggregateType();
+ }
+
+ // Advance the uniform offset, to track registers allocation for structs
+ sh::BlockMemberInfo blockInfo =
+ encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
+ : sh::BlockMemberInfo::getDefaultBlockInfo();
+
+ auto uniformMapEntry = uniformMap->find(fullName);
+ D3DUniform *d3dUniform = nullptr;
+
+ if (uniformMapEntry != uniformMap->end())
+ {
+ d3dUniform = uniformMapEntry->second;
+ }
+ else
+ {
+ d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
+ (*uniformMap)[fullName] = d3dUniform;
+ }
+
+ if (encoder)
+ {
+ d3dUniform->registerElement =
+ static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
+ unsigned int reg =
+ static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
+ if (shaderType == GL_FRAGMENT_SHADER)
+ {
+ d3dUniform->psRegisterIndex = reg;
+ }
+ else
+ {
+ ASSERT(shaderType == GL_VERTEX_SHADER);
+ d3dUniform->vsRegisterIndex = reg;
+ }
+
+ // Arrays are treated as aggregate types
+ if (uniform.isArray())
+ {
+ encoder->exitAggregateType();
+ }
+ }
+}
+
+template <typename T>
+void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
+{
+ const int components = gl::VariableComponentCount(targetUniformType);
+ const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
+
+ D3DUniform *targetUniform = getD3DUniformFromLocation(location);
+
+ unsigned int elementCount = targetUniform->elementCount();
+ unsigned int arrayElement = mState.getUniformLocations()[location].element;
+ unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
+
+ if (targetUniform->type == targetUniformType)
+ {
+ T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ T *dest = target + (i * 4);
+ const T *source = v + (i * components);
+
+ for (int c = 0; c < components; c++)
+ {
+ SetIfDirty(dest + c, source[c], &targetUniform->dirty);
+ }
+ for (int c = components; c < 4; c++)
+ {
+ SetIfDirty(dest + c, T(0), &targetUniform->dirty);
+ }
+ }
+ }
+ else if (targetUniform->type == targetBoolType)
+ {
+ GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ GLint *dest = boolParams + (i * 4);
+ const T *source = v + (i * components);
+
+ for (int c = 0; c < components; c++)
+ {
+ SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE,
+ &targetUniform->dirty);
+ }
+ for (int c = components; c < 4; c++)
+ {
+ SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
+ }
+ }
+ }
+ else if (targetUniform->isSampler())
+ {
+ ASSERT(targetUniformType == GL_INT);
+
+ GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
+
+ bool wasDirty = targetUniform->dirty;
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ GLint *dest = target + (i * 4);
+ const GLint *source = reinterpret_cast<const GLint *>(v) + (i * components);
+
+ SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
+ SetIfDirty(dest + 1, 0, &targetUniform->dirty);
+ SetIfDirty(dest + 2, 0, &targetUniform->dirty);
+ SetIfDirty(dest + 3, 0, &targetUniform->dirty);
+ }
+
+ if (!wasDirty && targetUniform->dirty)
+ {
+ mDirtySamplerMapping = true;
+ }
+ }
+ else
+ UNREACHABLE();
+}
+
+template <int cols, int rows>
+void ProgramD3D::setUniformMatrixfv(GLint location,
+ GLsizei countIn,
+ GLboolean transpose,
+ const GLfloat *value,
+ GLenum targetUniformType)
+{
+ D3DUniform *targetUniform = getD3DUniformFromLocation(location);
+
+ unsigned int elementCount = targetUniform->elementCount();
+ unsigned int arrayElement = mState.getUniformLocations()[location].element;
+ unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
+
+ const unsigned int targetMatrixStride = (4 * rows);
+ GLfloat *target =
+ (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
+ if (transpose == GL_FALSE)
+ {
+ targetUniform->dirty = TransposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) ||
+ targetUniform->dirty;
+ }
+ else
+ {
+ targetUniform->dirty =
+ ExpandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
+ }
+ target += targetMatrixStride;
+ value += cols * rows;
+ }
+}
+
+size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
+{
+ ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
+
+ // define member uniforms
+ sh::Std140BlockEncoder std140Encoder;
+ sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
+ sh::BlockLayoutEncoder *encoder = nullptr;
+
+ if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
+ {
+ encoder = &std140Encoder;
+ }
+ else
+ {
+ encoder = &hlslEncoder;
+ }
+
+ GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
+ interfaceBlock.isRowMajorLayout, &mBlockInfo);
+
+ return encoder->getBlockSize();
+}
+
+void ProgramD3D::assignAllSamplerRegisters()
+{
+ for (D3DUniform *d3dUniform : mD3DUniforms)
+ {
+ if (d3dUniform->isSampler())
+ {
+ assignSamplerRegisters(d3dUniform);
+ }
+ }
+}
+
+void ProgramD3D::assignSamplerRegisters(D3DUniform *d3dUniform)
+{
+ ASSERT(d3dUniform->isSampler());
+ const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
+ const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
+ ASSERT(vertexShaderD3D->hasUniform(d3dUniform) || fragmentShaderD3D->hasUniform(d3dUniform));
+ if (vertexShaderD3D->hasUniform(d3dUniform))
+ {
+ d3dUniform->vsRegisterIndex = vertexShaderD3D->getUniformRegister(d3dUniform->name);
+ ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX);
+ AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
+ mSamplersVS, &mUsedVertexSamplerRange);
+ }
+ if (fragmentShaderD3D->hasUniform(d3dUniform))
+ {
+ d3dUniform->psRegisterIndex = fragmentShaderD3D->getUniformRegister(d3dUniform->name);
+ ASSERT(d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
+ AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
+ mSamplersPS, &mUsedPixelSamplerRange);
+ }
+}
+
+// static
+void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
+ GLenum samplerType,
+ unsigned int samplerCount,
+ std::vector<Sampler> &outSamplers,
+ GLuint *outUsedRange)
+{
+ unsigned int samplerIndex = startSamplerIndex;
+
+ do
+ {
+ ASSERT(samplerIndex < outSamplers.size());
+ Sampler *sampler = &outSamplers[samplerIndex];
+ sampler->active = true;
+ sampler->textureType = gl::SamplerTypeToTextureType(samplerType);
+ sampler->logicalTextureUnit = 0;
+ *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
+ samplerIndex++;
+ } while (samplerIndex < startSamplerIndex + samplerCount);
+}
+
+void ProgramD3D::reset()
+{
+ SafeDeleteContainer(mVertexExecutables);
+ SafeDeleteContainer(mPixelExecutables);
+
+ for (auto &element : mGeometryExecutables)
+ {
+ SafeDelete(element);
+ }
+
+ mVertexHLSL.clear();
+ mVertexWorkarounds = D3DCompilerWorkarounds();
+
+ mPixelHLSL.clear();
+ mPixelWorkarounds = D3DCompilerWorkarounds();
+ mUsesFragDepth = false;
+ mPixelShaderKey.clear();
+ mUsesPointSize = false;
+ mUsesFlatInterpolation = false;
+
+ SafeDeleteContainer(mD3DUniforms);
+ mD3DUniformBlocks.clear();
+
+ SafeDelete(mVertexUniformStorage);
+ SafeDelete(mFragmentUniformStorage);
+
+ mSamplersPS.clear();
+ mSamplersVS.clear();
+
+ mUsedVertexSamplerRange = 0;
+ mUsedPixelSamplerRange = 0;
+ mDirtySamplerMapping = true;
+
+ mAttribLocationToD3DSemantic.fill(-1);
+
+ mStreamOutVaryings.clear();
+
+ mGeometryShaderPreamble.clear();
+}
+
+unsigned int ProgramD3D::getSerial() const
+{
+ return mSerial;
+}
+
+unsigned int ProgramD3D::issueSerial()
+{
+ return mCurrentSerial++;
+}
+
+void ProgramD3D::initAttribLocationsToD3DSemantic()
+{
+ const gl::Shader *vertexShader = mState.getAttachedVertexShader();
+ ASSERT(vertexShader != nullptr);
+
+ // Init semantic index
+ for (const sh::Attribute &attribute : mState.getAttributes())
+ {
+ int d3dSemantic = vertexShader->getSemanticIndex(attribute.name);
+ int regCount = gl::VariableRegisterCount(attribute.type);
+
+ for (int reg = 0; reg < regCount; ++reg)
+ {
+ mAttribLocationToD3DSemantic[attribute.location + reg] = d3dSemantic + reg;
+ }
+ }
+}
+
+void ProgramD3D::updateCachedInputLayout(const gl::State &state)
+{
+ mCachedInputLayout.clear();
+ const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
+
+ for (unsigned int locationIndex : angle::IterateBitSet(mState.getActiveAttribLocationsMask()))
+ {
+ int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
+
+ if (d3dSemantic != -1)
+ {
+ if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1))
+ {
+ mCachedInputLayout.resize(d3dSemantic + 1, gl::VERTEX_FORMAT_INVALID);
+ }
+ mCachedInputLayout[d3dSemantic] =
+ GetVertexFormatType(vertexAttributes[locationIndex],
+ state.getVertexAttribCurrentValue(locationIndex).Type);
+ }
+ }
+}
+
+void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPacking)
+{
+ const auto &builtins = varyingPacking.builtins(SHADER_VERTEX);
+
+ 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.push_back(D3DVarying(builtins.glPosition.semantic,
+ builtins.glPosition.index, 4, outputSlot));
+ }
+ }
+ else if (tfVaryingName == "gl_FragCoord")
+ {
+ if (builtins.glFragCoord.enabled)
+ {
+ mStreamOutVaryings.push_back(D3DVarying(builtins.glFragCoord.semantic,
+ builtins.glFragCoord.index, 4, outputSlot));
+ }
+ }
+ else if (tfVaryingName == "gl_PointSize")
+ {
+ if (builtins.glPointSize.enabled)
+ {
+ mStreamOutVaryings.push_back(D3DVarying("PSIZE", 0, 1, outputSlot));
+ }
+ }
+ else
+ {
+ for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
+ {
+ const auto &varying = *registerInfo.packedVarying->varying;
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ int componentCount = gl::VariableColumnCount(transposedType);
+ ASSERT(!varying.isBuiltIn());
+
+ // Transform feedback for varying structs is underspecified.
+ // See Khronos bug 9856.
+ // TODO(jmadill): Figure out how to be spec-compliant here.
+ if (registerInfo.packedVarying->isStructField() || varying.isStruct())
+ continue;
+
+ // There can be more than one register assigned to a particular varying, and each
+ // register needs its own stream out entry.
+ if (tfVaryingName == varying.name)
+ {
+ mStreamOutVaryings.push_back(D3DVarying(
+ varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot));
+ }
+ }
+ }
+ }
+}
+
+D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
+{
+ return mD3DUniforms[mState.getUniformLocations()[location].index];
+}
+
+bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
+{
+ std::string baseName = blockName;
+ gl::ParseAndStripArrayIndex(&baseName);
+
+ auto sizeIter = mBlockDataSizes.find(baseName);
+ if (sizeIter == mBlockDataSizes.end())
+ {
+ *sizeOut = 0;
+ return false;
+ }
+
+ *sizeOut = sizeIter->second;
+ return true;
+}
+
+bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const
+{
+ auto infoIter = mBlockInfo.find(memberUniformName);
+ if (infoIter == mBlockInfo.end())
+ {
+ *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
+ return false;
+ }
+
+ *memberInfoOut = infoIter->second;
+ return true;
+}
+
+void ProgramD3D::setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ UNREACHABLE();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
new file mode 100755
index 000000000..88fe4020d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -0,0 +1,414 @@
+//
+// Copyright (c) 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/WorkaroundsD3D.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
+
+// Helper struct representing a single shader uniform
+struct D3DUniform : angle::NonCopyable
+{
+ D3DUniform(GLenum typeIn,
+ const std::string &nameIn,
+ unsigned int arraySizeIn,
+ bool defaultBlock);
+ ~D3DUniform();
+
+ bool isSampler() const;
+ unsigned int elementCount() const { return std::max(1u, arraySize); }
+ bool isReferencedByVertexShader() const;
+ bool isReferencedByFragmentShader() const;
+
+ // Duplicated from the GL layer
+ GLenum type;
+ std::string name;
+ unsigned int arraySize;
+
+ // Pointer to a system copy of the data.
+ // TODO(jmadill): remove this in favor of gl::LinkedUniform::data().
+ uint8_t *data;
+
+ // Has the data been updated since the last sync?
+ bool dirty;
+
+ // Register information.
+ unsigned int vsRegisterIndex;
+ unsigned int psRegisterIndex;
+ 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;
+};
+
+struct D3DUniformBlock
+{
+ D3DUniformBlock() : vsRegisterIndex(GL_INVALID_INDEX), psRegisterIndex(GL_INVALID_INDEX) {}
+
+ bool vertexStaticUse() const { return vsRegisterIndex != GL_INVALID_INDEX; }
+
+ bool fragmentStaticUse() const { return psRegisterIndex != GL_INVALID_INDEX; }
+
+ unsigned int vsRegisterIndex;
+ unsigned int psRegisterIndex;
+};
+
+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 ShaderD3D *vertexShader,
+ const ShaderD3D *fragmentShader);
+
+ int getRendererMajorShaderModel() const;
+ bool usesBroadcast(const gl::ContextState &data) const;
+ bool usesFragDepth() const;
+ bool usesPointCoord() const;
+ bool usesFragCoord() const;
+ bool usesPointSize() const;
+ bool usesInsertedPointCoordValue() const;
+ bool usesViewScale() const;
+ bool addsPointCoordToVertexShader() const;
+ bool usesTransformFeedbackGLPosition() const;
+ bool usesSystemValuePointSize() const;
+ bool usesMultipleFragmentOuts() const;
+ GLint getMajorShaderVersion() const;
+ const ShaderD3D *getFragmentShader() const;
+
+ private:
+ const int mRendererMajorShaderModel;
+ const std::string mShaderModelSuffix;
+ const bool mUsesInstancedPointSpriteEmulation;
+ const bool mUsesViewScale;
+ const ShaderD3D *mVertexShader;
+ const ShaderD3D *mFragmentShader;
+};
+
+class ProgramD3D : public ProgramImpl
+{
+ public:
+ ProgramD3D(const gl::ProgramState &data, RendererD3D *renderer);
+ virtual ~ProgramD3D();
+
+ const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; }
+
+ GLint getSamplerMapping(gl::SamplerType type,
+ unsigned int samplerIndex,
+ const gl::Caps &caps) const;
+ GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const;
+ GLuint getUsedSamplerRange(gl::SamplerType type) const;
+ void updateSamplerMapping();
+
+ bool usesPointSize() const { return mUsesPointSize; }
+ bool usesPointSpriteEmulation() const;
+ bool usesGeometryShader(GLenum drawMode) const;
+ bool usesInstancedPointSpriteEmulation() const;
+
+ LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
+ gl::Error save(gl::BinaryOutputStream *stream) override;
+ void setBinaryRetrievableHint(bool retrievable) override;
+
+ gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
+ ShaderExecutableD3D **outExectuable);
+ gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout,
+ ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog);
+ gl::Error getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
+ ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog);
+ gl::Error getGeometryExecutableForPrimitiveType(const gl::ContextState &data,
+ GLenum drawMode,
+ ShaderExecutableD3D **outExecutable,
+ gl::InfoLog *infoLog);
+
+ LinkResult link(const gl::ContextState &data, gl::InfoLog &infoLog) override;
+ GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
+
+ bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
+ bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const override;
+ void setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs) override;
+
+ void initializeUniformStorage();
+ gl::Error applyUniforms(GLenum drawMode);
+ gl::Error applyUniformBuffers(const gl::ContextState &data);
+ void dirtyAllUniforms();
+
+ void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
+ void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
+ void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
+ void setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
+ void setUniform1iv(GLint location, GLsizei count, const GLint *v);
+ void setUniform2iv(GLint location, GLsizei count, const GLint *v);
+ void setUniform3iv(GLint location, GLsizei count, const GLint *v);
+ void setUniform4iv(GLint location, GLsizei count, const GLint *v);
+ void setUniform1uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniform2uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniform3uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniform4uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
+
+ const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; }
+ const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
+
+ unsigned int getSerial() const;
+
+ const AttribIndexArray &getAttribLocationToD3DSemantics() const
+ {
+ return mAttribLocationToD3DSemantic;
+ }
+
+ void updateCachedInputLayout(const gl::State &state);
+ const gl::InputLayout &getCachedInputLayout() const { return mCachedInputLayout; }
+
+ bool isSamplerMappingDirty() { return mDirtySamplerMapping; }
+
+ private:
+ 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;
+ };
+
+ struct Sampler
+ {
+ Sampler();
+
+ bool active;
+ GLint logicalTextureUnit;
+ GLenum textureType;
+ };
+
+ typedef std::map<std::string, D3DUniform *> D3DUniformMap;
+
+ void defineUniformsAndAssignRegisters();
+ void defineUniformBase(const gl::Shader *shader,
+ const sh::Uniform &uniform,
+ D3DUniformMap *uniformMap);
+ void defineUniform(GLenum shaderType,
+ const sh::ShaderVariable &uniform,
+ const std::string &fullName,
+ sh::HLSLBlockEncoder *encoder,
+ D3DUniformMap *uniformMap);
+ void assignAllSamplerRegisters();
+ void assignSamplerRegisters(D3DUniform *d3dUniform);
+
+ static void AssignSamplers(unsigned int startSamplerIndex,
+ GLenum samplerType,
+ unsigned int samplerCount,
+ std::vector<Sampler> &outSamplers,
+ GLuint *outUsedRange);
+
+ template <typename T>
+ void setUniform(GLint location, GLsizei count, const T *v, GLenum targetUniformType);
+
+ template <int cols, int rows>
+ void setUniformMatrixfv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ GLenum targetUniformType);
+
+ LinkResult compileProgramExecutables(const gl::ContextState &data, gl::InfoLog &infoLog);
+
+ void gatherTransformFeedbackVaryings(const VaryingPacking &varyings);
+ D3DUniform *getD3DUniformByName(const std::string &name);
+ D3DUniform *getD3DUniformFromLocation(GLint location);
+
+ void initAttribLocationsToD3DSemantic();
+
+ void reset();
+ void assignUniformBlockRegisters();
+
+ void initUniformBlockInfo();
+ size_t getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock);
+
+ RendererD3D *mRenderer;
+ DynamicHLSL *mDynamicHLSL;
+
+ std::vector<VertexExecutable *> mVertexExecutables;
+ std::vector<PixelExecutable *> mPixelExecutables;
+ std::vector<ShaderExecutableD3D *> mGeometryExecutables;
+
+ std::string mVertexHLSL;
+ D3DCompilerWorkarounds mVertexWorkarounds;
+
+ std::string mPixelHLSL;
+ D3DCompilerWorkarounds mPixelWorkarounds;
+ bool mUsesFragDepth;
+ 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;
+
+ UniformStorageD3D *mVertexUniformStorage;
+ UniformStorageD3D *mFragmentUniformStorage;
+
+ std::vector<Sampler> mSamplersPS;
+ std::vector<Sampler> mSamplersVS;
+ GLuint mUsedVertexSamplerRange;
+ GLuint mUsedPixelSamplerRange;
+ bool mDirtySamplerMapping;
+
+ // Cache for getPixelExecutableForFramebuffer
+ std::vector<GLenum> mPixelShaderOutputFormatCache;
+
+ AttribIndexArray mAttribLocationToD3DSemantic;
+
+ unsigned int mSerial;
+
+ std::vector<GLint> mVertexUBOCache;
+ std::vector<GLint> mFragmentUBOCache;
+ VertexExecutable::Signature mCachedVertexSignature;
+ gl::InputLayout mCachedInputLayout;
+
+ std::vector<D3DVarying> mStreamOutVaryings;
+ std::vector<D3DUniform *> mD3DUniforms;
+ std::vector<D3DUniformBlock> mD3DUniformBlocks;
+
+ std::map<std::string, sh::BlockMemberInfo> mBlockInfo;
+ std::map<std::string, size_t> mBlockDataSizes;
+
+ static unsigned int issueSerial();
+ static unsigned int mCurrentSerial;
+};
+}
+
+#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp
new file mode 100755
index 000000000..84b30aa10
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h
new file mode 100755
index 000000000..c96da5ce1
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h
@@ -0,0 +1,46 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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/angletypes.h"
+#include "libANGLE/FramebufferAttachment.h"
+
+namespace rx
+{
+
+class RenderTargetD3D : public FramebufferAttachmentRenderTarget
+{
+ public:
+ RenderTargetD3D();
+ virtual ~RenderTargetD3D();
+
+ 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()); }
+
+ virtual unsigned int getSerial() const;
+ static unsigned int issueSerials(unsigned int count);
+
+ // Only currently applies to D3D11.
+ virtual void signalDirty() {}
+
+ private:
+ const unsigned int mSerial;
+ static unsigned int mCurrentSerial;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
new file mode 100755
index 000000000..b0bf0f9cd
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 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/Image.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+
+namespace rx
+{
+RenderbufferD3D::RenderbufferD3D(RendererD3D *renderer)
+ : mRenderer(renderer), mRenderTarget(nullptr), mImage(nullptr)
+{
+}
+
+RenderbufferD3D::~RenderbufferD3D()
+{
+ SafeDelete(mRenderTarget);
+ mImage = nullptr;
+}
+
+gl::Error RenderbufferD3D::setStorage(GLenum internalformat, size_t width, size_t height)
+{
+ return setStorageMultisample(0, internalformat, width, height);
+}
+
+gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
+{
+ // 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);
+ if (samples > formatCaps.getMaxSamples())
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Renderbuffer format does not support %u samples, %u is the maximum.",
+ samples, formatCaps.getMaxSamples());
+ }
+
+ RenderTargetD3D *newRT = NULL;
+ ANGLE_TRY(mRenderer->createRenderTarget(static_cast<int>(width), static_cast<int>(height),
+ creationFormat, static_cast<GLsizei>(samples), &newRT));
+
+ SafeDelete(mRenderTarget);
+ mImage = nullptr;
+ mRenderTarget = newRT;
+
+ return gl::NoError();
+}
+
+gl::Error RenderbufferD3D::setStorageEGLImageTarget(egl::Image *image)
+{
+ mImage = GetImplAs<EGLImageD3D>(image);
+ SafeDelete(mRenderTarget);
+
+ return gl::NoError();
+}
+
+gl::Error RenderbufferD3D::getRenderTarget(RenderTargetD3D **outRenderTarget)
+{
+ if (mImage)
+ {
+ return mImage->getRenderTarget(outRenderTarget);
+ }
+ else
+ {
+ *outRenderTarget = mRenderTarget;
+ return gl::NoError();
+ }
+}
+
+gl::Error RenderbufferD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ return getRenderTarget(reinterpret_cast<RenderTargetD3D **>(rtOut));
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h
new file mode 100755
index 000000000..20f6a10b2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h
@@ -0,0 +1,49 @@
+//
+// Copyright (c) 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(RendererD3D *renderer);
+ virtual ~RenderbufferD3D();
+
+ gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override;
+ gl::Error setStorageMultisample(size_t samples,
+ GLenum internalformat,
+ size_t width,
+ size_t height) override;
+ gl::Error setStorageEGLImageTarget(egl::Image *image) override;
+
+ gl::Error getRenderTarget(RenderTargetD3D **outRenderTarget);
+ gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut) override;
+
+ private:
+ RendererD3D *mRenderer;
+ RenderTargetD3D *mRenderTarget;
+ EGLImageD3D *mImage;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
new file mode 100755
index 000000000..e7e22efc5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
@@ -0,0 +1,372 @@
+//
+// Copyright (c) 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/debug.h"
+#include "common/MemoryBuffer.h"
+#include "common/utilities.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.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/ResourceManager.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
+
+namespace rx
+{
+
+RendererD3D::RendererD3D(egl::Display *display)
+ : mDisplay(display),
+ mPresentPathFastEnabled(false),
+ mCapsInitialized(false),
+ mWorkaroundsInitialized(false),
+ mDisjoint(false),
+ mDeviceLost(false)
+{
+}
+
+RendererD3D::~RendererD3D()
+{
+ cleanup();
+}
+
+void RendererD3D::cleanup()
+{
+ for (auto &incompleteTexture : mIncompleteTextures)
+ {
+ incompleteTexture.second.set(nullptr);
+ }
+ mIncompleteTextures.clear();
+}
+
+unsigned int RendererD3D::GetBlendSampleMask(const gl::ContextState &data, int samples)
+{
+ const auto &glState = data.getState();
+ unsigned int mask = 0;
+ if (glState.isSampleCoverageEnabled())
+ {
+ GLclampf 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;
+ }
+
+ return mask;
+}
+
+// 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.
+gl::Error RendererD3D::applyTextures(GLImplFactory *implFactory,
+ const gl::ContextState &data,
+ gl::SamplerType shaderType,
+ const FramebufferTextureArray &framebufferTextures,
+ size_t framebufferTextureCount)
+{
+ const auto &glState = data.getState();
+ const auto &caps = data.getCaps();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+ ASSERT(!programD3D->isSamplerMappingDirty());
+
+ unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType);
+ for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
+ {
+ GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex);
+ GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps);
+ if (textureUnit != -1)
+ {
+ gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
+ ASSERT(texture);
+
+ gl::Sampler *samplerObject = glState.getSampler(textureUnit);
+
+ const gl::SamplerState &samplerState =
+ samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
+
+ // TODO: std::binary_search may become unavailable using older versions of GCC
+ if (texture->getTextureState().isSamplerComplete(samplerState, data) &&
+ !std::binary_search(framebufferTextures.begin(),
+ framebufferTextures.begin() + framebufferTextureCount, texture))
+ {
+ ANGLE_TRY(setSamplerState(shaderType, samplerIndex, texture, samplerState));
+ ANGLE_TRY(setTexture(shaderType, samplerIndex, texture));
+ }
+ else
+ {
+ // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture.
+ gl::Texture *incompleteTexture = getIncompleteTexture(implFactory, textureType);
+
+ ANGLE_TRY(setSamplerState(shaderType, samplerIndex, incompleteTexture,
+ incompleteTexture->getSamplerState()));
+ ANGLE_TRY(setTexture(shaderType, samplerIndex, incompleteTexture));
+ }
+ }
+ else
+ {
+ // No texture bound to this slot even though it is used by the shader, bind a NULL texture
+ ANGLE_TRY(setTexture(shaderType, samplerIndex, nullptr));
+ }
+ }
+
+ // Set all the remaining textures to NULL
+ size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? caps.maxTextureImageUnits
+ : caps.maxVertexTextureImageUnits;
+ clearTextures(shaderType, samplerRange, samplerCount);
+
+ return gl::NoError();
+}
+
+gl::Error RendererD3D::applyTextures(GLImplFactory *implFactory, const gl::ContextState &data)
+{
+ FramebufferTextureArray framebufferTextures;
+ size_t framebufferSerialCount = getBoundFramebufferTextures(data, &framebufferTextures);
+
+ ANGLE_TRY(applyTextures(implFactory, data, gl::SAMPLER_VERTEX, framebufferTextures,
+ framebufferSerialCount));
+ ANGLE_TRY(applyTextures(implFactory, data, gl::SAMPLER_PIXEL, framebufferTextures,
+ framebufferSerialCount));
+ return gl::NoError();
+}
+
+bool RendererD3D::skipDraw(const gl::ContextState &data, GLenum drawMode)
+{
+ const gl::State &state = data.getState();
+
+ if (drawMode == GL_POINTS)
+ {
+ bool usesPointSize = GetImplAs<ProgramD3D>(state.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 && !state.isTransformFeedbackActiveUnpaused())
+ {
+ // This is stictly speaking not an error, but developers should be
+ // notified of risking undefined behavior.
+ ERR("Point rendering without writing to gl_PointSize.");
+
+ return true;
+ }
+ }
+ else if (gl::IsTriangleMode(drawMode))
+ {
+ if (state.getRasterizerState().cullFace &&
+ state.getRasterizerState().cullMode == GL_FRONT_AND_BACK)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+gl::Error RendererD3D::markTransformFeedbackUsage(const gl::ContextState &data)
+{
+ const gl::TransformFeedback *transformFeedback = data.getState().getCurrentTransformFeedback();
+ for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
+ {
+ const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
+ if (binding.get() != nullptr)
+ {
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get());
+ ANGLE_TRY(bufferD3D->markTransformFeedbackUsage());
+ }
+ }
+
+ return gl::NoError();
+}
+
+size_t RendererD3D::getBoundFramebufferTextures(const gl::ContextState &data,
+ FramebufferTextureArray *outTextureArray)
+{
+ size_t textureCount = 0;
+
+ const gl::Framebuffer *drawFramebuffer = data.getState().getDrawFramebuffer();
+ for (size_t i = 0; i < drawFramebuffer->getNumColorBuffers(); i++)
+ {
+ const gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i);
+ if (attachment && attachment->type() == GL_TEXTURE)
+ {
+ (*outTextureArray)[textureCount++] = attachment->getTexture();
+ }
+ }
+
+ const gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer();
+ if (depthStencilAttachment && depthStencilAttachment->type() == GL_TEXTURE)
+ {
+ (*outTextureArray)[textureCount++] = depthStencilAttachment->getTexture();
+ }
+
+ std::sort(outTextureArray->begin(), outTextureArray->begin() + textureCount);
+
+ return textureCount;
+}
+
+gl::Texture *RendererD3D::getIncompleteTexture(GLImplFactory *implFactory, GLenum type)
+{
+ if (mIncompleteTextures.find(type) == mIncompleteTextures.end())
+ {
+ const GLubyte color[] = { 0, 0, 0, 255 };
+ const gl::Extents colorSize(1, 1, 1);
+ const gl::PixelUnpackState unpack(1, 0);
+ const gl::Box area(0, 0, 0, 1, 1, 1);
+
+ // If a texture is external use a 2D texture for the incomplete texture
+ GLenum createType = (type == GL_TEXTURE_EXTERNAL_OES) ? GL_TEXTURE_2D : type;
+
+ // Skip the API layer to avoid needing to pass the Context and mess with dirty bits.
+ gl::Texture *t =
+ new gl::Texture(implFactory, std::numeric_limits<GLuint>::max(), createType);
+ t->setStorage(createType, 1, GL_RGBA8, colorSize);
+ if (type == GL_TEXTURE_CUBE_MAP)
+ {
+ for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++)
+ {
+ t->getImplementation()->setSubImage(face, 0, area, GL_RGBA8, GL_UNSIGNED_BYTE,
+ unpack, color);
+ }
+ }
+ else
+ {
+ t->getImplementation()->setSubImage(createType, 0, area, GL_RGBA8, GL_UNSIGNED_BYTE, unpack,
+ color);
+ }
+ mIncompleteTextures[type].set(t);
+ }
+
+ return mIncompleteTextures[type].get();
+}
+
+GLenum RendererD3D::getResetStatus()
+{
+ if (!mDeviceLost)
+ {
+ if (testDeviceLost())
+ {
+ mDeviceLost = true;
+ notifyDeviceLost();
+ return GL_UNKNOWN_CONTEXT_RESET_EXT;
+ }
+ return GL_NO_ERROR;
+ }
+
+ if (testDeviceResettable())
+ {
+ return GL_NO_ERROR;
+ }
+
+ return GL_UNKNOWN_CONTEXT_RESET_EXT;
+}
+
+void RendererD3D::notifyDeviceLost()
+{
+ mDisplay->notifyDeviceLost();
+}
+
+std::string RendererD3D::getVendorString() const
+{
+ LUID adapterLuid = { 0 };
+
+ if (getLUID(&adapterLuid))
+ {
+ char adapterLuidString[64];
+ sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
+ return std::string(adapterLuidString);
+ }
+
+ return std::string("");
+}
+
+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;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.h
new file mode 100755
index 000000000..b63aba8a9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -0,0 +1,317 @@
+
+// Copyright (c) 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 "common/debug.h"
+#include "common/MemoryBuffer.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/Device.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+#include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
+#include "libANGLE/Version.h"
+
+//FIXME(jmadill): std::array is currently prohibited by Chromium style guide
+#include <array>
+
+namespace egl
+{
+class ConfigSet;
+}
+
+namespace gl
+{
+class FramebufferState;
+class InfoLog;
+class Texture;
+struct LinkedVarying;
+}
+
+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;
+
+enum ShaderType
+{
+ SHADER_VERTEX,
+ SHADER_PIXEL,
+ SHADER_GEOMETRY,
+ SHADER_TYPE_MAX
+};
+
+struct DeviceIdentifier
+{
+ UINT VendorId;
+ UINT DeviceId;
+ UINT SubSysId;
+ UINT Revision;
+ UINT FeatureLevel;
+};
+
+enum RendererClass
+{
+ RENDERER_D3D11,
+ RENDERER_D3D9
+};
+
+// 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(gl::VertexFormatType vertexFormatType) const = 0;
+ virtual GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const = 0;
+ virtual gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(
+ const gl::VertexAttribute &attrib,
+ GLsizei count,
+ GLsizei instances) const = 0;
+};
+
+using AttribIndexArray = std::array<int, gl::MAX_VERTEX_ATTRIBS>;
+
+class RendererD3D : public BufferFactoryD3D
+{
+ public:
+ explicit RendererD3D(egl::Display *display);
+ virtual ~RendererD3D();
+
+ virtual egl::Error initialize() = 0;
+
+ virtual egl::ConfigSet generateConfigs() = 0;
+ virtual void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const = 0;
+
+ virtual ContextImpl *createContext(const gl::ContextState &state) = 0;
+
+ std::string getVendorString() const;
+
+ 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) = 0;
+ virtual egl::Error getD3DTextureInfo(IUnknown *d3dTexture,
+ EGLint *width,
+ EGLint *height,
+ GLenum *fboFormat) const = 0;
+ virtual egl::Error validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const = 0;
+
+ virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0;
+ virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0;
+
+ virtual gl::Error setUniformBuffers(const gl::ContextState &data,
+ const std::vector<GLint> &vertexUniformBuffers,
+ const std::vector<GLint> &fragmentUniformBuffers) = 0;
+
+ virtual gl::Error applyUniforms(const ProgramD3D &programD3D,
+ GLenum drawMode,
+ const std::vector<D3DUniform *> &uniformArray) = 0;
+
+ virtual unsigned int getReservedVertexUniformBuffers() const = 0;
+ virtual unsigned int getReservedFragmentUniformBuffers() const = 0;
+
+ virtual int getMajorShaderModel() const = 0;
+
+ const WorkaroundsD3D &getWorkarounds() const;
+
+ // Pixel operations
+ virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0;
+ virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) = 0;
+ virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0;
+ virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0;
+
+ virtual gl::Error copyTexture(const gl::Texture *source,
+ GLint sourceLevel,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) = 0;
+ virtual gl::Error copyCompressedTexture(const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel) = 0;
+
+ // RenderTarget creation
+ virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) = 0;
+ virtual gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) = 0;
+
+ // Shader operations
+ virtual gl::Error loadExecutable(const void *function,
+ size_t length,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable) = 0;
+ virtual gl::Error compileToExecutable(gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const D3DCompilerWorkarounds &workarounds,
+ ShaderExecutableD3D **outExectuable) = 0;
+ virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0;
+
+ // Image operations
+ virtual ImageD3D *createImage() = 0;
+ virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0;
+ virtual gl::Error generateMipmapUsingD3D(TextureStorage *storage,
+ const gl::TextureState &textureState) = 0;
+ virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 0;
+ virtual TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D) = 0;
+ virtual TextureStorage *createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) = 0;
+ virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) = 0;
+ virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) = 0;
+ virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
+ virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
+
+ // Buffer-to-texture and Texture-to-buffer copies
+ virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0;
+ virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0;
+
+ // Device lost
+ GLenum 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();
+
+ // In D3D11, faster than calling setTexture a jillion times
+ virtual gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) = 0;
+
+ virtual egl::Error getEGLDevice(DeviceImpl **device) = 0;
+
+ bool presentPathFastEnabled() const { return mPresentPathFastEnabled; }
+
+ // Stream creation
+ virtual StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ 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;
+
+ // Necessary hack for default framebuffers in D3D.
+ virtual FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) = 0;
+
+ virtual gl::Version getMaxSupportedESVersion() 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;
+
+ void cleanup();
+
+ static unsigned int GetBlendSampleMask(const gl::ContextState &data, int samples);
+ // dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state.
+
+ gl::Error applyTextures(GLImplFactory *implFactory, const gl::ContextState &data);
+ bool skipDraw(const gl::ContextState &data, GLenum drawMode);
+ gl::Error markTransformFeedbackUsage(const gl::ContextState &data);
+
+ egl::Display *mDisplay;
+
+ bool mPresentPathFastEnabled;
+
+ private:
+ void ensureCapsInitialized() const;
+
+ typedef std::array<gl::Texture*, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureArray;
+
+ gl::Error applyTextures(GLImplFactory *implFactory,
+ const gl::ContextState &data,
+ gl::SamplerType shaderType,
+ const FramebufferTextureArray &framebufferTextures,
+ size_t framebufferTextureCount);
+
+ size_t getBoundFramebufferTextures(const gl::ContextState &data,
+ FramebufferTextureArray *outTextureArray);
+ gl::Texture *getIncompleteTexture(GLImplFactory *implFactory, GLenum type);
+
+ virtual WorkaroundsD3D generateWorkarounds() const = 0;
+
+ mutable bool mCapsInitialized;
+ mutable gl::Caps mNativeCaps;
+ mutable gl::TextureCapsMap mNativeTextureCaps;
+ mutable gl::Extensions mNativeExtensions;
+ mutable gl::Limitations mNativeLimitations;
+
+ gl::TextureMap mIncompleteTextures;
+
+ mutable bool mWorkaroundsInitialized;
+ mutable WorkaroundsD3D mWorkarounds;
+
+ bool mDisjoint;
+ bool mDeviceLost;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/SamplerD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/SamplerD3D.h
new file mode 100755
index 000000000..7aabdc813
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/SamplerD3D.h
@@ -0,0 +1,25 @@
+//
+// 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() {}
+ ~SamplerD3D() override {}
+};
+}
+
+#endif // LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
new file mode 100755
index 000000000..fd7b13abb
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
@@ -0,0 +1,227 @@
+//
+// Copyright (c) 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/utilities.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+
+// Definitions local to the translation unit
+namespace
+{
+
+const char *GetShaderTypeString(GLenum type)
+{
+ switch (type)
+ {
+ case GL_VERTEX_SHADER:
+ return "VERTEX";
+
+ case GL_FRAGMENT_SHADER:
+ return "FRAGMENT";
+
+ default:
+ UNREACHABLE();
+ return "";
+ }
+}
+
+} // anonymous namespace
+
+namespace rx
+{
+
+ShaderD3D::ShaderD3D(const gl::ShaderState &data, const WorkaroundsD3D &workarounds)
+ : ShaderImpl(data), mAdditionalOptions(0)
+{
+ uncompile();
+
+ if (workarounds.expandIntegerPowExpressions)
+ {
+ mAdditionalOptions |= SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS;
+ }
+
+ if (workarounds.getDimensionsIgnoresBaseLevel)
+ {
+ mAdditionalOptions |= SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL;
+ }
+
+ if (workarounds.preAddTexelFetchOffsets)
+ {
+ mAdditionalOptions |= SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH;
+ }
+ if (workarounds.rewriteUnaryMinusOperator)
+ {
+ mAdditionalOptions |= SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR;
+ }
+ if (workarounds.emulateIsnanFloat)
+ {
+ mAdditionalOptions |= SH_EMULATE_ISNAN_FLOAT_FUNCTION;
+ }
+}
+
+ShaderD3D::~ShaderD3D()
+{
+}
+
+std::string ShaderD3D::getDebugInfo() const
+{
+ return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mData.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;
+ mUsesFragCoord = false;
+ mUsesFrontFacing = false;
+ mUsesPointSize = false;
+ mUsesPointCoord = false;
+ mUsesDepthRange = false;
+ mUsesFragDepth = false;
+ mUsesDiscardRewriting = false;
+ mUsesNestedBreak = false;
+ mRequiresIEEEStrictCompiling = false;
+
+ mDebugInfo.clear();
+}
+
+void ShaderD3D::generateWorkarounds(D3DCompilerWorkarounds *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::getInterfaceBlockRegister(const std::string &blockName) const
+{
+ ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0);
+ return mInterfaceBlockRegisterMap.find(blockName)->second;
+}
+
+ShShaderOutput ShaderD3D::getCompilerOutputType() const
+{
+ return mCompilerOutputType;
+}
+
+ShCompileOptions ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream,
+ std::string *sourcePath)
+{
+ uncompile();
+
+ ShCompileOptions additionalOptions = 0;
+
+ const std::string &source = mData.getSource();
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ if (gl::DebugAnnotationsActive())
+ {
+ *sourcePath = getTempPath();
+ writeFile(sourcePath->c_str(), source.c_str(), source.length());
+ additionalOptions |= SH_LINE_DIRECTIVES | SH_SOURCE_PATH;
+ }
+#endif
+
+ additionalOptions |= mAdditionalOptions;
+
+ *shaderSourceStream << source;
+ return additionalOptions;
+}
+
+bool ShaderD3D::hasUniform(const D3DUniform *d3dUniform) const
+{
+ return mUniformRegisterMap.find(d3dUniform->name) != mUniformRegisterMap.end();
+}
+
+const std::map<std::string, unsigned int> &GetUniformRegisterMap(
+ const std::map<std::string, unsigned int> *uniformRegisterMap)
+{
+ ASSERT(uniformRegisterMap);
+ return *uniformRegisterMap;
+}
+
+bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
+{
+ // TODO(jmadill): We shouldn't need to cache this.
+ mCompilerOutputType = compiler->getShaderOutputType();
+
+ const std::string &translatedSource = mData.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;
+ mUsesFragCoord = translatedSource.find("GL_USES_FRAG_COORD") != std::string::npos;
+ mUsesFrontFacing = translatedSource.find("GL_USES_FRONT_FACING") != 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;
+ 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->getCompilerHandle(mData.getShaderType());
+
+ mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle));
+
+ for (const sh::InterfaceBlock &interfaceBlock : mData.getInterfaceBlocks())
+ {
+ if (interfaceBlock.staticUse)
+ {
+ unsigned int index = static_cast<unsigned int>(-1);
+ bool blockRegisterResult =
+ sh::GetInterfaceBlockRegister(compilerHandle, interfaceBlock.name, &index);
+ ASSERT(blockRegisterResult);
+
+ mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
+ }
+ }
+
+ mDebugInfo +=
+ std::string("// ") + GetShaderTypeString(mData.getShaderType()) + " SHADER BEGIN\n";
+ mDebugInfo += "\n// GLSL BEGIN\n\n" + mData.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;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.h
new file mode 100755
index 000000000..587c12173
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ShaderD3D.h
@@ -0,0 +1,84 @@
+//
+// Copyright (c) 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 rx
+{
+class DynamicHLSL;
+class RendererD3D;
+struct D3DCompilerWorkarounds;
+struct D3DUniform;
+struct WorkaroundsD3D;
+
+class ShaderD3D : public ShaderImpl
+{
+ public:
+ ShaderD3D(const gl::ShaderState &data, const WorkaroundsD3D &workarounds);
+ virtual ~ShaderD3D();
+
+ // ShaderImpl implementation
+ ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string *sourcePath) override;
+ bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override;
+ std::string getDebugInfo() const override;
+
+ // D3D-specific methods
+ void uncompile();
+
+ bool hasUniform(const D3DUniform *d3dUniform) 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 getInterfaceBlockRegister(const std::string &blockName) const;
+ void appendDebugInfo(const std::string &info) const { mDebugInfo += info; }
+
+ void generateWorkarounds(D3DCompilerWorkarounds *workarounds) const;
+
+ bool usesMultipleRenderTargets() const { return mUsesMultipleRenderTargets; }
+ bool usesFragColor() const { return mUsesFragColor; }
+ bool usesFragData() const { return mUsesFragData; }
+ bool usesFragCoord() const { return mUsesFragCoord; }
+ bool usesFrontFacing() const { return mUsesFrontFacing; }
+ bool usesPointSize() const { return mUsesPointSize; }
+ bool usesPointCoord() const { return mUsesPointCoord; }
+ bool usesDepthRange() const { return mUsesDepthRange; }
+ bool usesFragDepth() const { return mUsesFragDepth; }
+
+ ShShaderOutput getCompilerOutputType() const;
+
+ private:
+ bool mUsesMultipleRenderTargets;
+ bool mUsesFragColor;
+ bool mUsesFragData;
+ bool mUsesFragCoord;
+ bool mUsesFrontFacing;
+ bool mUsesPointSize;
+ bool mUsesPointCoord;
+ bool mUsesDepthRange;
+ bool mUsesFragDepth;
+ bool mUsesDiscardRewriting;
+ bool mUsesNestedBreak;
+ bool mRequiresIEEEStrictCompiling;
+
+ ShShaderOutput mCompilerOutputType;
+ mutable std::string mDebugInfo;
+ std::map<std::string, unsigned int> mUniformRegisterMap;
+ std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
+ ShCompileOptions mAdditionalOptions;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp
new file mode 100755
index 000000000..97ffdf509
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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) : mSize(initialSize)
+{
+}
+
+UniformStorageD3D::~UniformStorageD3D()
+{
+}
+
+size_t UniformStorageD3D::size() const
+{
+ return mSize;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h
new file mode 100755
index 000000000..71b83b795
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h
@@ -0,0 +1,54 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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/debug.h"
+
+#include <vector>
+#include <cstdint>
+
+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;
+
+ private:
+ size_t mSize;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
new file mode 100755
index 000000000..8696ab0d7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
@@ -0,0 +1,402 @@
+//
+// Copyright (c) 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/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+
+#include <tchar.h>
+#include <EGL/eglext.h>
+#include <algorithm>
+
+namespace rx
+{
+
+SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ const egl::Config *config,
+ 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),
+ mOrientation(static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0))),
+ mRenderTargetFormat(config->renderTargetFormat),
+ mDepthStencilFormat(config->depthStencilFormat),
+ mSwapChain(nullptr),
+ mSwapIntervalDirty(true),
+ mNativeWindow(renderer->createNativeWindow(window, 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)
+{
+ if (window != nullptr && !mFixedSize)
+ {
+ mWidth = -1;
+ mHeight = -1;
+ }
+
+ 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();
+ mRenderer->getD3DTextureInfo(mD3DTexture, &mWidth, &mHeight, &mRenderTargetFormat);
+ mDepthStencilFormat = GL_NONE;
+ break;
+
+ default:
+ break;
+ }
+}
+
+SurfaceD3D::~SurfaceD3D()
+{
+ releaseSwapChain();
+ SafeDelete(mNativeWindow);
+ SafeRelease(mD3DTexture);
+}
+
+void SurfaceD3D::releaseSwapChain()
+{
+ SafeDelete(mSwapChain);
+}
+
+egl::Error SurfaceD3D::initialize()
+{
+ if (mNativeWindow->getNativeWindow())
+ {
+ if (!mNativeWindow->initialize())
+ {
+ return egl::Error(EGL_BAD_SURFACE);
+ }
+ }
+
+ egl::Error error = resetSwapChain();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::FramebufferState &data)
+{
+ return mRenderer->createDefaultFramebuffer(data);
+}
+
+egl::Error SurfaceD3D::bindTexImage(gl::Texture *, EGLint)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::releaseTexImage(EGLint)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::resetSwapChain()
+{
+ ASSERT(!mSwapChain);
+
+ int width;
+ int height;
+
+ if (!mFixedSize)
+ {
+ RECT windowRect;
+ if (!mNativeWindow->getClientRect(&windowRect))
+ {
+ ASSERT(false);
+
+ return egl::Error(EGL_BAD_SURFACE, "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 = mWidth;
+ height = mHeight;
+ }
+
+ mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mD3DTexture,
+ mRenderTargetFormat, mDepthStencilFormat, mOrientation);
+ if (!mSwapChain)
+ {
+ return egl::Error(EGL_BAD_ALLOC);
+ }
+
+ egl::Error error = resetSwapChain(width, height);
+ if (error.isError())
+ {
+ SafeDelete(mSwapChain);
+ return error;
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight)
+{
+ ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
+ ASSERT(mSwapChain);
+
+ EGLint status = mSwapChain->resize(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::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::resetSwapChain(int backbufferWidth, int backbufferHeight)
+{
+ ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
+ ASSERT(mSwapChain);
+
+ EGLint status = mSwapChain->reset(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::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ if (!mSwapChain)
+ {
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ if (x + width > mWidth)
+ {
+ width = mWidth - x;
+ }
+
+ if (y + height > mHeight)
+ {
+ height = mHeight - y;
+ }
+
+ if (width != 0 && height != 0)
+ {
+ EGLint status = mSwapChain->swapRect(x, y, width, height);
+
+ if (status == EGL_CONTEXT_LOST)
+ {
+ mRenderer->notifyDeviceLost();
+ return egl::Error(status);
+ }
+ else if (status != EGL_SUCCESS)
+ {
+ return egl::Error(status);
+ }
+ }
+
+ checkForOutOfDateSwapChain();
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+bool SurfaceD3D::checkForOutOfDateSwapChain()
+{
+ 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))
+ {
+ ASSERT(false);
+ return false;
+ }
+
+ // 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();
+ }
+
+ bool wasDirty = (mSwapIntervalDirty || sizeDirty);
+
+ if (mSwapIntervalDirty)
+ {
+ resetSwapChain(clientWidth, clientHeight);
+ }
+ else if (sizeDirty)
+ {
+ resizeSwapChain(clientWidth, clientHeight);
+ }
+
+ return wasDirty;
+}
+
+egl::Error SurfaceD3D::swap()
+{
+ return swapRect(0, 0, mWidth, mHeight);
+}
+
+egl::Error SurfaceD3D::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ return swapRect(x, y, width, height);
+}
+
+rx::SwapChainD3D *SurfaceD3D::getSwapChain() const
+{
+ return mSwapChain;
+}
+
+void SurfaceD3D::setSwapInterval(EGLint interval)
+{
+ if (mSwapInterval == interval)
+ {
+ return;
+ }
+
+ mSwapInterval = interval;
+ mSwapIntervalDirty = true;
+}
+
+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::Error(EGL_SUCCESS);
+}
+
+gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ if (target.binding() == GL_BACK)
+ {
+ *rtOut = mSwapChain->getColorRenderTarget();
+ }
+ else
+ {
+ *rtOut = mSwapChain->getDepthStencilRenderTarget();
+ }
+ return gl::Error(GL_NO_ERROR);
+}
+
+WindowSurfaceD3D::WindowSurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ const egl::Config *config,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+ : SurfaceD3D(state,
+ renderer,
+ display,
+ config,
+ window,
+ 0,
+ static_cast<EGLClientBuffer>(0),
+ attribs)
+{
+}
+
+WindowSurfaceD3D::~WindowSurfaceD3D()
+{
+}
+
+PbufferSurfaceD3D::PbufferSurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ const egl::Config *config,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+ : SurfaceD3D(state,
+ renderer,
+ display,
+ config,
+ static_cast<EGLNativeWindowType>(0),
+ buftype,
+ clientBuffer,
+ attribs)
+{
+}
+
+PbufferSurfaceD3D::~PbufferSurfaceD3D()
+{
+}
+
+} // namespace rc
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
new file mode 100755
index 000000000..768c60bd0
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
@@ -0,0 +1,121 @@
+//
+// Copyright (c) 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 SwapChainD3D;
+class RendererD3D;
+
+class SurfaceD3D : public SurfaceImpl
+{
+ public:
+ ~SurfaceD3D() override;
+ void releaseSwapChain();
+
+ egl::Error initialize() override;
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) 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();
+
+ // Returns true if swapchain changed due to resize or interval update
+ bool checkForOutOfDateSwapChain();
+
+ gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut) override;
+
+ protected:
+ SurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ const egl::Config *config,
+ EGLNativeWindowType window,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs);
+
+ egl::Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
+ egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight);
+ egl::Error resizeSwapChain(int backbufferWidth, int backbufferHeight);
+
+ RendererD3D *mRenderer;
+ egl::Display *mDisplay;
+
+ bool mFixedSize;
+ GLint mOrientation;
+
+ GLenum mRenderTargetFormat;
+ GLenum mDepthStencilFormat;
+
+ 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;
+};
+
+class WindowSurfaceD3D : public SurfaceD3D
+{
+ public:
+ WindowSurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ const egl::Config *config,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs);
+ ~WindowSurfaceD3D() override;
+};
+
+class PbufferSurfaceD3D : public SurfaceD3D
+{
+ public:
+ PbufferSurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ const egl::Config *config,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs);
+ ~PbufferSurfaceD3D() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_SURFACED3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp
new file mode 100644
index 000000000..de8534c3d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 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/src/libANGLE/renderer/d3d/SwapChainD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
new file mode 100755
index 000000000..f49204527
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 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 <GLES2/gl2.h>
+#include <EGL/egl.h>
+
+#include "common/angleutils.h"
+#include "common/platform.h"
+
+#if !defined(ANGLE_FORCE_VSYNC_OFF)
+#define ANGLE_FORCE_VSYNC_OFF 0
+#endif
+
+namespace rx
+{
+class RenderTargetD3D;
+
+class SwapChainD3D : angle::NonCopyable
+{
+ public:
+ SwapChainD3D(HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat);
+ virtual ~SwapChainD3D();
+
+ virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0;
+ virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0;
+ virtual EGLint swapRect(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;
+
+ protected:
+ const GLenum mOffscreenRenderTargetFormat;
+ const GLenum mDepthBufferFormat;
+
+ HANDLE mShareHandle;
+ IUnknown *mD3DTexture;
+};
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp b/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
new file mode 100755
index 000000000..287700264
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -0,0 +1,3086 @@
+//
+// 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/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/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+
+namespace rx
+{
+
+namespace
+{
+
+gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const uint8_t *pixels,
+ ptrdiff_t layerOffset, const uint8_t **pointerOut)
+{
+ if (unpack.pixelBuffer.id() != 0)
+ {
+ // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported
+ gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
+ 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>(pixelBuffer);
+ ASSERT(bufferD3D);
+ const uint8_t *bufferData = NULL;
+ ANGLE_TRY(bufferD3D->getData(&bufferData));
+ *pointerOut = bufferData + offset;
+ }
+ else
+ {
+ *pointerOut = pixels;
+ }
+
+ // Offset the pointer for 2D array layer (if it's valid)
+ if (*pointerOut != nullptr)
+ {
+ *pointerOut += layerOffset;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+bool IsRenderTargetUsage(GLenum usage)
+{
+ return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+}
+
+}
+
+TextureD3D::TextureD3D(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureImpl(state),
+ mRenderer(renderer),
+ mDirtyImages(true),
+ mImmutable(false),
+ mTexStorage(nullptr),
+ mBaseLevel(0)
+{
+}
+
+TextureD3D::~TextureD3D()
+{
+}
+
+gl::Error TextureD3D::getNativeTexture(TextureStorage **outStorage)
+{
+ // ensure the underlying texture is created
+ ANGLE_TRY(initializeStorage(false));
+
+ if (mTexStorage)
+ {
+ ANGLE_TRY(updateStorage());
+ }
+
+ ASSERT(outStorage);
+
+ *outStorage = mTexStorage;
+ return gl::NoError();
+}
+
+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);
+}
+
+bool TextureD3D::shouldUseSetData(const ImageD3D *image) const
+{
+ if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload)
+ {
+ return false;
+ }
+
+ gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(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);
+}
+
+gl::Error TextureD3D::setImageImpl(const gl::ImageIndex &index,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ 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 gl::Error(GL_NO_ERROR);
+ }
+
+ // 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 = NULL;
+ ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData));
+
+ if (pixelData != nullptr)
+ {
+ if (shouldUseSetData(image))
+ {
+ ANGLE_TRY(mTexStorage->setData(index, image, NULL, type, unpack, pixelData));
+ }
+ else
+ {
+ gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
+ ANGLE_TRY(image->loadData(fullImageArea, unpack, type, pixelData, index.is3D()));
+ }
+
+ mDirtyImages = true;
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D::subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset)
+{
+ // CPU readback & copy where direct GPU copy is not supported
+ const uint8_t *pixelData = NULL;
+ ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData));
+
+ if (pixelData != NULL)
+ {
+ ImageD3D *image = getImage(index);
+ ASSERT(image);
+
+ if (shouldUseSetData(image))
+ {
+ return mTexStorage->setData(index, image, &area, type, unpack, pixelData);
+ }
+
+ ANGLE_TRY(image->loadData(area, unpack, type, pixelData, index.is3D()));
+ ANGLE_TRY(commitRegion(index, area));
+ mDirtyImages = true;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D::setCompressedImageImpl(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 gl::NoError();
+ }
+
+ // 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 = NULL;
+ ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData));
+
+ if (pixelData != NULL)
+ {
+ gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
+ ANGLE_TRY(image->loadCompressedData(fullImageArea, pixelData));
+
+ mDirtyImages = true;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D::subImageCompressed(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 = NULL;
+ ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData));
+
+ if (pixelData != NULL)
+ {
+ ImageD3D *image = getImage(index);
+ ASSERT(image);
+
+ ANGLE_TRY(image->loadCompressedData(area, pixelData));
+
+ mDirtyImages = true;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat)
+{
+ return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
+}
+
+gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea,
+ GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget)
+{
+ if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 ||
+ unpack.skipImages != 0)
+ {
+ // TODO(jmadill): additional unpack parameters
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION,
+ "Unimplemented pixel store parameters in fastUnpackPixels");
+ }
+
+ // No-op
+ if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ // 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(unpack, static_cast<unsigned int>(offset),
+ destRenderTarget, sizedInternalFormat, type,
+ destArea));
+
+ return gl::NoError();
+}
+
+GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
+{
+ if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) ||
+ mRenderer->getNativeExtensions().textureNPOT)
+ {
+ // 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));
+}
+
+gl::Error TextureD3D::setImageExternal(GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
+{
+ // Only external images can accept external textures
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D::generateMipmap()
+{
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+ ASSERT(maxLevel > baseLevel); // Should be checked before calling this.
+
+ if (mTexStorage && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ // Switch to using the mipmapped texture.
+ TextureStorage *textureStorage = NULL;
+ ANGLE_TRY(getNativeTexture(&textureStorage));
+ ANGLE_TRY(textureStorage->useLevelZeroWorkaroundTexture(false));
+ }
+
+ // Set up proper mipmap chain in our Image array.
+ initMipmapImages();
+
+ if (mTexStorage && mTexStorage->supportsNativeMipmapFunction())
+ {
+ ANGLE_TRY(updateStorage());
+
+ // Generate the mipmap chain using the ad-hoc DirectX function.
+ ANGLE_TRY(mRenderer->generateMipmapUsingD3D(mTexStorage, mState));
+ }
+ else
+ {
+ // Generate the mipmap chain, one level at a time.
+ ANGLE_TRY(generateMipmapUsingImages(maxLevel));
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D::generateMipmapUsingImages(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));
+
+ // 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 (mRenderer->getWorkarounds().setDataFasterThanImageUpload && mTexStorage)
+ {
+ 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(srcIndex, mTexStorage));
+ }
+ }
+ else
+ {
+ ANGLE_TRY(updateStorage());
+ }
+ }
+
+ // 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->getWorkarounds().zeroMaxLodWorkaround));
+
+ 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(sourceIndex, destIndex));
+ }
+ else
+ {
+ // CPU-side mipmapping
+ ANGLE_TRY(mRenderer->generateMipmap(getImage(destIndex), getImage(sourceIndex)));
+ }
+ }
+ }
+
+ if (mTexStorage)
+ {
+ updateStorage();
+ }
+
+ return gl::NoError();
+}
+
+bool TextureD3D::isBaseImageZeroSize() const
+{
+ ImageD3D *baseImage = getBaseLevelImage();
+
+ if (!baseImage || baseImage->getWidth() <= 0)
+ {
+ return true;
+ }
+
+ if (!gl::IsCubeMapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0)
+ {
+ return true;
+ }
+
+ if (baseImage->getTarget() == GL_TEXTURE_3D && baseImage->getDepth() <= 0)
+ {
+ return true;
+ }
+
+ if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(getBaseLevel()) <= 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+gl::Error TextureD3D::ensureRenderTarget()
+{
+ ANGLE_TRY(initializeStorage(true));
+
+ if (!isBaseImageZeroSize())
+ {
+ ASSERT(mTexStorage);
+ if (!mTexStorage->isRenderTarget())
+ {
+ TextureStorage *newRenderTargetStorage = NULL;
+ ANGLE_TRY(createCompleteStorage(true, &newRenderTargetStorage));
+
+ gl::Error error = mTexStorage->copyToStorage(newRenderTargetStorage);
+ if (error.isError())
+ {
+ SafeDelete(newRenderTargetStorage);
+ return error;
+ }
+
+ error = setCompleteTexStorage(newRenderTargetStorage);
+ if (error.isError())
+ {
+ SafeDelete(newRenderTargetStorage);
+ return error;
+ }
+ }
+ }
+
+ return gl::NoError();
+}
+
+bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const
+{
+ ImageD3D *image = getImage(index);
+ bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0)));
+ return (image->isRenderableFormat() && levelsComplete);
+}
+
+gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box &region)
+{
+ if (mTexStorage)
+ {
+ ASSERT(isValidIndex(index));
+ ImageD3D *image = getImage(index);
+ ANGLE_TRY(image->copyToStorage(mTexStorage, index, region));
+ image->markClean();
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ RenderTargetD3D *rtD3D = nullptr;
+ gl::Error error = getRenderTarget(target.textureIndex(), &rtD3D);
+ *rtOut = static_cast<FramebufferAttachmentRenderTarget *>(rtD3D);
+ return error;
+}
+
+void TextureD3D::setBaseLevel(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();
+ SafeDelete(mTexStorage);
+ }
+}
+
+void TextureD3D::syncState(const gl::Texture::DirtyBits &dirtyBits)
+{
+ // TODO(geofflang): Use dirty bits
+}
+
+TextureD3D_2D::TextureD3D_2D(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3D(state, renderer)
+{
+ mEGLImageTarget = false;
+ for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+ {
+ mImageArray[i] = renderer->createImage();
+ }
+}
+
+TextureD3D_2D::~TextureD3D_2D()
+{
+ // 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 (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+ {
+ delete mImageArray[i];
+ }
+
+ SafeDelete(mTexStorage);
+}
+
+ImageD3D *TextureD3D_2D::getImage(int level, int layer) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(layer == 0);
+ return mImageArray[level];
+}
+
+ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const
+{
+ ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(!index.hasLayer());
+ ASSERT(index.type == GL_TEXTURE_2D);
+ return mImageArray[index.mipIndex];
+}
+
+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::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+}
+
+gl::Error TextureD3D_2D::setImage(GLenum target,
+ size_t imageLevel,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D && size.depth == 1);
+
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+
+ bool fastUnpacked = false;
+ GLint level = static_cast<GLint>(imageLevel);
+
+ redefineImage(level, sizedInternalFormat, size, false);
+
+ gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+
+ // Attempt a fast gpu copy of the pixel data to the surface
+ if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level))
+ {
+ // Will try to create RT storage if it does not exist
+ RenderTargetD3D *destRenderTarget = NULL;
+ ANGLE_TRY(getRenderTarget(index, &destRenderTarget));
+
+ gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
+
+ ANGLE_TRY(fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type,
+ destRenderTarget));
+
+ // Ensure we don't overwrite our newly initialized data
+ mImageArray[level]->markClean();
+
+ fastUnpacked = true;
+ }
+
+ if (!fastUnpacked)
+ {
+ ANGLE_TRY(setImageImpl(index, type, unpack, pixels, 0));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::setSubImage(GLenum target,
+ size_t imageLevel,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);
+
+ GLint level = static_cast<GLint>(imageLevel);
+ gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+ if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
+ {
+ RenderTargetD3D *renderTarget = NULL;
+ ANGLE_TRY(getRenderTarget(index, &renderTarget));
+ ASSERT(!mImageArray[level]->isDirty());
+
+ return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, renderTarget);
+ }
+ else
+ {
+ return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
+ }
+}
+
+gl::Error TextureD3D_2D::setCompressedImage(GLenum target,
+ size_t imageLevel,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D && size.depth == 1);
+ GLint level = static_cast<GLint>(imageLevel);
+
+ // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+ redefineImage(level, internalFormat, size, false);
+
+ return setCompressedImageImpl(gl::ImageIndex::Make2D(level), unpack, pixels, 0);
+}
+
+gl::Error TextureD3D_2D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);
+
+ gl::ImageIndex index = gl::ImageIndex::Make2D(static_cast<GLint>(level));
+ ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0));
+
+ return commitRegion(index, area);
+}
+
+gl::Error TextureD3D_2D::copyImage(GLenum target,
+ size_t imageLevel,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source)
+{
+ ASSERT(target == GL_TEXTURE_2D);
+
+ GLint level = static_cast<GLint>(imageLevel);
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE);
+ redefineImage(level, sizedInternalFormat, gl::Extents(sourceArea.width, sourceArea.height, 1),
+ false);
+
+ gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+ gl::Offset destOffset(0, 0, 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->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source));
+ mDirtyImages = true;
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget());
+ mImageArray[level]->markClean();
+
+ if (sourceArea.width != 0 && sourceArea.height != 0 && isValidLevel(level))
+ {
+ ANGLE_TRY(mRenderer->copyImage2D(source, sourceArea, internalFormat, destOffset,
+ mTexStorage, level));
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_2D::copySubImage(GLenum target,
+ size_t imageLevel,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ ASSERT(target == GL_TEXTURE_2D && destOffset.z == 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)
+
+ GLint level = static_cast<GLint>(imageLevel);
+ gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+
+ // 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->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source));
+ mDirtyImages = true;
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget());
+
+ if (isValidLevel(level))
+ {
+ ANGLE_TRY(updateStorageLevel(level));
+ ANGLE_TRY(mRenderer->copyImage2D(
+ source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
+ destOffset, mTexStorage, level));
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_2D::copyTexture(GLenum internalFormat,
+ GLenum type,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ GLenum sourceTarget = source->getTarget();
+ GLint sourceLevel = 0;
+
+ GLint destLevel = 0;
+
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+ gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
+ static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
+ redefineImage(destLevel, sizedInternalFormat, size, false);
+
+ ASSERT(canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel)));
+
+ ANGLE_TRY(ensureRenderTarget());
+ ASSERT(isValidLevel(destLevel));
+ ANGLE_TRY(updateStorageLevel(destLevel));
+
+ gl::Rectangle sourceRect(0, 0, size.width, size.height);
+ gl::Offset destOffset(0, 0, 0);
+ ANGLE_TRY(mRenderer->copyTexture(source, sourceLevel, sourceRect,
+ gl::GetInternalFormatInfo(sizedInternalFormat).format,
+ destOffset, mTexStorage, destLevel, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::copySubTexture(const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ GLint sourceLevel = 0;
+ GLint destLevel = 0;
+
+ ASSERT(canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel)));
+
+ ANGLE_TRY(ensureRenderTarget());
+ ASSERT(isValidLevel(destLevel));
+ ANGLE_TRY(updateStorageLevel(destLevel));
+
+ ANGLE_TRY(mRenderer->copyTexture(source, sourceLevel, sourceArea,
+ gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
+ destOffset, mTexStorage, destLevel, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::copyCompressedTexture(const gl::Texture *source)
+{
+ GLenum sourceTarget = source->getTarget();
+ GLint sourceLevel = 0;
+
+ GLint destLevel = 0;
+
+ GLenum sizedInternalFormat = source->getFormat(sourceTarget, sourceLevel).asSized();
+ gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
+ static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
+ redefineImage(destLevel, sizedInternalFormat, size, false);
+
+ ANGLE_TRY(initializeStorage(false));
+ ASSERT(mTexStorage);
+
+ ANGLE_TRY(mRenderer->copyCompressedTexture(source, sourceLevel, mTexStorage, destLevel));
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
+{
+ ASSERT(GL_TEXTURE_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);
+ redefineImage(level, internalFormat, levelSize, true);
+ }
+
+ for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true);
+ }
+
+ // TODO(geofflang): Verify storage creation had no errors
+ bool renderTarget = IsRenderTargetUsage(mState.getUsage());
+ TextureStorage *storage = mRenderer->createTextureStorage2D(
+ internalFormat, renderTarget, size.width, size.height, static_cast<int>(levels), false);
+
+ gl::Error error = setCompleteTexStorage(storage);
+ if (error.isError())
+ {
+ SafeDelete(storage);
+ return error;
+ }
+
+ ANGLE_TRY(updateStorage());
+
+ mImmutable = true;
+
+ return gl::NoError();
+}
+
+void TextureD3D_2D::bindTexImage(egl::Surface *surface)
+{
+ GLenum internalformat = surface->getConfig()->renderTargetFormat;
+
+ gl::Extents size(surface->getWidth(), surface->getHeight(), 1);
+ redefineImage(0, internalformat, size, true);
+
+ if (mTexStorage)
+ {
+ SafeDelete(mTexStorage);
+ }
+
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ ASSERT(surfaceD3D);
+
+ mTexStorage = mRenderer->createTextureStorage2D(surfaceD3D->getSwapChain());
+ mEGLImageTarget = false;
+
+ mDirtyImages = true;
+}
+
+void TextureD3D_2D::releaseTexImage()
+{
+ if (mTexStorage)
+ {
+ SafeDelete(mTexStorage);
+ }
+
+ for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ redefineImage(i, GL_NONE, gl::Extents(0, 0, 1), true);
+ }
+}
+
+gl::Error TextureD3D_2D::setEGLImageTarget(GLenum target, 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);
+ redefineImage(0, format.asSized(), size, true);
+
+ // Clear all other images.
+ for (size_t level = 1; level < ArraySize(mImageArray); level++)
+ {
+ redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true);
+ }
+
+ SafeDelete(mTexStorage);
+ mImageArray[0]->markClean();
+
+ // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error.
+ RenderTargetD3D *renderTargetD3D = nullptr;
+ ANGLE_TRY(eglImaged3d->getRenderTarget(&renderTargetD3D));
+
+ mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D);
+ mEGLImageTarget = true;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void TextureD3D_2D::initMipmapImages()
+{
+ 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);
+
+ redefineImage(level, getBaseLevelInternalFormat(), levelSize, false);
+ }
+}
+
+gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+ ASSERT(!index.hasLayer());
+
+ // ensure the underlying texture is created
+ ANGLE_TRY(ensureRenderTarget());
+ ANGLE_TRY(updateStorageLevel(index.mipIndex));
+
+ return mTexStorage->getRenderTarget(index, 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 <= (int)ArraySize(mImageArray) && mImageArray[level] != nullptr);
+ ImageD3D *image = mImageArray[level];
+
+ 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.mipIndex);
+}
+
+// Constructs a native texture resource from the texture images
+gl::Error TextureD3D_2D::initializeStorage(bool renderTarget)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ // do not attempt to create storage for nonexistant data
+ if (!isLevelComplete(getBaseLevel()))
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
+
+ TextureStorage *storage = NULL;
+ ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
+
+ gl::Error error = setCompleteTexStorage(storage);
+ if (error.isError())
+ {
+ SafeDelete(storage);
+ return error;
+ }
+
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ ANGLE_TRY(updateStorage());
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) 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->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ // 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
+ *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels, hintLevelZeroOnly);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+ if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
+ {
+ for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
+ {
+ ANGLE_TRY(mImageArray[level]->setManagedSurface2D(newCompleteTexStorage, level));
+ }
+ }
+
+ SafeDelete(mTexStorage);
+ mTexStorage = newCompleteTexStorage;
+
+ mDirtyImages = true;
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::updateStorage()
+{
+ ASSERT(mTexStorage != NULL);
+ GLint storageLevels = mTexStorage->getLevelCount();
+ for (int level = 0; level < storageLevels; level++)
+ {
+ if (mImageArray[level]->isDirty() && isLevelComplete(level))
+ {
+ ANGLE_TRY(updateStorageLevel(level));
+ }
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::updateStorageLevel(int level)
+{
+ ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
+ 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(index, region));
+ }
+
+ return gl::NoError();
+}
+
+void TextureD3D_2D::redefineImage(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();
+
+ mImageArray[level]->redefine(GL_TEXTURE_2D, internalformat, size, forceRelease);
+
+ 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)
+ {
+ // TODO(jmadill): Don't discard error.
+ mImageArray[0]->copyFromTexStorage(gl::ImageIndex::Make2D(0), mTexStorage);
+ }
+
+ if ((level >= storageLevels && storageLevels != 0) ||
+ size.width != storageWidth ||
+ size.height != storageHeight ||
+ internalformat != storageFormat) // Discard mismatched storage
+ {
+ markAllImagesDirty();
+ SafeDelete(mTexStorage);
+ }
+ }
+
+ // Can't be an EGL image target after being redefined
+ mEGLImageTarget = false;
+}
+
+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.type == GL_TEXTURE_2D &&
+ index.mipIndex >= 0 && index.mipIndex < 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 (int i = 0; i < 6; i++)
+ {
+ for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
+ {
+ mImageArray[i][j] = renderer->createImage();
+ }
+ }
+}
+
+TextureD3D_Cube::~TextureD3D_Cube()
+{
+ // 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 (int i = 0; i < 6; i++)
+ {
+ for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
+ {
+ SafeDelete(mImageArray[i][j]);
+ }
+ }
+
+ SafeDelete(mTexStorage);
+}
+
+ImageD3D *TextureD3D_Cube::getImage(int level, int layer) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(layer >= 0 && layer < 6);
+ return mImageArray[layer][level];
+}
+
+ImageD3D *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const
+{
+ ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(index.layerIndex >= 0 && index.layerIndex < 6);
+ return mImageArray[index.layerIndex][index.mipIndex];
+}
+
+GLsizei TextureD3D_Cube::getLayerCount(int level) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ return 6;
+}
+
+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::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0;
+}
+
+gl::Error TextureD3D_Cube::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_Cube::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
+{
+ ASSERT(size.depth == 1);
+
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+ gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
+
+ redefineImage(index.layerIndex, static_cast<GLint>(level), sizedInternalFormat, size);
+
+ return setImageImpl(index, type, unpack, pixels, 0);
+}
+
+gl::Error TextureD3D_Cube::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
+{
+ ASSERT(area.depth == 1 && area.z == 0);
+
+ gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
+ return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
+}
+
+gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, size_t level, 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
+ size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target);
+
+ redefineImage(static_cast<int>(faceIndex), static_cast<GLint>(level), internalFormat, size);
+
+ gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
+ return setCompressedImageImpl(index, unpack, pixels, 0);
+}
+
+gl::Error TextureD3D_Cube::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
+{
+ ASSERT(area.depth == 1 && area.z == 0);
+
+ gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
+
+ ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0));
+ return commitRegion(index, area);
+}
+
+gl::Error TextureD3D_Cube::copyImage(GLenum target,
+ size_t imageLevel,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source)
+{
+ int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target));
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE);
+
+ GLint level = static_cast<GLint>(imageLevel);
+
+ gl::Extents size(sourceArea.width, sourceArea.height, 1);
+ redefineImage(static_cast<int>(faceIndex), level, sizedInternalFormat, size);
+
+ gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
+ gl::Offset destOffset(0, 0, 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->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ ANGLE_TRY(
+ mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source));
+ mDirtyImages = true;
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget());
+ mImageArray[faceIndex][level]->markClean();
+
+ ASSERT(size.width == size.height);
+
+ if (size.width > 0 && isValidFaceLevel(faceIndex, level))
+ {
+ ANGLE_TRY(mRenderer->copyImageCube(source, sourceArea, internalFormat, destOffset,
+ mTexStorage, target, level));
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_Cube::copySubImage(GLenum target,
+ size_t imageLevel,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target));
+
+ GLint level = static_cast<GLint>(imageLevel);
+ gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
+
+ // 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->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ gl::Error error =
+ mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mDirtyImages = true;
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget());
+ if (isValidFaceLevel(faceIndex, level))
+ {
+ ANGLE_TRY(updateStorageFaceLevel(faceIndex, level));
+ ANGLE_TRY(mRenderer->copyImageCube(
+ source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
+ destOffset, mTexStorage, target, level));
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_Cube::setStorage(GLenum target, 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 (int faceIndex = 0; faceIndex < 6; faceIndex++)
+ {
+ mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalFormat, gl::Extents(mipSize, mipSize, 1), true);
+ }
+ }
+
+ for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+ {
+ mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, GL_NONE, gl::Extents(0, 0, 0), true);
+ }
+ }
+
+ // TODO(geofflang): Verify storage creation had no errors
+ bool renderTarget = IsRenderTargetUsage(mState.getUsage());
+
+ TextureStorage *storage = mRenderer->createTextureStorageCube(
+ internalFormat, renderTarget, size.width, static_cast<int>(levels), false);
+
+ gl::Error error = setCompleteTexStorage(storage);
+ if (error.isError())
+ {
+ SafeDelete(storage);
+ return error;
+ }
+
+ ANGLE_TRY(updateStorage());
+
+ mImmutable = true;
+
+ return gl::NoError();
+}
+
+// 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 (int faceIndex = 1; faceIndex < 6; faceIndex++)
+ {
+ const ImageD3D &faceBaseImage = *mImageArray[faceIndex][getBaseLevel()];
+
+ if (faceBaseImage.getWidth() != baseWidth ||
+ faceBaseImage.getHeight() != baseHeight ||
+ faceBaseImage.getInternalFormat() != baseFormat )
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void TextureD3D_Cube::bindTexImage(egl::Surface *surface)
+{
+ UNREACHABLE();
+}
+
+void TextureD3D_Cube::releaseTexImage()
+{
+ UNREACHABLE();
+}
+
+void TextureD3D_Cube::initMipmapImages()
+{
+ 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 < 6; faceIndex++)
+ {
+ for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
+ {
+ int faceLevelSize =
+ (std::max(mImageArray[faceIndex][baseLevel]->getWidth() >> (level - baseLevel), 1));
+ redefineImage(faceIndex, level, mImageArray[faceIndex][baseLevel]->getInternalFormat(),
+ gl::Extents(faceLevelSize, faceLevelSize, 1));
+ }
+ }
+}
+
+gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+ ASSERT(gl::IsCubeMapTextureTarget(index.type));
+
+ // ensure the underlying texture is created
+ ANGLE_TRY(ensureRenderTarget());
+ ANGLE_TRY(updateStorageFaceLevel(index.layerIndex, index.mipIndex));
+
+ return mTexStorage->getRenderTarget(index, outRT);
+}
+
+gl::Error TextureD3D_Cube::initializeStorage(bool renderTarget)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return gl::NoError();
+ }
+
+ // do not attempt to create storage for nonexistant data
+ if (!isFaceLevelComplete(0, getBaseLevel()))
+ {
+ return gl::NoError();
+ }
+
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
+
+ TextureStorage *storage = NULL;
+ ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
+
+ gl::Error error = setCompleteTexStorage(storage);
+ if (error.isError())
+ {
+ SafeDelete(storage);
+ return error;
+ }
+
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ ANGLE_TRY(updateStorage());
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) 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->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ // If any of the CPU images (levels >= 1) are dirty, then the textureStorage should use the mipped texture to begin with.
+ // Otherwise, it should use the level-zero-only texture.
+ hintLevelZeroOnly = true;
+ for (int faceIndex = 0; faceIndex < 6 && 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
+ *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+ if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
+ {
+ for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+ {
+ for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
+ {
+ ANGLE_TRY(mImageArray[faceIndex][level]->setManagedSurfaceCube(
+ newCompleteTexStorage, faceIndex, level));
+ }
+ }
+ }
+
+ SafeDelete(mTexStorage);
+ mTexStorage = newCompleteTexStorage;
+
+ mDirtyImages = true;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_Cube::updateStorage()
+{
+ ASSERT(mTexStorage != NULL);
+ GLint storageLevels = mTexStorage->getLevelCount();
+ for (int face = 0; face < 6; face++)
+ {
+ for (int level = 0; level < storageLevels; level++)
+ {
+ if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level))
+ {
+ ANGLE_TRY(updateStorageFaceLevel(face, level));
+ }
+ }
+ }
+
+ return gl::NoError();
+}
+
+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 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) &&
+ mImageArray[faceIndex][level] != nullptr);
+
+ if (isImmutable())
+ {
+ return true;
+ }
+
+ int levelZeroSize = getLevelZeroWidth();
+
+ if (levelZeroSize <= 0)
+ {
+ return false;
+ }
+
+ // "isCubeComplete" checks for base level completeness and we must call that
+ // to determine if any face at level 0 is complete. We omit that check here
+ // to avoid re-checking cube-completeness for every face at level 0.
+ if (level == 0)
+ {
+ return true;
+ }
+
+ // Check that non-zero levels are consistent with the base level.
+ const ImageD3D *faceLevelImage = mImageArray[faceIndex][level];
+
+ 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.layerIndex, index.mipIndex);
+}
+
+gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level)
+{
+ ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL);
+ ImageD3D *image = mImageArray[faceIndex][level];
+
+ if (image->isDirty())
+ {
+ GLenum faceTarget = gl::LayerIndexToCubeMapTextureTarget(faceIndex);
+ gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level);
+ gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1);
+ ANGLE_TRY(commitRegion(index, region));
+ }
+
+ return gl::NoError();
+}
+
+void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size)
+{
+ // 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();
+
+ mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalformat, size, false);
+
+ if (mTexStorage)
+ {
+ const int storageLevels = mTexStorage->getLevelCount();
+
+ if ((level >= storageLevels && storageLevels != 0) ||
+ size.width != storageWidth ||
+ size.height != storageHeight ||
+ internalformat != storageFormat) // Discard mismatched storage
+ {
+ markAllImagesDirty();
+ SafeDelete(mTexStorage);
+ }
+ }
+}
+
+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::MakeCube(gl::LayerIndexToCubeMapTextureTarget(layer), mip);
+}
+
+bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const
+{
+ return (mTexStorage && gl::IsCubeMapTextureTarget(index.type) &&
+ index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
+}
+
+void TextureD3D_Cube::markAllImagesDirty()
+{
+ for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
+ {
+ for (int dirtyFace = 0; dirtyFace < 6; 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] = renderer->createImage();
+ }
+}
+
+TextureD3D_3D::~TextureD3D_3D()
+{
+ // 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 (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+ {
+ delete mImageArray[i];
+ }
+
+ SafeDelete(mTexStorage);
+}
+
+ImageD3D *TextureD3D_3D::getImage(int level, int layer) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(layer == 0);
+ return mImageArray[level];
+}
+
+ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const
+{
+ ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(!index.hasLayer());
+ ASSERT(index.type == GL_TEXTURE_3D);
+ return mImageArray[index.mipIndex];
+}
+
+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::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+}
+
+gl::Error TextureD3D_3D::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_3D::setImage(GLenum target,
+ size_t imageLevel,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_3D);
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+
+ GLint level = static_cast<GLint>(imageLevel);
+ redefineImage(level, sizedInternalFormat, size);
+
+ bool fastUnpacked = false;
+
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+
+ // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
+ if (isFastUnpackable(unpack, sizedInternalFormat) && !size.empty() && isLevelComplete(level))
+ {
+ // Will try to create RT storage if it does not exist
+ RenderTargetD3D *destRenderTarget = NULL;
+ ANGLE_TRY(getRenderTarget(index, &destRenderTarget));
+
+ gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
+
+ ANGLE_TRY(fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type,
+ destRenderTarget));
+
+ // Ensure we don't overwrite our newly initialized data
+ mImageArray[level]->markClean();
+
+ fastUnpacked = true;
+ }
+
+ if (!fastUnpacked)
+ {
+ ANGLE_TRY(setImageImpl(index, type, unpack, pixels, 0));
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_3D::setSubImage(GLenum target,
+ size_t imageLevel,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_3D);
+
+ GLint level = static_cast<GLint>(imageLevel);
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+
+ // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
+ if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
+ {
+ RenderTargetD3D *destRenderTarget = NULL;
+ ANGLE_TRY(getRenderTarget(index, &destRenderTarget));
+ ASSERT(!mImageArray[level]->isDirty());
+
+ return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, destRenderTarget);
+ }
+ else
+ {
+ return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
+ }
+}
+
+gl::Error TextureD3D_3D::setCompressedImage(GLenum target,
+ size_t imageLevel,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_3D);
+
+ GLint level = static_cast<GLint>(imageLevel);
+ // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+ redefineImage(level, internalFormat, size);
+
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+ return setCompressedImageImpl(index, unpack, pixels, 0);
+}
+
+gl::Error TextureD3D_3D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_3D);
+
+ gl::ImageIndex index = gl::ImageIndex::Make3D(static_cast<GLint>(level));
+ ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0));
+ return commitRegion(index, area);
+}
+
+gl::Error TextureD3D_3D::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented.");
+}
+
+gl::Error TextureD3D_3D::copySubImage(GLenum target,
+ size_t imageLevel,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ ASSERT(target == GL_TEXTURE_3D);
+
+ GLint level = static_cast<GLint>(imageLevel);
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+
+ if (canCreateRenderTargetForImage(index))
+ {
+ ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source));
+ mDirtyImages = true;
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget());
+ if (isValidLevel(level))
+ {
+ ANGLE_TRY(updateStorageLevel(level));
+ ANGLE_TRY(mRenderer->copyImage3D(
+ source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
+ destOffset, mTexStorage, level));
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_3D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
+{
+ ASSERT(target == GL_TEXTURE_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_TEXTURE_3D, internalFormat, levelSize, true);
+ }
+
+ for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ mImageArray[level]->redefine(GL_TEXTURE_3D, GL_NONE, gl::Extents(0, 0, 0), true);
+ }
+
+ // TODO(geofflang): Verify storage creation had no errors
+ bool renderTarget = IsRenderTargetUsage(mState.getUsage());
+ TextureStorage *storage =
+ mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width, size.height,
+ size.depth, static_cast<int>(levels));
+
+ gl::Error error = setCompleteTexStorage(storage);
+ if (error.isError())
+ {
+ SafeDelete(storage);
+ return error;
+ }
+
+ ANGLE_TRY(updateStorage());
+
+ mImmutable = true;
+
+ return gl::NoError();
+}
+
+void TextureD3D_3D::bindTexImage(egl::Surface *surface)
+{
+ UNREACHABLE();
+}
+
+void TextureD3D_3D::releaseTexImage()
+{
+ UNREACHABLE();
+}
+
+void TextureD3D_3D::initMipmapImages()
+{
+ 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));
+ redefineImage(level, getBaseLevelInternalFormat(), levelSize);
+ }
+}
+
+gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+ // ensure the underlying texture is created
+ ANGLE_TRY(ensureRenderTarget());
+
+ if (index.hasLayer())
+ {
+ ANGLE_TRY(updateStorage());
+ }
+ else
+ {
+ ANGLE_TRY(updateStorageLevel(index.mipIndex));
+ }
+
+ return mTexStorage->getRenderTarget(index, outRT);
+}
+
+gl::Error TextureD3D_3D::initializeStorage(bool renderTarget)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ // do not attempt to create storage for nonexistant data
+ if (!isLevelComplete(getBaseLevel()))
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
+
+ TextureStorage *storage = NULL;
+ ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
+
+ gl::Error error = setCompleteTexStorage(storage);
+ if (error.isError())
+ {
+ SafeDelete(storage);
+ return error;
+ }
+
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ ANGLE_TRY(updateStorage());
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage **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, renderTarget, width, height, depth, levels);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+ SafeDelete(mTexStorage);
+ mTexStorage = newCompleteTexStorage;
+ mDirtyImages = true;
+
+ // We do not support managed 3D storage, as that is D3D9/ES2-only
+ ASSERT(!mTexStorage->isManaged());
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_3D::updateStorage()
+{
+ ASSERT(mTexStorage != NULL);
+ GLint storageLevels = mTexStorage->getLevelCount();
+ for (int level = 0; level < storageLevels; level++)
+ {
+ if (mImageArray[level]->isDirty() && isLevelComplete(level))
+ {
+ ANGLE_TRY(updateStorageLevel(level));
+ }
+ }
+
+ return gl::NoError();
+}
+
+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 < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
+
+ 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];
+
+ 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.mipIndex);
+}
+
+gl::Error TextureD3D_3D::updateStorageLevel(int level)
+{
+ ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
+ 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(index, region));
+ }
+
+ return gl::NoError();
+}
+
+void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size)
+{
+ // 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();
+
+ mImageArray[level]->redefine(GL_TEXTURE_3D, internalformat, size, false);
+
+ 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();
+ SafeDelete(mTexStorage);
+ }
+ }
+}
+
+gl::ImageIndexIterator TextureD3D_3D::imageIterator() const
+{
+ return gl::ImageIndexIterator::Make3D(0, mTexStorage->getLevelCount(),
+ gl::ImageIndex::ENTIRE_LEVEL, gl::ImageIndex::ENTIRE_LEVEL);
+}
+
+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.type == GL_TEXTURE_3D &&
+ index.mipIndex >= 0 && index.mipIndex < 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] = NULL;
+ }
+}
+
+TextureD3D_2DArray::~TextureD3D_2DArray()
+{
+ // 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();
+ SafeDelete(mTexStorage);
+}
+
+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] : NULL);
+}
+
+ImageD3D *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const
+{
+ ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT((index.layerIndex == 0 && mLayerCounts[index.mipIndex] == 0) ||
+ index.layerIndex < mLayerCounts[index.mipIndex]);
+ ASSERT(index.type == GL_TEXTURE_2D_ARRAY);
+ return (mImageArray[index.mipIndex] ? mImageArray[index.mipIndex][index.layerIndex] : NULL);
+}
+
+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::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+}
+
+gl::Error TextureD3D_2DArray::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_2DArray::setImage(GLenum target,
+ size_t imageLevel,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+ GLint level = static_cast<GLint>(imageLevel);
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+ redefineImage(level, sizedInternalFormat, size);
+
+ const auto sizedInputFormat = gl::GetSizedInternalFormat(format, type);
+ const gl::InternalFormat &inputFormat = gl::GetInternalFormatInfo(sizedInputFormat);
+ GLsizei inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(inputFormat.computeDepthPitch(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 index = gl::ImageIndex::Make2DArray(level, i);
+ ANGLE_TRY(setImageImpl(index, type, unpack, pixels, layerOffset));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::setSubImage(GLenum target,
+ size_t imageLevel,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D_ARRAY);
+ GLint level = static_cast<GLint>(imageLevel);
+ const auto sizedInputFormat = gl::GetSizedInternalFormat(format, type);
+ const gl::InternalFormat &inputFormat = gl::GetInternalFormatInfo(sizedInputFormat);
+ GLsizei inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(inputFormat.computeDepthPitch(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 index = gl::ImageIndex::Make2DArray(level, layer);
+ ANGLE_TRY(
+ TextureD3D::subImage(index, layerArea, format, type, unpack, pixels, layerOffset));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target,
+ size_t imageLevel,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+ GLint level = static_cast<GLint>(imageLevel);
+ // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+ redefineImage(level, internalFormat, size);
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ GLsizei inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(
+ formatInfo.computeDepthPitch(size.width, size.height, 1, 0, 0),
+ inputDepthPitch);
+
+ for (int i = 0; i < size.depth; i++)
+ {
+ const ptrdiff_t layerOffset = (inputDepthPitch * i);
+
+ gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
+ ANGLE_TRY(setCompressedImageImpl(index, unpack, pixels, layerOffset));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
+ GLsizei inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(
+ formatInfo.computeDepthPitch(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 index = gl::ImageIndex::Make2DArray(static_cast<GLint>(level), layer);
+ ANGLE_TRY(
+ TextureD3D::subImageCompressed(index, layerArea, format, unpack, pixels, layerOffset));
+ ANGLE_TRY(commitRegion(index, layerArea));
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_2DArray::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented.");
+}
+
+gl::Error TextureD3D_2DArray::copySubImage(GLenum target,
+ size_t imageLevel,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+ GLint level = static_cast<GLint>(imageLevel);
+ gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z);
+
+ if (canCreateRenderTargetForImage(index))
+ {
+ gl::Offset destLayerOffset(destOffset.x, destOffset.y, 0);
+ ANGLE_TRY(mImageArray[level][destOffset.z]->copyFromFramebuffer(destLayerOffset, sourceArea,
+ source));
+ mDirtyImages = true;
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget());
+
+ if (isValidLevel(level))
+ {
+ ANGLE_TRY(updateStorageLevel(level));
+ ANGLE_TRY(mRenderer->copyImage2DArray(
+ source, sourceArea,
+ gl::GetInternalFormatInfo(getInternalFormat(getBaseLevel())).format, destOffset,
+ mTexStorage, level));
+ }
+ }
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_2DArray::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
+{
+ ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+ 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_TEXTURE_2D_ARRAY, internalFormat, levelLayerSize, true);
+ }
+ }
+ }
+
+ // TODO(geofflang): Verify storage creation had no errors
+ bool renderTarget = IsRenderTargetUsage(mState.getUsage());
+ TextureStorage *storage =
+ mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width,
+ size.height, size.depth, static_cast<int>(levels));
+
+ gl::Error error = setCompleteTexStorage(storage);
+ if (error.isError())
+ {
+ SafeDelete(storage);
+ return error;
+ }
+
+ ANGLE_TRY(updateStorage());
+
+ mImmutable = true;
+
+ return gl::NoError();
+}
+
+void TextureD3D_2DArray::bindTexImage(egl::Surface *surface)
+{
+ UNREACHABLE();
+}
+
+void TextureD3D_2DArray::releaseTexImage()
+{
+ UNREACHABLE();
+}
+
+void TextureD3D_2DArray::initMipmapImages()
+{
+ 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);
+ redefineImage(level, baseFormat, levelLayerSize);
+ }
+}
+
+gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+ // ensure the underlying texture is created
+ ANGLE_TRY(ensureRenderTarget());
+ ANGLE_TRY(updateStorageLevel(index.mipIndex));
+ return mTexStorage->getRenderTarget(index, outRT);
+}
+
+gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return gl::NoError();
+ }
+
+ // do not attempt to create storage for nonexistant data
+ if (!isLevelComplete(getBaseLevel()))
+ {
+ return gl::NoError();
+ }
+
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
+
+ TextureStorage *storage = nullptr;
+ ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
+
+ gl::Error error = setCompleteTexStorage(storage);
+ if (error.isError())
+ {
+ SafeDelete(storage);
+ return error;
+ }
+
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ ANGLE_TRY(updateStorage());
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureStorage **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, renderTarget, width, height, depth, levels);
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+ SafeDelete(mTexStorage);
+ mTexStorage = newCompleteTexStorage;
+ mDirtyImages = true;
+
+ // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only
+ ASSERT(!mTexStorage->isManaged());
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DArray::updateStorage()
+{
+ ASSERT(mTexStorage != NULL);
+ GLint storageLevels = mTexStorage->getLevelCount();
+ for (int level = 0; level < storageLevels; level++)
+ {
+ if (isLevelComplete(level))
+ {
+ ANGLE_TRY(updateStorageLevel(level));
+ }
+ }
+
+ return gl::NoError();
+}
+
+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.mipIndex);
+}
+
+gl::Error TextureD3D_2DArray::updateStorageLevel(int level)
+{
+ ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts));
+ ASSERT(isLevelComplete(level));
+
+ for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ {
+ ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL);
+ 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(index, region));
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+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] = NULL;
+ mLayerCounts[level] = 0;
+ }
+}
+
+void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size)
+{
+ // 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();
+ 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 (size.depth > 0)
+ {
+ for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ {
+ mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalformat,
+ gl::Extents(size.width, size.height, 1), false);
+ }
+ }
+
+ if (mTexStorage)
+ {
+ const GLenum storageFormat = getBaseLevelInternalFormat();
+ 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();
+ SafeDelete(mTexStorage);
+ }
+ }
+}
+
+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.type != GL_TEXTURE_2D_ARRAY)
+ {
+ return false;
+ }
+
+ // Check the mip index
+ if (index.mipIndex < 0 || index.mipIndex >= mTexStorage->getLevelCount())
+ {
+ return false;
+ }
+
+ // Check the layer index
+ return (!index.hasLayer() || (index.layerIndex >= 0 && index.layerIndex < mLayerCounts[index.mipIndex]));
+}
+
+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;
+}
+
+TextureD3D_External::TextureD3D_External(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3D(state, renderer)
+{
+}
+
+TextureD3D_External::~TextureD3D_External()
+{
+ SafeDelete(mTexStorage);
+}
+
+ImageD3D *TextureD3D_External::getImage(const gl::ImageIndex &index) const
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+GLsizei TextureD3D_External::getLayerCount(int level) const
+{
+ return 1;
+}
+
+gl::Error TextureD3D_External::setImage(GLenum target,
+ size_t imageLevel,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ // Image setting is not supported for external images
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::setSubImage(GLenum target,
+ size_t imageLevel,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::setCompressedImage(GLenum target,
+ size_t imageLevel,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::setCompressedSubImage(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::copyImage(GLenum target,
+ size_t imageLevel,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::copySubImage(GLenum target,
+ size_t imageLevel,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::setStorage(GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureD3D_External::setImageExternal(GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
+{
+ ASSERT(target == GL_TEXTURE_EXTERNAL_OES);
+
+ SafeDelete(mTexStorage);
+
+ // If the stream is null, the external image is unbound and we release the storage
+ if (stream != nullptr)
+ {
+ mTexStorage = mRenderer->createTextureStorageExternal(stream, desc);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void TextureD3D_External::bindTexImage(egl::Surface *surface)
+{
+ UNREACHABLE();
+}
+
+void TextureD3D_External::releaseTexImage()
+{
+ UNREACHABLE();
+}
+
+gl::Error TextureD3D_External::setEGLImageTarget(GLenum target, 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(&renderTargetD3D));
+
+ SafeDelete(mTexStorage);
+ mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D);
+
+ return gl::NoError();
+}
+
+void TextureD3D_External::initMipmapImages()
+{
+ UNREACHABLE();
+}
+
+gl::Error TextureD3D_External::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+bool TextureD3D_External::isImageComplete(const gl::ImageIndex &index) const
+{
+ return (index.mipIndex == 0) ? (mTexStorage != nullptr) : false;
+}
+
+gl::Error TextureD3D_External::initializeStorage(bool renderTarget)
+{
+ // Texture storage is created when an external image is bound
+ ASSERT(mTexStorage);
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_External::createCompleteStorage(bool renderTarget,
+ TextureStorage **outTexStorage) const
+{
+ UNREACHABLE();
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_External::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+ UNREACHABLE();
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureD3D_External::updateStorage()
+{
+ // Texture storage does not need to be updated since it is already loaded with the latest
+ // external image
+ ASSERT(mTexStorage);
+ return gl::Error(GL_NO_ERROR);
+}
+
+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.type == GL_TEXTURE_EXTERNAL_OES && index.mipIndex == 0);
+}
+
+void TextureD3D_External::markAllImagesDirty()
+{
+ UNREACHABLE();
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.h
new file mode 100755
index 000000000..99343632a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.h
@@ -0,0 +1,505 @@
+//
+// 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 "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Stream.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class EGLImageD3D;
+class ImageD3D;
+class RendererD3D;
+class RenderTargetD3D;
+class TextureStorage;
+
+class TextureD3D : public TextureImpl
+{
+ public:
+ TextureD3D(const gl::TextureState &data, RendererD3D *renderer);
+ virtual ~TextureD3D();
+
+ gl::Error getNativeTexture(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;
+
+ GLint getBaseLevelWidth() const;
+ GLint getBaseLevelHeight() const;
+ GLenum getBaseLevelInternalFormat() const;
+
+ bool isImmutable() const { return mImmutable; }
+
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, 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;
+
+ virtual gl::Error setImageExternal(GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+ gl::Error generateMipmap() override;
+ TextureStorage *getStorage();
+ ImageD3D *getBaseLevelImage() const;
+
+ gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut) override;
+
+ void setBaseLevel(GLuint baseLevel) override;
+
+ void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+
+ protected:
+ gl::Error setImageImpl(const gl::ImageIndex &index,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset);
+ gl::Error subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset);
+ gl::Error setCompressedImageImpl(const gl::ImageIndex &index,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset);
+ gl::Error subImageCompressed(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::PixelUnpackState &unpack, GLenum sizedInternalFormat);
+ gl::Error fastUnpackPixels(const gl::PixelUnpackState &unpack, 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 void initMipmapImages() = 0;
+ bool isBaseImageZeroSize() const;
+ virtual bool isImageComplete(const gl::ImageIndex &index) const = 0;
+
+ bool canCreateRenderTargetForImage(const gl::ImageIndex &index) const;
+ virtual gl::Error ensureRenderTarget();
+
+ virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const = 0;
+ virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) = 0;
+ gl::Error commitRegion(const gl::ImageIndex &index, const gl::Box &region);
+
+ GLuint getBaseLevel() const { return mBaseLevel; };
+
+ virtual void markAllImagesDirty() = 0;
+
+ GLint getBaseLevelDepth() const;
+
+ RendererD3D *mRenderer;
+
+ bool mDirtyImages;
+
+ bool mImmutable;
+ TextureStorage *mTexStorage;
+
+ private:
+ virtual gl::Error initializeStorage(bool renderTarget) = 0;
+
+ virtual gl::Error updateStorage() = 0;
+
+ bool shouldUseSetData(const ImageD3D *image) const;
+
+ gl::Error generateMipmapUsingImages(const GLuint maxLevel);
+
+ GLuint mBaseLevel;
+};
+
+class TextureD3D_2D : public TextureD3D
+{
+ public:
+ TextureD3D_2D(const gl::TextureState &data, RendererD3D *renderer);
+ virtual ~TextureD3D_2D();
+
+ virtual ImageD3D *getImage(int level, int layer) const;
+ virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
+ virtual GLsizei getLayerCount(int level) const;
+
+ GLsizei getWidth(GLint level) const;
+ GLsizei getHeight(GLint level) const;
+ GLenum getInternalFormat(GLint level) const;
+ bool isDepth(GLint level) const;
+
+ gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
+
+ gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error copyTexture(GLenum internalFormat,
+ GLenum type,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+ gl::Error copySubTexture(const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+ gl::Error copyCompressedTexture(const gl::Texture *source) override;
+
+ gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
+
+ virtual void bindTexImage(egl::Surface *surface);
+ virtual void releaseTexImage();
+
+ gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+ virtual gl::ImageIndexIterator imageIterator() const;
+ virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
+ virtual bool isValidIndex(const gl::ImageIndex &index) const;
+
+ protected:
+ void markAllImagesDirty() override;
+
+ private:
+ virtual gl::Error initializeStorage(bool renderTarget);
+ virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const;
+ virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+
+ virtual gl::Error updateStorage();
+ virtual void initMipmapImages();
+
+ bool isValidLevel(int level) const;
+ bool isLevelComplete(int level) const;
+ virtual bool isImageComplete(const gl::ImageIndex &index) const;
+
+ gl::Error updateStorageLevel(int level);
+
+ void redefineImage(size_t level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease);
+
+ bool mEGLImageTarget;
+ ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureD3D_Cube : public TextureD3D
+{
+ public:
+ TextureD3D_Cube(const gl::TextureState &data, RendererD3D *renderer);
+ virtual ~TextureD3D_Cube();
+
+ virtual ImageD3D *getImage(int level, int layer) const;
+ virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
+ virtual GLsizei getLayerCount(int level) const;
+
+ virtual bool hasDirtyImages() const { return mDirtyImages; }
+ virtual void resetDirty() { mDirtyImages = false; }
+
+ GLenum getInternalFormat(GLint level, GLint layer) const;
+ bool isDepth(GLint level, GLint layer) const;
+
+ gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
+
+ gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
+
+ virtual void bindTexImage(egl::Surface *surface);
+ virtual void releaseTexImage();
+
+ gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+ virtual gl::ImageIndexIterator imageIterator() const;
+ virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
+ virtual bool isValidIndex(const gl::ImageIndex &index) const;
+
+ protected:
+ void markAllImagesDirty() override;
+
+ private:
+ virtual gl::Error initializeStorage(bool renderTarget);
+ virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const;
+ virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+
+ virtual gl::Error updateStorage();
+ void initMipmapImages() override;
+
+ bool isValidFaceLevel(int faceIndex, int level) const;
+ bool isFaceLevelComplete(int faceIndex, int level) const;
+ bool isCubeComplete() const;
+ virtual bool isImageComplete(const gl::ImageIndex &index) const;
+ gl::Error updateStorageFaceLevel(int faceIndex, int level);
+
+ void redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size);
+
+ ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureD3D_3D : public TextureD3D
+{
+ public:
+ TextureD3D_3D(const gl::TextureState &data, RendererD3D *renderer);
+ virtual ~TextureD3D_3D();
+
+ virtual ImageD3D *getImage(int level, int layer) const;
+ virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
+ virtual GLsizei getLayerCount(int level) const;
+
+ 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;
+
+ gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
+
+ gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
+
+ virtual void bindTexImage(egl::Surface *surface);
+ virtual void releaseTexImage();
+
+ gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+ virtual gl::ImageIndexIterator imageIterator() const;
+ virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
+ virtual bool isValidIndex(const gl::ImageIndex &index) const;
+
+ protected:
+ void markAllImagesDirty() override;
+ GLint getLevelZeroDepth() const override;
+
+ private:
+ virtual gl::Error initializeStorage(bool renderTarget);
+ virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const;
+ virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+
+ virtual gl::Error updateStorage();
+ void initMipmapImages() override;
+
+ bool isValidLevel(int level) const;
+ bool isLevelComplete(int level) const;
+ virtual bool isImageComplete(const gl::ImageIndex &index) const;
+ gl::Error updateStorageLevel(int level);
+
+ void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size);
+
+ ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureD3D_2DArray : public TextureD3D
+{
+ public:
+ TextureD3D_2DArray(const gl::TextureState &data, RendererD3D *renderer);
+ virtual ~TextureD3D_2DArray();
+
+ virtual ImageD3D *getImage(int level, int layer) const;
+ virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
+ virtual GLsizei getLayerCount(int level) const;
+
+ GLsizei getWidth(GLint level) const;
+ GLsizei getHeight(GLint level) const;
+ GLenum getInternalFormat(GLint level) const;
+ bool isDepth(GLint level) const;
+
+ gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
+
+ gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
+
+ virtual void bindTexImage(egl::Surface *surface);
+ virtual void releaseTexImage();
+
+ gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+ virtual gl::ImageIndexIterator imageIterator() const;
+ virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
+ virtual bool isValidIndex(const gl::ImageIndex &index) const;
+
+ protected:
+ void markAllImagesDirty() override;
+
+ private:
+ virtual gl::Error initializeStorage(bool renderTarget);
+ virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const;
+ virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+
+ virtual gl::Error updateStorage();
+ void initMipmapImages() override;
+
+ bool isValidLevel(int level) const;
+ bool isLevelComplete(int level) const;
+ virtual bool isImageComplete(const gl::ImageIndex &index) const;
+ gl::Error updateStorageLevel(int level);
+
+ void deleteImages();
+ void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size);
+
+ // 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];
+};
+
+class TextureD3D_External : public TextureD3D
+{
+ public:
+ TextureD3D_External(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_External() override;
+
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+ GLsizei getLayerCount(int level) const override;
+
+ gl::Error setImage(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+ gl::Error setSubImage(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ gl::Error copyImage(GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorage(GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ gl::Error setImageExternal(GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+
+ void bindTexImage(egl::Surface *surface) override;
+ void releaseTexImage() override;
+
+ gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+ gl::Error getRenderTarget(const gl::ImageIndex &index, 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:
+ gl::Error initializeStorage(bool renderTarget) override;
+ gl::Error createCompleteStorage(bool renderTarget,
+ TextureStorage **outTexStorage) const override;
+ gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) override;
+
+ gl::Error updateStorage() override;
+ void initMipmapImages() override;
+
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+};
+}
+
+#endif // LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/TextureStorage.h b/gfx/angle/src/libANGLE/renderer/d3d/TextureStorage.h
new file mode 100755
index 000000000..417237495
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/TextureStorage.h
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// TextureStorage.h: Defines the abstract rx::TextureStorage class.
+
+#ifndef LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
+#define LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/debug.h"
+#include "libANGLE/Error.h"
+
+#include <GLES2/gl2.h>
+#include <stdint.h>
+
+namespace gl
+{
+struct ImageIndex;
+struct Box;
+struct PixelUnpackState;
+}
+
+namespace rx
+{
+class SwapChainD3D;
+class RenderTargetD3D;
+class ImageD3D;
+
+class TextureStorage : angle::NonCopyable
+{
+ public:
+ TextureStorage() {}
+ virtual ~TextureStorage() {}
+
+ virtual int getTopLevel() const = 0;
+ virtual bool isRenderTarget() const = 0;
+ virtual bool isManaged() const = 0;
+ virtual bool supportsNativeMipmapFunction() const = 0;
+ virtual int getLevelCount() const = 0;
+
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
+ virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) = 0;
+
+ virtual gl::Error copyToStorage(TextureStorage *destStorage) = 0;
+ virtual gl::Error setData(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 gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) { return gl::Error(GL_NO_ERROR); }
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp b/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp
new file mode 100755
index 000000000..eea85fea7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp
@@ -0,0 +1,405 @@
+//
+// 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 in D3D
+// for linking between shader stages.
+//
+
+#include "libANGLE/renderer/d3d/VaryingPacking.h"
+
+#include "common/utilities.h"
+#include "compiler/translator/blocklayoutHLSL.h"
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+
+namespace rx
+{
+
+// Implementation of VaryingPacking::BuiltinVarying
+VaryingPacking::BuiltinVarying::BuiltinVarying() : enabled(false), index(0), systemValue(false)
+{
+}
+
+std::string VaryingPacking::BuiltinVarying::str() const
+{
+ return (systemValue ? semantic : (semantic + Str(index)));
+}
+
+void VaryingPacking::BuiltinVarying::enableSystem(const std::string &systemValueSemantic)
+{
+ enabled = true;
+ semantic = systemValueSemantic;
+ systemValue = true;
+}
+
+void VaryingPacking::BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal)
+{
+ enabled = true;
+ semantic = semanticVal;
+ index = indexVal;
+}
+
+// Implementation of VaryingPacking
+VaryingPacking::VaryingPacking(GLuint maxVaryingVectors)
+ : mRegisterMap(maxVaryingVectors), mBuiltinInfo(SHADER_TYPE_MAX)
+{
+}
+
+// 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::packVarying(const PackedVarying &packedVarying)
+{
+ unsigned int varyingRows = 0;
+ unsigned int varyingColumns = 0;
+
+ const auto &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.Variables of type mat2 occupies 2 complete rows."
+ // 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);
+ varyingRows = gl::VariableRowCount(transposedType);
+ varyingColumns = gl::VariableColumnCount(transposedType);
+
+ // "Arrays of size N are assumed to take N times the size of the base type"
+ varyingRows *= varying.elementCount();
+
+ unsigned int maxVaryingVectors = static_cast<unsigned int>(mRegisterMap.size());
+
+ 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 (isFree(row, 0, varyingRows, varyingColumns))
+ {
+ insert(row, 0, 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 (isFree(r, 2, varyingRows, 2))
+ {
+ insert(r, 2, 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 (isFree(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 = arrayIndex;
+ registerInfo.varyingRowIndex = 0;
+ mRegisterList.push_back(registerInfo);
+ mRegisterMap[row + arrayIndex][bestColumn] = true;
+ }
+ break;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool VaryingPacking::isFree(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::insert(unsigned int registerRow,
+ unsigned int registerColumn,
+ const PackedVarying &packedVarying)
+{
+ unsigned int varyingRows = 0;
+ unsigned int varyingColumns = 0;
+
+ const auto &varying = *packedVarying.varying;
+ ASSERT(!varying.isStruct());
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ varyingRows = gl::VariableRowCount(transposedType);
+ varyingColumns = gl::VariableColumnCount(transposedType);
+
+ PackedVaryingRegister registerInfo;
+ registerInfo.packedVarying = &packedVarying;
+ registerInfo.registerColumn = registerColumn;
+
+ for (unsigned int arrayElement = 0; arrayElement < varying.elementCount(); ++arrayElement)
+ {
+ for (unsigned int varyingRow = 0; varyingRow < varyingRows; ++varyingRow)
+ {
+ registerInfo.registerRow = registerRow + (arrayElement * varyingRows) + varyingRow;
+ registerInfo.varyingRowIndex = varyingRow;
+ registerInfo.varyingArrayIndex = arrayElement;
+ mRegisterList.push_back(registerInfo);
+
+ for (unsigned int columnIndex = 0; columnIndex < varyingColumns; ++columnIndex)
+ {
+ mRegisterMap[registerInfo.registerRow][registerColumn + columnIndex] = true;
+ }
+ }
+ }
+}
+
+// See comment on packVarying.
+bool VaryingPacking::packVaryings(gl::InfoLog &infoLog,
+ const std::vector<PackedVarying> &packedVaryings,
+ const std::vector<std::string> &transformFeedbackVaryings)
+{
+ std::set<std::string> uniqueVaryingNames;
+
+ // "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)
+ {
+ const auto &varying = *packedVarying.varying;
+
+ // Do not assign registers to built-in or unreferenced varyings
+ if (varying.isBuiltIn() || (!varying.staticUse && !packedVarying.isStructField()))
+ {
+ continue;
+ }
+
+ ASSERT(!varying.isStruct());
+ ASSERT(uniqueVaryingNames.count(varying.name) == 0);
+
+ if (packVarying(packedVarying))
+ {
+ uniqueVaryingNames.insert(varying.name);
+ }
+ else
+ {
+ infoLog << "Could not pack varying " << varying.name;
+ return false;
+ }
+ }
+
+ for (const std::string &transformFeedbackVaryingName : transformFeedbackVaryings)
+ {
+ if (transformFeedbackVaryingName.compare(0, 3, "gl_") == 0)
+ {
+ // do not pack builtin XFB varyings
+ continue;
+ }
+
+ bool found = false;
+ for (const PackedVarying &packedVarying : packedVaryings)
+ {
+ const auto &varying = *packedVarying.varying;
+
+ // Make sure transform feedback varyings aren't optimized out.
+ if (uniqueVaryingNames.count(transformFeedbackVaryingName) > 0)
+ {
+ found = true;
+ break;
+ }
+
+ if (transformFeedbackVaryingName == varying.name)
+ {
+ if (!packVarying(packedVarying))
+ {
+ infoLog << "Could not pack varying " << varying.name;
+ return false;
+ }
+
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ infoLog << "Transform feedback varying " << transformFeedbackVaryingName
+ << " does not exist in the vertex shader.";
+ return false;
+ }
+ }
+
+ // Sort the packed register list
+ std::sort(mRegisterList.begin(), mRegisterList.end());
+
+ // Assign semantic indices
+ for (unsigned int semanticIndex = 0;
+ semanticIndex < static_cast<unsigned int>(mRegisterList.size()); ++semanticIndex)
+ {
+ mRegisterList[semanticIndex].semanticIndex = semanticIndex;
+ }
+
+ return true;
+}
+
+unsigned int VaryingPacking::getRegisterCount() const
+{
+ unsigned int count = 0;
+
+ for (const Register &reg : mRegisterMap)
+ {
+ if (reg.data[0] || reg.data[1] || reg.data[2] || reg.data[3])
+ {
+ ++count;
+ }
+ }
+
+ if (mBuiltinInfo[SHADER_PIXEL].glFragCoord.enabled)
+ {
+ ++count;
+ }
+
+ if (mBuiltinInfo[SHADER_PIXEL].glPointCoord.enabled)
+ {
+ ++count;
+ }
+
+ return count;
+}
+
+void VaryingPacking::enableBuiltins(ShaderType shaderType,
+ const ProgramD3DMetadata &programMetadata)
+{
+ int majorShaderModel = programMetadata.getRendererMajorShaderModel();
+ bool position = programMetadata.usesTransformFeedbackGLPosition();
+ bool fragCoord = programMetadata.usesFragCoord();
+ bool pointCoord = shaderType == SHADER_VERTEX ? programMetadata.addsPointCoordToVertexShader()
+ : programMetadata.usesPointCoord();
+ bool pointSize = programMetadata.usesSystemValuePointSize();
+ bool hlsl4 = (majorShaderModel >= 4);
+ const std::string &userSemantic = GetVaryingSemantic(majorShaderModel, pointSize);
+
+ unsigned int reservedSemanticIndex = getMaxSemanticIndex();
+
+ BuiltinInfo *builtins = &mBuiltinInfo[shaderType];
+
+ if (hlsl4)
+ {
+ builtins->dxPosition.enableSystem("SV_Position");
+ }
+ else if (shaderType == SHADER_PIXEL)
+ {
+ builtins->dxPosition.enableSystem("VPOS");
+ }
+ else
+ {
+ builtins->dxPosition.enableSystem("POSITION");
+ }
+
+ if (position)
+ {
+ builtins->glPosition.enable(userSemantic, reservedSemanticIndex++);
+ }
+
+ if (fragCoord)
+ {
+ builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++);
+ }
+
+ if (pointCoord)
+ {
+ // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
+ // In D3D11 we manually compute gl_PointCoord in the GS.
+ if (hlsl4)
+ {
+ builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++);
+ }
+ else
+ {
+ builtins->glPointCoord.enable("TEXCOORD", 0);
+ }
+ }
+
+ // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
+ if (pointSize && (shaderType != SHADER_PIXEL || hlsl4))
+ {
+ builtins->glPointSize.enableSystem("PSIZE");
+ }
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.h b/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.h
new file mode 100755
index 000000000..ca4640b00
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.h
@@ -0,0 +1,175 @@
+//
+// 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 in D3D
+// for linking between shader stages.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_
+#define LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_
+
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+class ProgramD3DMetadata;
+
+struct PackedVarying
+{
+ PackedVarying(const sh::ShaderVariable &varyingIn, sh::InterpolationType interpolationIn)
+ : varying(&varyingIn), vertexOnly(false), interpolation(interpolationIn)
+ {
+ }
+ PackedVarying(const sh::ShaderVariable &varyingIn,
+ sh::InterpolationType interpolationIn,
+ const std::string &parentStructNameIn)
+ : varying(&varyingIn),
+ vertexOnly(false),
+ interpolation(interpolationIn),
+ parentStructName(parentStructNameIn)
+ {
+ }
+
+ bool isStructField() const { return !parentStructName.empty(); }
+
+ const sh::ShaderVariable *varying;
+
+ // Transform feedback varyings can be only referenced in the VS.
+ bool vertexOnly;
+
+ // Cached so we can store sh::ShaderVariable to point to varying fields.
+ sh::InterpolationType interpolation;
+
+ // Struct name
+ std::string parentStructName;
+};
+
+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;
+ }
+
+ bool isStructField() const { return !structFieldName.empty(); }
+
+ // 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;
+
+ // Assigned after packing
+ unsigned int semanticIndex;
+
+ // Struct member this varying corresponds to.
+ std::string structFieldName;
+};
+
+class VaryingPacking final : angle::NonCopyable
+{
+ public:
+ VaryingPacking(GLuint maxVaryingVectors);
+
+ bool packVaryings(gl::InfoLog &infoLog,
+ const std::vector<PackedVarying> &packedVaryings,
+ const std::vector<std::string> &transformFeedbackVaryings);
+
+ 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());
+ }
+ unsigned int getRegisterCount() const;
+
+ void enableBuiltins(ShaderType shaderType, const ProgramD3DMetadata &programMetadata);
+
+ struct BuiltinVarying final : 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
+ {
+ BuiltinVarying dxPosition;
+ BuiltinVarying glPosition;
+ BuiltinVarying glFragCoord;
+ BuiltinVarying glPointCoord;
+ BuiltinVarying glPointSize;
+ };
+
+ const BuiltinInfo &builtins(ShaderType shaderType) const { return mBuiltinInfo[shaderType]; }
+
+ bool usesPointSize() const { return mBuiltinInfo[SHADER_VERTEX].glPointSize.enabled; }
+
+ private:
+ bool packVarying(const PackedVarying &packedVarying);
+ bool isFree(unsigned int registerRow,
+ unsigned int registerColumn,
+ unsigned int varyingRows,
+ unsigned int varyingColumns) const;
+ void insert(unsigned int registerRow,
+ unsigned int registerColumn,
+ const PackedVarying &packedVarying);
+
+ std::vector<Register> mRegisterMap;
+ std::vector<PackedVaryingRegister> mRegisterList;
+
+ std::vector<BuiltinInfo> mBuiltinInfo;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp b/gfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
new file mode 100755
index 000000000..ac31a865e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
@@ -0,0 +1,280 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/VertexAttribute.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();
+ }
+}
+
+unsigned int VertexBufferInterface::getSerial() const
+{
+ return mVertexBuffer->getSerial();
+}
+
+unsigned int VertexBufferInterface::getBufferSize() const
+{
+ return mVertexBuffer->getBufferSize();
+}
+
+gl::Error VertexBufferInterface::setBufferSize(unsigned int size)
+{
+ if (mVertexBuffer->getBufferSize() == 0)
+ {
+ return mVertexBuffer->initialize(size, mDynamic);
+ }
+
+ return mVertexBuffer->setBufferSize(size);
+}
+
+gl::ErrorOrResult<unsigned int> VertexBufferInterface::getSpaceRequired(
+ const gl::VertexAttribute &attrib,
+ GLsizei count,
+ GLsizei instances) const
+{
+ unsigned int spaceRequired = 0;
+ ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, count, instances), spaceRequired);
+
+ // Align to 16-byte boundary
+ unsigned int alignedSpaceRequired = roundUp(spaceRequired, 16u);
+
+ if (alignedSpaceRequired < spaceRequired)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Vertex buffer overflow in VertexBufferInterface::getSpaceRequired.");
+ }
+
+ return alignedSpaceRequired;
+}
+
+gl::Error VertexBufferInterface::discard()
+{
+ return mVertexBuffer->discard();
+}
+
+VertexBuffer *VertexBufferInterface::getVertexBuffer() const
+{
+ return mVertexBuffer;
+}
+
+// StreamingVertexBufferInterface Implementation
+StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory,
+ std::size_t initialSize)
+ : VertexBufferInterface(factory, true), mWritePosition(0), mReservedSpace(0)
+{
+ setBufferSize(static_cast<unsigned int>(initialSize));
+}
+
+StreamingVertexBufferInterface::~StreamingVertexBufferInterface()
+{
+}
+
+gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size)
+{
+ unsigned int curBufferSize = getBufferSize();
+ if (size > curBufferSize)
+ {
+ ANGLE_TRY(setBufferSize(std::max(size, 3 * curBufferSize / 2)));
+ mWritePosition = 0;
+ }
+ else if (mWritePosition + size > curBufferSize)
+ {
+ ANGLE_TRY(discard());
+ mWritePosition = 0;
+ }
+
+ return gl::NoError();
+}
+
+gl::Error StreamingVertexBufferInterface::storeDynamicAttribute(const gl::VertexAttribute &attrib,
+ GLenum currentValueType,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ unsigned int *outStreamOffset,
+ const uint8_t *sourceData)
+{
+ unsigned int spaceRequired = 0;
+ ANGLE_TRY_RESULT(getSpaceRequired(attrib, count, instances), spaceRequired);
+
+ // Protect against integer overflow
+ angle::CheckedNumeric<unsigned int> checkedPosition(mWritePosition);
+ checkedPosition += spaceRequired;
+ if (!checkedPosition.IsValid())
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal error, new vertex buffer write position would overflow.");
+ }
+
+ ANGLE_TRY(reserveSpace(mReservedSpace));
+ mReservedSpace = 0;
+
+ ANGLE_TRY(mVertexBuffer->storeVertexAttributes(attrib, currentValueType, start, count,
+ instances, mWritePosition, sourceData));
+
+ if (outStreamOffset)
+ {
+ *outStreamOffset = mWritePosition;
+ }
+
+ mWritePosition += spaceRequired;
+
+ return gl::NoError();
+}
+
+gl::Error StreamingVertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib,
+ GLsizei count,
+ GLsizei instances)
+{
+ unsigned int requiredSpace = 0;
+ ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, count, instances), requiredSpace);
+
+ // Align to 16-byte boundary
+ auto alignedRequiredSpace = rx::CheckedRoundUp(requiredSpace, 16u);
+ alignedRequiredSpace += mReservedSpace;
+
+ // Protect against integer overflow
+ if (!alignedRequiredSpace.IsValid())
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Unable to reserve %u extra bytes in internal vertex buffer, "
+ "it would result in an overflow.",
+ requiredSpace);
+ }
+
+ mReservedSpace = alignedRequiredSpace.ValueOrDie();
+
+ return gl::NoError();
+}
+
+// StaticVertexBufferInterface Implementation
+StaticVertexBufferInterface::AttributeSignature::AttributeSignature()
+ : type(GL_NONE), size(0), stride(0), normalized(false), pureInteger(false), offset(0)
+{
+}
+
+bool StaticVertexBufferInterface::AttributeSignature::matchesAttribute(
+ const gl::VertexAttribute &attrib) const
+{
+ size_t attribStride = ComputeVertexAttributeStride(attrib);
+
+ if (type != attrib.type || size != attrib.size || static_cast<GLuint>(stride) != attribStride ||
+ normalized != attrib.normalized || pureInteger != attrib.pureInteger)
+ {
+ return false;
+ }
+
+ size_t attribOffset = (static_cast<size_t>(attrib.offset) % attribStride);
+ return (offset == attribOffset);
+}
+
+void StaticVertexBufferInterface::AttributeSignature::set(const gl::VertexAttribute &attrib)
+{
+ type = attrib.type;
+ size = attrib.size;
+ normalized = attrib.normalized;
+ pureInteger = attrib.pureInteger;
+ offset = stride = static_cast<GLuint>(ComputeVertexAttributeStride(attrib));
+ offset = static_cast<size_t>(attrib.offset) % ComputeVertexAttributeStride(attrib);
+}
+
+StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory)
+ : VertexBufferInterface(factory, false)
+{
+}
+
+StaticVertexBufferInterface::~StaticVertexBufferInterface()
+{
+}
+
+bool StaticVertexBufferInterface::matchesAttribute(const gl::VertexAttribute &attrib) const
+{
+ return mSignature.matchesAttribute(attrib);
+}
+
+void StaticVertexBufferInterface::setAttribute(const gl::VertexAttribute &attrib)
+{
+ return mSignature.set(attrib);
+}
+
+gl::Error StaticVertexBufferInterface::storeStaticAttribute(const gl::VertexAttribute &attrib,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ const uint8_t *sourceData)
+{
+ unsigned int spaceRequired = 0;
+ ANGLE_TRY_RESULT(getSpaceRequired(attrib, count, instances), spaceRequired);
+ setBufferSize(spaceRequired);
+
+ ASSERT(attrib.enabled);
+ ANGLE_TRY(mVertexBuffer->storeVertexAttributes(attrib, GL_NONE, start, count, instances, 0,
+ sourceData));
+
+ mSignature.set(attrib);
+ mVertexBuffer->hintUnmapResource();
+ return gl::NoError();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.h b/gfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
new file mode 100755
index 000000000..b3d98247f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
@@ -0,0 +1,159 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/angleutils.h"
+#include "libANGLE/Error.h"
+
+#include <GLES2/gl2.h>
+
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+namespace gl
+{
+struct VertexAttribute;
+struct VertexAttribCurrentValueData;
+}
+
+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 gl::Error initialize(unsigned int size, bool dynamicUsage) = 0;
+
+ virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib,
+ GLenum currentValueType,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ unsigned int offset,
+ const uint8_t *sourceData) = 0;
+
+ virtual unsigned int getBufferSize() const = 0;
+ virtual gl::Error setBufferSize(unsigned int size) = 0;
+ virtual gl::Error discard() = 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:
+ gl::Error discard();
+
+ gl::Error setBufferSize(unsigned int size);
+ gl::ErrorOrResult<unsigned int> getSpaceRequired(const gl::VertexAttribute &attrib,
+ GLsizei count,
+ GLsizei instances) const;
+ BufferFactoryD3D *const mFactory;
+ VertexBuffer *mVertexBuffer;
+ bool mDynamic;
+};
+
+class StreamingVertexBufferInterface : public VertexBufferInterface
+{
+ public:
+ StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize);
+ ~StreamingVertexBufferInterface();
+
+ gl::Error storeDynamicAttribute(const gl::VertexAttribute &attrib,
+ GLenum currentValueType,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ unsigned int *outStreamOffset,
+ const uint8_t *sourceData);
+
+ gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute,
+ GLsizei count,
+ GLsizei instances);
+
+ private:
+ gl::Error reserveSpace(unsigned int size);
+
+ unsigned int mWritePosition;
+ unsigned int mReservedSpace;
+};
+
+class StaticVertexBufferInterface : public VertexBufferInterface
+{
+ public:
+ explicit StaticVertexBufferInterface(BufferFactoryD3D *factory);
+ ~StaticVertexBufferInterface();
+
+ gl::Error storeStaticAttribute(const gl::VertexAttribute &attrib,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ const uint8_t *sourceData);
+
+ bool matchesAttribute(const gl::VertexAttribute &attribute) const;
+ void setAttribute(const gl::VertexAttribute &attribute);
+
+ private:
+ class AttributeSignature final : angle::NonCopyable
+ {
+ public:
+ AttributeSignature();
+ bool matchesAttribute(const gl::VertexAttribute &attrib) const;
+ void set(const gl::VertexAttribute &attrib);
+
+ private:
+ GLenum type;
+ GLuint size;
+ GLuint stride;
+ bool normalized;
+ bool pureInteger;
+ size_t offset;
+ };
+
+ AttributeSignature mSignature;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/gfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
new file mode 100755
index 000000000..89dd4faf2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
@@ -0,0 +1,589 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+
+#include "common/BitSetIterator.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.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
+};
+
+int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size)
+{
+ // Size cannot be larger than a GLsizei
+ if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
+ {
+ size = static_cast<unsigned int>(std::numeric_limits<int>::max());
+ }
+
+ GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib));
+ return (size - attrib.offset % stride +
+ (stride - static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)))) /
+ stride;
+}
+
+bool DirectStoragePossible(const gl::VertexAttribute &attrib)
+{
+ // Current value attribs may not use direct storage.
+ if (!attrib.enabled)
+ {
+ return false;
+ }
+
+ gl::Buffer *buffer = attrib.buffer.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;
+
+ if (attrib.type != GL_FLOAT)
+ {
+ gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
+
+ // TODO(jmadill): add VertexFormatCaps
+ BufferFactoryD3D *factory = bufferD3D->getFactory();
+
+ auto errorOrElementSize = factory->getVertexSpaceRequired(attrib, 1, 0);
+ if (errorOrElementSize.isError())
+ {
+ ERR("Unlogged error in DirectStoragePossible.");
+ return false;
+ }
+
+ alignment = std::min<size_t>(errorOrElementSize.getResult(), 4);
+
+ // CPU-converted vertex data must be converted (naturally).
+ if ((factory->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_CPU) != 0)
+ {
+ return false;
+ }
+ }
+
+ // Final alignment check - unaligned data must be converted.
+ return (static_cast<size_t>(ComputeVertexAttributeStride(attrib)) % alignment == 0) &&
+ (static_cast<size_t>(attrib.offset) % alignment == 0);
+}
+} // anonymous namespace
+
+TranslatedAttribute::TranslatedAttribute()
+ : active(false),
+ attribute(nullptr),
+ currentValueType(GL_NONE),
+ baseOffset(0),
+ usesFirstVertexOffset(false),
+ stride(0),
+ vertexBuffer(),
+ storage(nullptr),
+ serial(0),
+ divisor(0)
+{
+}
+
+gl::ErrorOrResult<unsigned int> TranslatedAttribute::computeOffset(GLint startVertex) const
+{
+ if (!usesFirstVertexOffset)
+ {
+ return baseOffset;
+ }
+
+ CheckedNumeric<unsigned int> offset;
+
+ offset = baseOffset + stride * static_cast<unsigned int>(startVertex);
+ ANGLE_TRY_CHECKED_MATH(offset);
+ return offset.ValueOrDie();
+}
+
+VertexStorageType ClassifyAttributeStorage(const gl::VertexAttribute &attrib)
+{
+ // 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.
+ auto *buffer = attrib.buffer.get();
+ if (!buffer)
+ {
+ return VertexStorageType::DYNAMIC;
+ }
+
+ // Check if the buffer supports direct storage.
+ if (DirectStoragePossible(attrib))
+ {
+ 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()
+ : buffer(nullptr),
+ offset(0)
+{
+ data.FloatValues[0] = std::numeric_limits<float>::quiet_NaN();
+ data.FloatValues[1] = std::numeric_limits<float>::quiet_NaN();
+ data.FloatValues[2] = std::numeric_limits<float>::quiet_NaN();
+ data.FloatValues[3] = std::numeric_limits<float>::quiet_NaN();
+ data.Type = GL_FLOAT;
+}
+
+VertexDataManager::CurrentValueState::~CurrentValueState()
+{
+ SafeDelete(buffer);
+}
+
+VertexDataManager::VertexDataManager(BufferFactoryD3D *factory)
+ : mFactory(factory),
+ mStreamingBuffer(nullptr),
+ // TODO(jmadill): use context caps
+ mCurrentValueCache(gl::MAX_VERTEX_ATTRIBS)
+{
+ mStreamingBuffer = new StreamingVertexBufferInterface(factory, INITIAL_STREAM_BUFFER_SIZE);
+
+ if (!mStreamingBuffer)
+ {
+ ERR("Failed to allocate the streaming vertex buffer.");
+ }
+}
+
+VertexDataManager::~VertexDataManager()
+{
+ SafeDelete(mStreamingBuffer);
+}
+
+gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
+ GLint start,
+ GLsizei count,
+ std::vector<TranslatedAttribute> *translatedAttribs,
+ GLsizei instances)
+{
+ ASSERT(mStreamingBuffer);
+
+ const gl::VertexArray *vertexArray = state.getVertexArray();
+ const auto &vertexAttributes = vertexArray->getVertexAttributes();
+
+ mDynamicAttribsMaskCache.reset();
+ const gl::Program *program = state.getProgram();
+
+ translatedAttribs->clear();
+
+ for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
+ {
+ // Skip attrib locations the program doesn't use.
+ if (!program->isAttribLocationActive(attribIndex))
+ continue;
+
+ const auto &attrib = vertexAttributes[attribIndex];
+
+ // Resize automatically puts in empty attribs
+ translatedAttribs->resize(attribIndex + 1);
+
+ TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];
+ auto currentValueData =
+ state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
+
+ // Record the attribute now
+ translated->active = true;
+ translated->attribute = &attrib;
+ translated->currentValueType = currentValueData.Type;
+ translated->divisor = attrib.divisor;
+
+ switch (ClassifyAttributeStorage(attrib))
+ {
+ case VertexStorageType::STATIC:
+ {
+ // Store static attribute.
+ ANGLE_TRY(StoreStaticAttrib(translated, count, instances));
+ break;
+ }
+ case VertexStorageType::DYNAMIC:
+ // Dynamic attributes must be handled together.
+ mDynamicAttribsMaskCache.set(attribIndex);
+ break;
+ case VertexStorageType::DIRECT:
+ // Update translated data for direct attributes.
+ StoreDirectAttrib(translated);
+ break;
+ case VertexStorageType::CURRENT_VALUE:
+ {
+ ANGLE_TRY(storeCurrentValue(currentValueData, translated, attribIndex));
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+
+ if (mDynamicAttribsMaskCache.none())
+ {
+ return gl::NoError();
+ }
+
+ ANGLE_TRY(
+ storeDynamicAttribs(translatedAttribs, mDynamicAttribsMaskCache, start, count, instances));
+
+ PromoteDynamicAttribs(*translatedAttribs, mDynamicAttribsMaskCache, count);
+
+ return gl::NoError();
+}
+
+// static
+void VertexDataManager::StoreDirectAttrib(TranslatedAttribute *directAttrib)
+{
+ const auto &attrib = *directAttrib->attribute;
+ gl::Buffer *buffer = attrib.buffer.get();
+ BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
+
+ ASSERT(DirectStoragePossible(attrib));
+ directAttrib->vertexBuffer.set(nullptr);
+ directAttrib->storage = bufferD3D;
+ directAttrib->serial = bufferD3D->getSerial();
+ directAttrib->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib));
+ directAttrib->baseOffset = static_cast<unsigned int>(attrib.offset);
+
+ // Instanced vertices do not apply the 'start' offset
+ directAttrib->usesFirstVertexOffset = (attrib.divisor == 0);
+}
+
+// static
+gl::Error VertexDataManager::StoreStaticAttrib(TranslatedAttribute *translated,
+ GLsizei count,
+ GLsizei instances)
+{
+ const gl::VertexAttribute &attrib = *translated->attribute;
+
+ gl::Buffer *buffer = attrib.buffer.get();
+ ASSERT(buffer && attrib.enabled && !DirectStoragePossible(attrib));
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+
+ // Compute source data pointer
+ const uint8_t *sourceData = nullptr;
+
+ ANGLE_TRY(bufferD3D->getData(&sourceData));
+ sourceData += static_cast<int>(attrib.offset);
+
+ unsigned int streamOffset = 0;
+
+ translated->storage = nullptr;
+ ANGLE_TRY_RESULT(bufferD3D->getFactory()->getVertexSpaceRequired(attrib, 1, 0),
+ translated->stride);
+
+ auto *staticBuffer = bufferD3D->getStaticVertexBuffer(attrib);
+ ASSERT(staticBuffer);
+
+ if (staticBuffer->empty())
+ {
+ // Convert the entire buffer
+ int totalCount = ElementsInBuffer(attrib, static_cast<unsigned int>(bufferD3D->getSize()));
+ int startIndex = static_cast<int>(attrib.offset) /
+ static_cast<int>(ComputeVertexAttributeStride(attrib));
+
+ ANGLE_TRY(
+ staticBuffer->storeStaticAttribute(attrib, -startIndex, totalCount, 0, sourceData));
+ }
+
+ unsigned int firstElementOffset =
+ (static_cast<unsigned int>(attrib.offset) /
+ static_cast<unsigned int>(ComputeVertexAttributeStride(attrib))) *
+ translated->stride;
+
+ VertexBuffer *vertexBuffer = staticBuffer->getVertexBuffer();
+
+ CheckedNumeric<unsigned int> checkedOffset(streamOffset);
+ checkedOffset += firstElementOffset;
+
+ if (!checkedOffset.IsValid())
+ {
+ return gl::Error(GL_INVALID_OPERATION,
+ "Integer overflow in VertexDataManager::StoreStaticAttrib");
+ }
+
+ translated->vertexBuffer.set(vertexBuffer);
+ translated->serial = vertexBuffer->getSerial();
+ translated->baseOffset = streamOffset + firstElementOffset;
+
+ // Instanced vertices do not apply the 'start' offset
+ translated->usesFirstVertexOffset = (attrib.divisor == 0);
+
+ return gl::NoError();
+}
+
+gl::Error VertexDataManager::storeDynamicAttribs(
+ std::vector<TranslatedAttribute> *translatedAttribs,
+ const gl::AttributesMask &dynamicAttribsMask,
+ GLint start,
+ GLsizei count,
+ GLsizei instances)
+{
+ // 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 : IterateBitSet(dynamicAttribsMask))
+ {
+ const auto &dynamicAttrib = (*translatedAttribs)[attribIndex];
+ ANGLE_TRY(reserveSpaceForAttrib(dynamicAttrib, count, instances));
+ }
+
+ // Store dynamic attributes
+ for (auto attribIndex : IterateBitSet(dynamicAttribsMask))
+ {
+ auto *dynamicAttrib = &(*translatedAttribs)[attribIndex];
+ ANGLE_TRY(storeDynamicAttrib(dynamicAttrib, start, count, instances));
+ }
+
+ return gl::NoError();
+}
+
+void VertexDataManager::PromoteDynamicAttribs(
+ const std::vector<TranslatedAttribute> &translatedAttribs,
+ const gl::AttributesMask &dynamicAttribsMask,
+ GLsizei count)
+{
+ for (auto attribIndex : IterateBitSet(dynamicAttribsMask))
+ {
+ const auto &dynamicAttrib = translatedAttribs[attribIndex];
+ gl::Buffer *buffer = dynamicAttrib.attribute->buffer.get();
+ if (buffer)
+ {
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+ size_t typeSize = ComputeVertexAttributeTypeSize(*dynamicAttrib.attribute);
+ bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize));
+ }
+ }
+}
+
+gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
+ GLsizei count,
+ GLsizei instances) const
+{
+ const gl::VertexAttribute &attrib = *translatedAttrib.attribute;
+ ASSERT(!DirectStoragePossible(attrib));
+
+ gl::Buffer *buffer = attrib.buffer.get();
+ BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
+ ASSERT(!bufferD3D || bufferD3D->getStaticVertexBuffer(attrib) == nullptr);
+
+ size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
+ ASSERT(!bufferD3D ||
+ ElementsInBuffer(attrib, static_cast<unsigned int>(bufferD3D->getSize())) >=
+ static_cast<int>(totalCount));
+
+ return mStreamingBuffer->reserveVertexSpace(attrib, static_cast<GLsizei>(totalCount),
+ instances);
+}
+
+gl::Error VertexDataManager::storeDynamicAttrib(TranslatedAttribute *translated,
+ GLint start,
+ GLsizei count,
+ GLsizei instances)
+{
+ const gl::VertexAttribute &attrib = *translated->attribute;
+
+ gl::Buffer *buffer = attrib.buffer.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 = (attrib.divisor > 0 ? 0 : start);
+
+ // Compute source data pointer
+ const uint8_t *sourceData = nullptr;
+
+ if (buffer)
+ {
+ ANGLE_TRY(storage->getData(&sourceData));
+ sourceData += static_cast<int>(attrib.offset);
+ }
+ else
+ {
+ sourceData = static_cast<const uint8_t*>(attrib.pointer);
+ }
+
+ unsigned int streamOffset = 0;
+
+ translated->storage = nullptr;
+ ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, 1, 0), translated->stride);
+
+ size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
+
+ ANGLE_TRY(mStreamingBuffer->storeDynamicAttribute(
+ attrib, translated->currentValueType, firstVertexIndex, static_cast<GLsizei>(totalCount),
+ instances, &streamOffset, sourceData));
+
+ VertexBuffer *vertexBuffer = mStreamingBuffer->getVertexBuffer();
+
+ translated->vertexBuffer.set(vertexBuffer);
+ translated->serial = vertexBuffer->getSerial();
+ translated->baseOffset = streamOffset;
+ translated->usesFirstVertexOffset = false;
+
+ return gl::NoError();
+}
+
+gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribCurrentValueData &currentValue,
+ TranslatedAttribute *translated,
+ size_t attribIndex)
+{
+ CurrentValueState *cachedState = &mCurrentValueCache[attribIndex];
+ auto *&buffer = cachedState->buffer;
+
+ if (!buffer)
+ {
+ buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE);
+ }
+
+ if (cachedState->data != currentValue)
+ {
+ const gl::VertexAttribute &attrib = *translated->attribute;
+
+ ANGLE_TRY(buffer->reserveVertexSpace(attrib, 1, 0));
+
+ const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
+ unsigned int streamOffset;
+ ANGLE_TRY(buffer->storeDynamicAttribute(attrib, currentValue.Type, 0, 1, 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 gl::NoError();
+}
+
+// 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/src/libANGLE/renderer/d3d/VertexDataManager.h b/gfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.h
new file mode 100755
index 000000000..da46c7a87
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/VertexDataManager.h
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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/angletypes.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/VertexAttribute.h"
+
+namespace gl
+{
+class State;
+struct VertexAttribute;
+struct VertexAttribCurrentValueData;
+}
+
+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();
+
+ // Computes the correct offset from baseOffset, usesFirstVertexOffset, stride and startVertex.
+ // Can throw an error on integer overflow.
+ gl::ErrorOrResult<unsigned int> computeOffset(GLint startVertex) const;
+
+ bool active;
+
+ const gl::VertexAttribute *attribute;
+ GLenum 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::VertexAttribute &attrib);
+
+class VertexDataManager : angle::NonCopyable
+{
+ public:
+ VertexDataManager(BufferFactoryD3D *factory);
+ virtual ~VertexDataManager();
+
+ gl::Error prepareVertexData(const gl::State &state,
+ GLint start,
+ GLsizei count,
+ std::vector<TranslatedAttribute> *translatedAttribs,
+ GLsizei instances);
+
+ static void StoreDirectAttrib(TranslatedAttribute *directAttrib);
+
+ static gl::Error StoreStaticAttrib(TranslatedAttribute *translated,
+ GLsizei count,
+ GLsizei instances);
+
+ gl::Error storeDynamicAttribs(std::vector<TranslatedAttribute> *translatedAttribs,
+ const gl::AttributesMask &dynamicAttribsMask,
+ GLint start,
+ GLsizei count,
+ GLsizei instances);
+
+ // Promote static usage of dynamic buffers.
+ static void PromoteDynamicAttribs(const std::vector<TranslatedAttribute> &translatedAttribs,
+ const gl::AttributesMask &dynamicAttribsMask,
+ GLsizei count);
+
+ gl::Error storeCurrentValue(const gl::VertexAttribCurrentValueData &currentValue,
+ TranslatedAttribute *translated,
+ size_t attribIndex);
+
+ private:
+ struct CurrentValueState
+ {
+ CurrentValueState();
+ ~CurrentValueState();
+
+ StreamingVertexBufferInterface *buffer;
+ gl::VertexAttribCurrentValueData data;
+ size_t offset;
+ };
+
+ gl::Error reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
+ GLsizei count,
+ GLsizei instances) const;
+
+ gl::Error storeDynamicAttrib(TranslatedAttribute *translated,
+ GLint start,
+ GLsizei count,
+ GLsizei instances);
+
+ 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/src/libANGLE/renderer/d3d/WorkaroundsD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h
new file mode 100755
index 000000000..ede929ce8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h
@@ -0,0 +1,111 @@
+//
+// Copyright (c) 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.
+//
+
+// WorkaroundsD3D.h: Workarounds for D3D driver bugs and other issues.
+
+#ifndef LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_
+#define LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_
+
+// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate
+// independent of ANGLE's renderer. Workarounds should also be accessible
+// outside of the Renderer.
+
+namespace rx
+{
+struct D3DCompilerWorkarounds
+{
+ bool skipOptimization = false;
+ bool useMaxOptimization = false;
+
+ // IEEE strictness needs to be enabled for NANs to work.
+ bool enableIEEEStrictness = false;
+};
+
+struct WorkaroundsD3D
+{
+ // On some systems, having extra rendertargets than necessary slows down the shader.
+ // We can fix this by optimizing those out of the shader. At the same time, we can
+ // work around a bug on some nVidia drivers that they ignore "null" render targets
+ // in D3D11, by compacting the active color attachments list to omit null entries.
+ bool mrtPerfWorkaround = false;
+
+ bool setDataFasterThanImageUpload = false;
+
+ // Some renderers can't disable mipmaps on a mipmapped texture (i.e. solely sample from level
+ // zero, and ignore the other levels). D3D11 Feature Level 10+ does this by setting MaxLOD to
+ // 0.0f in the Sampler state. D3D9 sets D3DSAMP_MIPFILTER to D3DTEXF_NONE. There is no
+ // equivalent to this in D3D11 Feature Level 9_3. This causes problems when (for example) an
+ // application creates a mipmapped texture2D, but sets GL_TEXTURE_MIN_FILTER to GL_NEAREST
+ // (i.e disables mipmaps). To work around this, D3D11 FL9_3 has to create two copies of the
+ // texture. The textures' level zeros are identical, but only one texture has mips.
+ bool zeroMaxLodWorkaround = false;
+
+ // Some renderers do not support Geometry Shaders so the Geometry Shader-based PointSprite
+ // emulation will not work. To work around this, D3D11 FL9_3 has to use a different pointsprite
+ // emulation that is implemented using instanced quads.
+ bool useInstancedPointSpriteEmulation = false;
+
+ // A bug fixed in NVIDIA driver version 347.88 < x <= 368.81 triggers a TDR when using
+ // CopySubresourceRegion from a staging texture to a depth/stencil in D3D11. The workaround
+ // is to use UpdateSubresource to trigger an extra copy. We disable this workaround on newer
+ // NVIDIA driver versions because of a second driver bug present with the workaround enabled.
+ // (See: http://anglebug.com/1452)
+ bool depthStencilBlitExtraCopy = false;
+
+ // The HLSL optimizer has a bug with optimizing "pow" in certain integer-valued expressions.
+ // We can work around this by expanding the pow into a series of multiplies if we're running
+ // under the affected compiler.
+ bool expandIntegerPowExpressions = false;
+
+ // NVIDIA drivers sometimes write out-of-order results to StreamOut buffers when transform
+ // feedback is used to repeatedly write to the same buffer positions.
+ bool flushAfterEndingTransformFeedback = false;
+
+ // Some drivers (NVIDIA) do not take into account the base level of the texture in the results
+ // of the HLSL GetDimensions builtin.
+ bool getDimensionsIgnoresBaseLevel = false;
+
+ // On some Intel drivers, HLSL's function texture.Load returns 0 when the parameter Location
+ // is negative, even if the sum of Offset and Location is in range. This may cause errors when
+ // translating GLSL's function texelFetchOffset into texture.Load, as it is valid for
+ // texelFetchOffset to use negative texture coordinates as its parameter P when the sum of P
+ // and Offset is in range. To work around this, we translate texelFetchOffset into texelFetch
+ // by adding Offset directly to Location before reading the texture.
+ bool preAddTexelFetchOffsets = false;
+
+ // On some AMD drivers, 1x1 and 2x2 mips of depth/stencil textures aren't sampled correctly.
+ // We can work around this bug by doing an internal blit to a temporary single-channel texture
+ // before we sample.
+ bool emulateTinyStencilTextures = false;
+
+ // In Intel driver, the data with format DXGI_FORMAT_B5G6R5_UNORM will be parsed incorrectly.
+ // This workaroud will disable B5G6R5 support when it's Intel driver. By default, it will use
+ // R8G8B8A8 format.
+ bool disableB5G6R5Support = false;
+
+ // On some Intel drivers, evaluating unary minus operator on integer may get wrong answer in
+ // vertex shaders. To work around this bug, we translate -(int) into ~(int)+1.
+ bool rewriteUnaryMinusOperator = false;
+
+ // On some Intel drivers, using isnan() on highp float will get wrong answer. To work around
+ // this bug, we use an expression to emulate function isnan(). Tracking bug:
+ // https://crbug.com/650547
+ bool emulateIsnanFloat = false;
+
+ // On some Intel drivers, using clear() may not take effect. To work around this bug, we call
+ // clear() twice on these platforms. Tracking bug: https://crbug.com/655534
+ bool callClearTwice = false;
+
+ // On some Intel drivers, copying from staging storage to constant buffer storage does not
+ // seem to work. Work around this by keeping system memory storage as a canonical reference
+ // for buffer data.
+ // D3D11-only workaround. See http://crbug.com/593024.
+ bool useSystemMemoryForConstantBuffers = false;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
new file mode 100755
index 000000000..f8a0ac597
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
@@ -0,0 +1,2250 @@
+//
+// Copyright (c) 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 "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "third_party/trace_event/trace_event.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/passthroughrgba2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.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/passthroughrgb2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.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/passthroughrg2d11ps.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/passthroughr2d11ps.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/passthroughlum2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.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/passthroughrgb3d11ps.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/passthroughrg3d11ps.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/passthroughr3d11ps.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/passthroughlum3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.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/swizzlef2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.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 * destArea.width;
+ size_t srcOffset = sourceArea.x * pixelSize;
+ size_t destOffset = destArea.x * pixelSize;
+
+ for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++)
+ {
+ 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.height - 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);
+ gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea);
+
+ // 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
+
+Blit11::Blit11(Renderer11 *renderer)
+ : mRenderer(renderer),
+ mResourcesInitialized(false),
+ mVertexBuffer(nullptr),
+ mPointSampler(nullptr),
+ mLinearSampler(nullptr),
+ mScissorEnabledRasterizerState(nullptr),
+ mScissorDisabledRasterizerState(nullptr),
+ mDepthStencilState(nullptr),
+ 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(nullptr),
+ 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(nullptr),
+ mResolvedDepthStencilRTView(nullptr)
+{
+}
+
+Blit11::~Blit11()
+{
+ freeResources();
+
+ mQuad2DIL.release();
+ mQuad2DVS.release();
+ mDepthPS.release();
+
+ mQuad3DIL.release();
+ mQuad3DVS.release();
+ mQuad3DGS.release();
+
+ clearShaderMap();
+ releaseResolveDepthStencilResources();
+}
+
+gl::Error Blit11::initResources()
+{
+ if (mResourcesInitialized)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ TRACE_EVENT0("gpu.angle", "Blit11::initResources");
+
+ HRESULT result;
+ ID3D11Device *device = mRenderer->getDevice();
+
+ 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;
+
+ result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit vertex buffer, HRESULT: 0x%X",
+ result);
+ }
+ d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer");
+
+ 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;
+
+ result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create blit point sampler state, HRESULT: 0x%X", result);
+ }
+ d3d11::SetDebugName(mPointSampler, "Blit11 point sampler");
+
+ 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;
+
+ result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create blit linear sampler state, HRESULT: 0x%X", result);
+ }
+ d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler");
+
+ // 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;
+ result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create blit scissoring rasterizer state, HRESULT: 0x%X",
+ result);
+ }
+ d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state");
+
+ rasterDesc.ScissorEnable = FALSE;
+ result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create blit no scissoring rasterizer state, HRESULT: 0x%X",
+ result);
+ }
+ d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state");
+
+ 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;
+
+ result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create blit depth stencil state, HRESULT: 0x%X", result);
+ }
+ d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state");
+
+ 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;
+
+ result = device->CreateBuffer(&swizzleBufferDesc, nullptr, &mSwizzleCB);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit swizzle buffer, HRESULT: 0x%X",
+ result);
+ }
+ d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer");
+
+ mResourcesInitialized = true;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Blit11::freeResources()
+{
+ SafeRelease(mVertexBuffer);
+ SafeRelease(mPointSampler);
+ SafeRelease(mLinearSampler);
+ SafeRelease(mScissorEnabledRasterizerState);
+ SafeRelease(mScissorDisabledRasterizerState);
+ SafeRelease(mDepthStencilState);
+ SafeRelease(mSwizzleCB);
+
+ mResourcesInitialized = false;
+}
+
+// static
+Blit11::BlitShaderType Blit11::GetBlitShaderType(GLenum destinationFormat,
+ bool isSigned,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ ShaderDimension dimension)
+{
+ if (dimension == SHADER_3D)
+ {
+ ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha);
+
+ if (isSigned)
+ {
+ switch (destinationFormat)
+ {
+ case GL_RGBA_INTEGER:
+ return BLITSHADER_3D_RGBAI;
+ case GL_RGB_INTEGER:
+ return BLITSHADER_3D_RGBI;
+ case GL_RG_INTEGER:
+ return BLITSHADER_3D_RGI;
+ case GL_RED_INTEGER:
+ return BLITSHADER_3D_RI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ }
+ else
+ {
+ switch (destinationFormat)
+ {
+ case GL_RGBA:
+ return BLITSHADER_3D_RGBAF;
+ case GL_RGBA_INTEGER:
+ return BLITSHADER_3D_RGBAUI;
+ case GL_BGRA_EXT:
+ return BLITSHADER_3D_BGRAF;
+ case GL_RGB:
+ return BLITSHADER_3D_RGBF;
+ case GL_RGB_INTEGER:
+ return BLITSHADER_3D_RGBUI;
+ case GL_RG:
+ return BLITSHADER_3D_RGF;
+ case GL_RG_INTEGER:
+ return BLITSHADER_3D_RGUI;
+ case GL_RED:
+ return BLITSHADER_3D_RF;
+ case GL_RED_INTEGER:
+ return BLITSHADER_3D_RUI;
+ case GL_ALPHA:
+ return BLITSHADER_3D_ALPHA;
+ case GL_LUMINANCE:
+ return BLITSHADER_3D_LUMA;
+ case GL_LUMINANCE_ALPHA:
+ return BLITSHADER_3D_LUMAALPHA;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ }
+ }
+ else if (isSigned)
+ {
+ ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha);
+
+ switch (destinationFormat)
+ {
+ case GL_RGBA_INTEGER:
+ return BLITSHADER_2D_RGBAI;
+ case GL_RGB_INTEGER:
+ return BLITSHADER_2D_RGBI;
+ case GL_RG_INTEGER:
+ return BLITSHADER_2D_RGI;
+ case GL_RED_INTEGER:
+ return BLITSHADER_2D_RI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ }
+ else
+ {
+ if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha)
+ {
+ switch (destinationFormat)
+ {
+ case GL_RGBA:
+ return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBAF_PREMULTIPLY
+ : BLITSHADER_2D_RGBAF_UNMULTIPLY;
+ case GL_BGRA_EXT:
+ return unpackPremultiplyAlpha ? BLITSHADER_2D_BGRAF_PREMULTIPLY
+ : BLITSHADER_2D_BGRAF_UNMULTIPLY;
+ case GL_RGB:
+ return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBF_PREMULTIPLY
+ : BLITSHADER_2D_RGBF_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ }
+ else
+ {
+ switch (destinationFormat)
+ {
+ case GL_RGBA:
+ return BLITSHADER_2D_RGBAF;
+ case GL_RGBA_INTEGER:
+ return BLITSHADER_2D_RGBAUI;
+ case GL_BGRA_EXT:
+ return BLITSHADER_2D_BGRAF;
+ case GL_RGB:
+ return BLITSHADER_2D_RGBF;
+ case GL_RGB_INTEGER:
+ return BLITSHADER_2D_RGBUI;
+ case GL_RG:
+ return BLITSHADER_2D_RGF;
+ case GL_RG_INTEGER:
+ return BLITSHADER_2D_RGUI;
+ case GL_RED:
+ return BLITSHADER_2D_RF;
+ case GL_RED_INTEGER:
+ return BLITSHADER_2D_RUI;
+ case GL_ALPHA:
+ return BLITSHADER_2D_ALPHA;
+ case GL_LUMINANCE:
+ return BLITSHADER_2D_LUMA;
+ case GL_LUMINANCE_ALPHA:
+ return BLITSHADER_2D_LUMAALPHA;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ }
+ }
+}
+
+// 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;
+ }
+}
+
+Blit11::ShaderSupport Blit11::getShaderSupport(const Shader &shader)
+{
+ ID3D11Device *device = mRenderer->getDevice();
+ ShaderSupport support;
+
+ if (shader.dimension == SHADER_2D)
+ {
+ support.inputLayout = mQuad2DIL.resolve(device);
+ support.vertexShader = mQuad2DVS.resolve(device);
+ support.geometryShader = nullptr;
+ support.vertexWriteFunction = Write2DVertices;
+ }
+ else
+ {
+ ASSERT(shader.dimension == SHADER_3D);
+ support.inputLayout = mQuad3DIL.resolve(device);
+ support.vertexShader = mQuad3DVS.resolve(device);
+ support.geometryShader = mQuad3DGS.resolve(device);
+ support.vertexWriteFunction = Write3DVertices;
+ }
+
+ return support;
+}
+
+gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source,
+ ID3D11RenderTargetView *dest,
+ const gl::Extents &size,
+ const gl::SwizzleState &swizzleTarget)
+{
+ ANGLE_TRY(initResources());
+
+ HRESULT result;
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
+ source->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(shaderType, sourceSRVDesc.ViewDimension, &shader));
+
+ // Set vertices
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to map internal vertex buffer for swizzle, HRESULT: 0x%X.",
+ result);
+ }
+
+ const ShaderSupport &support = getShaderSupport(*shader);
+
+ UINT stride = 0;
+ UINT startIdx = 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, 0);
+
+ // Set constant buffer
+ result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to map internal constant buffer for swizzle, HRESULT: 0x%X.",
+ result);
+ }
+
+ unsigned int *swizzleIndices = reinterpret_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, 0);
+
+ // Apply vertex buffer
+ deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
+
+ // Apply constant buffer
+ deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB);
+
+ // Apply state
+ deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+ deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
+ deviceContext->RSSetState(mScissorDisabledRasterizerState);
+
+ // Apply shaders
+ deviceContext->IASetInputLayout(support.inputLayout);
+ deviceContext->IASetPrimitiveTopology(topology);
+ deviceContext->VSSetShader(support.vertexShader, nullptr, 0);
+
+ deviceContext->PSSetShader(shader->pixelShader, nullptr, 0);
+ deviceContext->GSSetShader(support.geometryShader, nullptr, 0);
+
+ // Unset the currently bound shader resource to avoid conflicts
+ auto stateManager = mRenderer->getStateManager();
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+ // Apply render target
+ stateManager->setOneTimeRenderTarget(dest, nullptr);
+
+ // Set the viewport
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = static_cast<FLOAT>(size.width);
+ viewport.Height = static_cast<FLOAT>(size.height);
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ deviceContext->RSSetViewports(1, &viewport);
+
+ // Apply textures
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
+
+ // Apply samplers
+ deviceContext->PSSetSamplers(0, 1, &mPointSampler);
+
+ // Draw the quad
+ deviceContext->Draw(drawCount, 0);
+
+ // Unbind textures and render targets and vertex buffer
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+ UINT zero = 0;
+ ID3D11Buffer *const nullBuffer = nullptr;
+ deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
+
+ mRenderer->markAllStateDirty();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ ID3D11RenderTargetView *dest,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ GLenum destFormat,
+ GLenum filter,
+ bool maskOffAlpha,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ ANGLE_TRY(initResources());
+
+ HRESULT result;
+ 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->GetDesc(&sourceSRVDesc);
+
+ GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
+
+ ASSERT(componentType != GL_NONE);
+ ASSERT(componentType != GL_SIGNED_NORMALIZED);
+ bool isSigned = (componentType == GL_INT);
+
+ ShaderDimension dimension =
+ (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D;
+
+ const Shader *shader = nullptr;
+ ANGLE_TRY(getBlitShader(destFormat, isSigned, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
+ dimension, &shader));
+
+ const ShaderSupport &support = getShaderSupport(*shader);
+
+ // Set vertices
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.",
+ result);
+ }
+
+ UINT stride = 0;
+ UINT startIdx = 0;
+ UINT drawCount = 0;
+ D3D11_PRIMITIVE_TOPOLOGY topology;
+
+ support.vertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
+ &stride, &drawCount, &topology);
+
+ deviceContext->Unmap(mVertexBuffer, 0);
+
+ // Apply vertex buffer
+ deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
+
+ // Apply state
+ if (maskOffAlpha)
+ {
+ ID3D11BlendState *blendState = mAlphaMaskBlendState.resolve(mRenderer->getDevice());
+ ASSERT(blendState);
+ deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFF);
+ }
+ else
+ {
+ deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+ }
+ deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
+
+ if (scissor)
+ {
+ D3D11_RECT scissorRect;
+ scissorRect.left = scissor->x;
+ scissorRect.right = scissor->x + scissor->width;
+ scissorRect.top = scissor->y;
+ scissorRect.bottom = scissor->y + scissor->height;
+
+ deviceContext->RSSetScissorRects(1, &scissorRect);
+ deviceContext->RSSetState(mScissorEnabledRasterizerState);
+ }
+ else
+ {
+ deviceContext->RSSetState(mScissorDisabledRasterizerState);
+ }
+
+ // Apply shaders
+ deviceContext->IASetInputLayout(support.inputLayout);
+ deviceContext->IASetPrimitiveTopology(topology);
+ deviceContext->VSSetShader(support.vertexShader, nullptr, 0);
+
+ deviceContext->PSSetShader(shader->pixelShader, nullptr, 0);
+ deviceContext->GSSetShader(support.geometryShader, nullptr, 0);
+
+ // Unset the currently bound shader resource to avoid conflicts
+ auto stateManager = mRenderer->getStateManager();
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+ // Apply render target
+ stateManager->setOneTimeRenderTarget(dest, nullptr);
+
+ // Set the viewport
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = static_cast<FLOAT>(destSize.width);
+ viewport.Height = static_cast<FLOAT>(destSize.height);
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ deviceContext->RSSetViewports(1, &viewport);
+
+ // Apply textures
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
+
+ // Apply samplers
+ ID3D11SamplerState *sampler = nullptr;
+ switch (filter)
+ {
+ case GL_NEAREST:
+ sampler = mPointSampler;
+ break;
+ case GL_LINEAR:
+ sampler = mLinearSampler;
+ break;
+
+ default:
+ UNREACHABLE();
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal error, unknown blit filter mode.");
+ }
+ deviceContext->PSSetSamplers(0, 1, &sampler);
+
+ // Draw the quad
+ deviceContext->Draw(drawCount, 0);
+
+ // Unbind textures and render targets and vertex buffer
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+ UINT zero = 0;
+ ID3D11Buffer *const nullBuffer = nullptr;
+ deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
+
+ mRenderer->markAllStateDirty();
+
+ return gl::NoError();
+}
+
+gl::Error Blit11::copyStencil(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(source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, true);
+}
+
+gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ ID3D11DepthStencilView *dest,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor)
+{
+ ANGLE_TRY(initResources());
+
+ HRESULT result;
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ // Set vertices
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.",
+ result);
+ }
+
+ UINT stride = 0;
+ UINT startIdx = 0;
+ UINT drawCount = 0;
+ D3D11_PRIMITIVE_TOPOLOGY topology;
+
+ Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride,
+ &drawCount, &topology);
+
+ deviceContext->Unmap(mVertexBuffer, 0);
+
+ // Apply vertex buffer
+ deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
+
+ // Apply state
+ deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+ deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF);
+
+ if (scissor)
+ {
+ D3D11_RECT scissorRect;
+ scissorRect.left = scissor->x;
+ scissorRect.right = scissor->x + scissor->width;
+ scissorRect.top = scissor->y;
+ scissorRect.bottom = scissor->y + scissor->height;
+
+ deviceContext->RSSetScissorRects(1, &scissorRect);
+ deviceContext->RSSetState(mScissorEnabledRasterizerState);
+ }
+ else
+ {
+ deviceContext->RSSetState(mScissorDisabledRasterizerState);
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11VertexShader *quad2DVS = mQuad2DVS.resolve(device);
+ if (quad2DVS == nullptr)
+ {
+ return gl::Error(GL_INVALID_OPERATION, "Error compiling internal 2D blit vertex shader");
+ }
+
+ // Apply shaders
+ deviceContext->IASetInputLayout(mQuad2DIL.resolve(device));
+ deviceContext->IASetPrimitiveTopology(topology);
+ deviceContext->VSSetShader(quad2DVS, nullptr, 0);
+
+ deviceContext->PSSetShader(mDepthPS.resolve(device), nullptr, 0);
+ deviceContext->GSSetShader(nullptr, nullptr, 0);
+
+ // Unset the currently bound shader resource to avoid conflicts
+ auto stateManager = mRenderer->getStateManager();
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+ // Apply render target
+ stateManager->setOneTimeRenderTarget(nullptr, dest);
+
+ // Set the viewport
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = static_cast<FLOAT>(destSize.width);
+ viewport.Height = static_cast<FLOAT>(destSize.height);
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ deviceContext->RSSetViewports(1, &viewport);
+
+ // Apply textures
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
+
+ // Apply samplers
+ deviceContext->PSSetSamplers(0, 1, &mPointSampler);
+
+ // Draw the quad
+ deviceContext->Draw(drawCount, 0);
+
+ // Unbind textures and render targets and vertex buffer
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+
+ UINT zero = 0;
+ ID3D11Buffer *const nullBuffer = nullptr;
+ deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
+
+ mRenderer->markAllStateDirty();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Blit11::copyDepthStencil(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(source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, false);
+}
+
+gl::Error Blit11::copyDepthStencilImpl(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(source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, copyOffset,
+ copyOffset, copySize, srcPixelSize, destPixelSize,
+ BlitD24S8ToD32F);
+ }
+ ASSERT(srcDXGIFormat == DXGI_FORMAT_R32G8X24_TYPELESS);
+ return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
+ copySize, srcPixelSize, destPixelSize, BlitD32FS8ToD32F);
+ }
+
+ return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, destSubresource,
+ destArea, destSize, scissor, copyOffset, copyOffset, copySize,
+ srcPixelSize, destPixelSize, StretchedBlitNearest);
+}
+
+gl::Error Blit11::copyAndConvertImpl(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());
+
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ TextureHelper11 sourceStaging;
+ ANGLE_TRY_RESULT(CreateStagingTexture(GL_TEXTURE_2D, source.getFormatSet(), sourceSize,
+ StagingAccess::READ, device),
+ sourceStaging);
+
+ deviceContext->CopySubresourceRegion(sourceStaging.getResource(), 0, 0, 0, 0,
+ source.getResource(), sourceSubresource, nullptr);
+
+ D3D11_MAPPED_SUBRESOURCE sourceMapping;
+ HRESULT result =
+ deviceContext->Map(sourceStaging.getResource(), 0, D3D11_MAP_READ, 0, &sourceMapping);
+ if (FAILED(result))
+ {
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Failed to map internal source staging texture for depth stencil blit, HRESULT: 0x%X.",
+ result);
+ }
+
+ D3D11_MAPPED_SUBRESOURCE destMapping;
+ result = deviceContext->Map(destStaging.getResource(), 0, D3D11_MAP_WRITE, 0, &destMapping);
+ if (FAILED(result))
+ {
+ deviceContext->Unmap(sourceStaging.getResource(), 0);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to map internal destination staging texture for depth stencil "
+ "blit, HRESULT: 0x%X.",
+ result);
+ }
+
+ // 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)
+ {
+ gl::ClipRectangle(clipRect, *scissor, &clipRect);
+ }
+
+ 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.getResource(), 0);
+ deviceContext->Unmap(destStaging.getResource(), 0);
+
+ return gl::NoError();
+}
+
+gl::Error Blit11::copyAndConvert(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());
+
+ ID3D11Device *device = mRenderer->getDevice();
+ 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_RESULT(CreateStagingTexture(GL_TEXTURE_2D, dest.getFormatSet(), destSize,
+ StagingAccess::READ_WRITE, device),
+ destStaging);
+
+ deviceContext->CopySubresourceRegion(destStaging.getResource(), 0, 0, 0, 0, dest.getResource(),
+ destSubresource, nullptr);
+
+ copyAndConvertImpl(source, sourceSubresource, sourceArea, sourceSize, destStaging, destArea,
+ destSize, scissor, readOffset, writeOffset, copySize, srcPixelStride,
+ destPixelStride, convertFunction);
+
+ // Work around timeouts/TDRs in older NVIDIA drivers.
+ if (mRenderer->getWorkarounds().depthStencilBlitExtraCopy)
+ {
+ D3D11_MAPPED_SUBRESOURCE mapped;
+ deviceContext->Map(destStaging.getResource(), 0, D3D11_MAP_READ, 0, &mapped);
+ deviceContext->UpdateSubresource(dest.getResource(), destSubresource, nullptr, mapped.pData,
+ mapped.RowPitch, mapped.DepthPitch);
+ deviceContext->Unmap(destStaging.getResource(), 0);
+ }
+ else
+ {
+ deviceContext->CopySubresourceRegion(dest.getResource(), destSubresource, 0, 0, 0,
+ destStaging.getResource(), 0, nullptr);
+ }
+
+ return gl::NoError();
+}
+
+void Blit11::addBlitShaderToMap(BlitShaderType blitShaderType,
+ ShaderDimension dimension,
+ ID3D11PixelShader *ps)
+{
+ ASSERT(mBlitShaderMap.find(blitShaderType) == mBlitShaderMap.end());
+ ASSERT(ps);
+
+ Shader shader;
+ shader.dimension = dimension;
+ shader.pixelShader = ps;
+
+ mBlitShaderMap[blitShaderType] = shader;
+}
+
+void Blit11::addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType,
+ ShaderDimension dimension,
+ ID3D11PixelShader *ps)
+{
+ ASSERT(mSwizzleShaderMap.find(swizzleShaderType) == mSwizzleShaderMap.end());
+ ASSERT(ps);
+
+ Shader shader;
+ shader.dimension = dimension;
+ shader.pixelShader = ps;
+
+ mSwizzleShaderMap[swizzleShaderType] = shader;
+}
+
+void Blit11::clearShaderMap()
+{
+ for (auto &blitShader : mBlitShaderMap)
+ {
+ SafeRelease(blitShader.second.pixelShader);
+ }
+ mBlitShaderMap.clear();
+
+ for (auto &swizzleShader : mSwizzleShaderMap)
+ {
+ SafeRelease(swizzleShader.second.pixelShader);
+ }
+ mSwizzleShaderMap.clear();
+}
+
+gl::Error Blit11::getBlitShader(GLenum destFormat,
+ bool isSigned,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ ShaderDimension dimension,
+ const Shader **shader)
+{
+ BlitShaderType blitShaderType = GetBlitShaderType(destFormat, isSigned, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha, dimension);
+
+ if (blitShaderType == BLITSHADER_INVALID)
+ {
+ return gl::Error(GL_INVALID_OPERATION, "Internal blit shader type mismatch");
+ }
+
+ auto blitShaderIt = mBlitShaderMap.find(blitShaderType);
+ if (blitShaderIt != mBlitShaderMap.end())
+ {
+ *shader = &blitShaderIt->second;
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ ASSERT(dimension == SHADER_2D || mRenderer->isES3Capable());
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ switch (blitShaderType)
+ {
+ case BLITSHADER_2D_RGBAF:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_PREMULTIPLY:
+ addBlitShaderToMap(blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBAPremultiply2D,
+ "Blit11 2D RGBA premultiply pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_UNMULTIPLY:
+ addBlitShaderToMap(blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBAUnmultiply2D,
+ "Blit11 2D RGBA unmultiply pixel shader"));
+ break;
+ case BLITSHADER_2D_BGRAF:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader"));
+ break;
+ case BLITSHADER_2D_BGRAF_PREMULTIPLY:
+ addBlitShaderToMap(blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBAPremultiply2D,
+ "Blit11 2D BGRA premultiply pixel shader"));
+ break;
+ case BLITSHADER_2D_BGRAF_UNMULTIPLY:
+ addBlitShaderToMap(blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBAUnmultiply2D,
+ "Blit11 2D BGRA unmultiply pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF_PREMULTIPLY:
+ addBlitShaderToMap(blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBPremultiply2D,
+ "Blit11 2D RGB premultiply pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF_UNMULTIPLY:
+ addBlitShaderToMap(blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBUnmultiply2D,
+ "Blit11 2D RGB unmultiply pixel shader"));
+ break;
+ case BLITSHADER_2D_RGF:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader"));
+ break;
+ case BLITSHADER_2D_RF:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader"));
+ break;
+ case BLITSHADER_2D_ALPHA:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMA:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMAALPHA:
+ addBlitShaderToMap(blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D,
+ "Blit11 2D luminance alpha pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAUI:
+ addBlitShaderToMap(blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI,
+ "Blit11 2D RGBA UI pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBUI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader"));
+ break;
+ case BLITSHADER_2D_RGUI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader"));
+ break;
+ case BLITSHADER_2D_RGI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader"));
+ break;
+ case BLITSHADER_2D_RUI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader"));
+ break;
+ case BLITSHADER_2D_RI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAUI:
+ addBlitShaderToMap(blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI,
+ "Blit11 3D UI RGBA pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader"));
+ break;
+ case BLITSHADER_3D_BGRAF:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBUI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader"));
+ break;
+ case BLITSHADER_3D_RGF:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader"));
+ break;
+ case BLITSHADER_3D_RGUI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader"));
+ break;
+ case BLITSHADER_3D_RGI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader"));
+ break;
+ case BLITSHADER_3D_RF:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader"));
+ break;
+ case BLITSHADER_3D_RUI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader"));
+ break;
+ case BLITSHADER_3D_RI:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader"));
+ break;
+ case BLITSHADER_3D_ALPHA:
+ addBlitShaderToMap(
+ blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader"));
+ break;
+ case BLITSHADER_3D_LUMA:
+ addBlitShaderToMap(blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughLum3D,
+ "Blit11 3D luminance pixel shader"));
+ break;
+ case BLITSHADER_3D_LUMAALPHA:
+ addBlitShaderToMap(blitShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D,
+ "Blit11 3D luminance alpha pixel shader"));
+ break;
+ default:
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION, "Internal error");
+ }
+
+ blitShaderIt = mBlitShaderMap.find(blitShaderType);
+ ASSERT(blitShaderIt != mBlitShaderMap.end());
+ *shader = &blitShaderIt->second;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Blit11::getSwizzleShader(GLenum type,
+ D3D11_SRV_DIMENSION viewDimension,
+ const Shader **shader)
+{
+ SwizzleShaderType swizzleShaderType = GetSwizzleShaderType(type, viewDimension);
+
+ if (swizzleShaderType == SWIZZLESHADER_INVALID)
+ {
+ return gl::Error(GL_INVALID_OPERATION, "Swizzle shader type not found");
+ }
+
+ auto swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
+ if (swizzleShaderIt != mSwizzleShaderMap.end())
+ {
+ *shader = &swizzleShaderIt->second;
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ // Swizzling shaders (OpenGL ES 3+)
+ ASSERT(mRenderer->isES3Capable());
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ switch (swizzleShaderType)
+ {
+ case SWIZZLESHADER_2D_FLOAT:
+ addSwizzleShaderToMap(
+ swizzleShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_2D_UINT:
+ addSwizzleShaderToMap(
+ swizzleShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_2D_INT:
+ addSwizzleShaderToMap(
+ swizzleShaderType, SHADER_2D,
+ d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_CUBE_FLOAT:
+ addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_SwizzleF2DArray,
+ "Blit11 2D Cube F swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_CUBE_UINT:
+ addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_SwizzleUI2DArray,
+ "Blit11 2D Cube UI swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_CUBE_INT:
+ addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_SwizzleI2DArray,
+ "Blit11 2D Cube I swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_3D_FLOAT:
+ addSwizzleShaderToMap(
+ swizzleShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_3D_UINT:
+ addSwizzleShaderToMap(
+ swizzleShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_3D_INT:
+ addSwizzleShaderToMap(
+ swizzleShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_ARRAY_FLOAT:
+ addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_SwizzleF2DArray,
+ "Blit11 2D Array F swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_ARRAY_UINT:
+ addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_SwizzleUI2DArray,
+ "Blit11 2D Array UI swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_ARRAY_INT:
+ addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ d3d11::CompilePS(device, g_PS_SwizzleI2DArray,
+ "Blit11 2D Array I swizzle pixel shader"));
+ break;
+ default:
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION, "Internal error");
+ }
+
+ swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
+ ASSERT(swizzleShaderIt != mSwizzleShaderMap.end());
+ *shader = &swizzleShaderIt->second;
+ return gl::NoError();
+}
+
+gl::ErrorOrResult<TextureHelper11> Blit11::resolveDepth(RenderTarget11 *depth)
+{
+ // Multisampled depth stencil SRVs are not available in feature level 10.0
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0)
+ {
+ return gl::Error(GL_INVALID_OPERATION,
+ "Resolving multisampled depth stencil textures is not supported in "
+ "feature level 10.0.");
+ }
+
+ const auto &extents = depth->getExtents();
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ ANGLE_TRY(initResolveDepthStencil(extents));
+
+ // Notify the Renderer that all state should be invalidated.
+ mRenderer->markAllStateDirty();
+
+ // Apply the necessary state changes to the D3D11 immediate device context.
+ context->IASetInputLayout(nullptr);
+ context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ context->VSSetShader(mResolveDepthStencilVS.resolve(device), nullptr, 0);
+ context->GSSetShader(nullptr, nullptr, 0);
+ context->RSSetState(nullptr);
+ context->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
+ context->OMSetRenderTargets(1, &mResolvedDepthStencilRTView, nullptr);
+ context->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+
+ // Set the viewport
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = static_cast<FLOAT>(extents.width);
+ viewport.Height = static_cast<FLOAT>(extents.height);
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ context->RSSetViewports(1, &viewport);
+
+ ID3D11ShaderResourceView *pixelViews[] = {depth->getShaderResourceView()};
+
+ context->PSSetShaderResources(0, 1, pixelViews);
+
+ context->PSSetShader(mResolveDepthPS.resolve(device), nullptr, 0);
+
+ // Trigger the blit on the GPU.
+ context->Draw(6, 0);
+
+ gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1);
+
+ const auto &copyFunction = GetCopyDepthStencilFunction(depth->getInternalFormat());
+ const auto &dsFormatSet = depth->getFormatSet();
+ const auto &dsDxgiInfo = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat);
+
+ ID3D11Texture2D *destTex = nullptr;
+
+ D3D11_TEXTURE2D_DESC destDesc;
+ destDesc.Width = extents.width;
+ destDesc.Height = extents.height;
+ destDesc.MipLevels = 1;
+ destDesc.ArraySize = 1;
+ destDesc.Format = dsFormatSet.texFormat;
+ destDesc.SampleDesc.Count = 1;
+ destDesc.SampleDesc.Quality = 0;
+ destDesc.Usage = D3D11_USAGE_DEFAULT;
+ destDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ destDesc.CPUAccessFlags = 0;
+ destDesc.MiscFlags = 0;
+
+ HRESULT hr = device->CreateTexture2D(&destDesc, nullptr, &destTex);
+ if (FAILED(hr))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Error creating depth resolve dest texture.");
+ }
+ d3d11::SetDebugName(destTex, "resolveDepthDest");
+
+ TextureHelper11 dest = TextureHelper11::MakeAndPossess2D(destTex, depth->getFormatSet());
+ ANGLE_TRY(copyAndConvert(mResolvedDepthStencil, 0, copyBox, extents, dest, 0, copyBox, extents,
+ nullptr, 0, 0, 0, 8, dsDxgiInfo.pixelBytes, copyFunction));
+ return dest;
+}
+
+gl::Error Blit11::initResolveDepthStencil(const gl::Extents &extents)
+{
+ // Check if we need to recreate depth stencil view
+ if (mResolvedDepthStencil.valid() && extents == mResolvedDepthStencil.getExtents())
+ {
+ return gl::NoError();
+ }
+
+ 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;
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ ID3D11Texture2D *resolvedDepthStencil = nullptr;
+ HRESULT hr = device->CreateTexture2D(&textureDesc, nullptr, &resolvedDepthStencil);
+ if (FAILED(hr))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate resolved depth stencil texture");
+ }
+ d3d11::SetDebugName(resolvedDepthStencil, "Blit11::mResolvedDepthStencil");
+
+ ASSERT(mResolvedDepthStencilRTView == nullptr);
+ hr =
+ device->CreateRenderTargetView(resolvedDepthStencil, nullptr, &mResolvedDepthStencilRTView);
+ if (FAILED(hr))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to allocate Blit11::mResolvedDepthStencilRTView");
+ }
+ d3d11::SetDebugName(mResolvedDepthStencilRTView, "Blit11::mResolvedDepthStencilRTView");
+
+ mResolvedDepthStencil = TextureHelper11::MakeAndPossess2D(resolvedDepthStencil, formatSet);
+
+ return gl::NoError();
+}
+
+gl::ErrorOrResult<TextureHelper11> Blit11::resolveStencil(RenderTarget11 *depthStencil,
+ bool alsoDepth)
+{
+ // Multisampled depth stencil SRVs are not available in feature level 10.0
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0)
+ {
+ return gl::Error(GL_INVALID_OPERATION,
+ "Resolving multisampled depth stencil textures is not supported in "
+ "feature level 10.0.");
+ }
+
+ const auto &extents = depthStencil->getExtents();
+
+ ANGLE_TRY(initResolveDepthStencil(extents));
+
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ ID3D11Resource *stencilResource = depthStencil->getTexture();
+
+ // Check if we need to re-create the stencil SRV.
+ if (mStencilSRV)
+ {
+ ID3D11Resource *priorResource = nullptr;
+ mStencilSRV->GetResource(&priorResource);
+
+ if (stencilResource != priorResource)
+ {
+ SafeRelease(mStencilSRV);
+ }
+ }
+
+ if (!mStencilSRV)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC srViewDesc;
+ srViewDesc.Format = GetStencilSRVFormat(depthStencil->getFormatSet());
+ srViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+
+ HRESULT hr = device->CreateShaderResourceView(stencilResource, &srViewDesc, &mStencilSRV);
+ if (FAILED(hr))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Error creating Blit11 stencil SRV");
+ }
+ d3d11::SetDebugName(mStencilSRV, "Blit11::mStencilSRV");
+ }
+
+ // Notify the Renderer that all state should be invalidated.
+ mRenderer->markAllStateDirty();
+
+ // Apply the necessary state changes to the D3D11 immediate device context.
+ context->IASetInputLayout(nullptr);
+ context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ context->VSSetShader(mResolveDepthStencilVS.resolve(device), nullptr, 0);
+ context->GSSetShader(nullptr, nullptr, 0);
+ context->RSSetState(nullptr);
+ context->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
+ context->OMSetRenderTargets(1, &mResolvedDepthStencilRTView, nullptr);
+ context->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+
+ // Set the viewport
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = static_cast<FLOAT>(extents.width);
+ viewport.Height = static_cast<FLOAT>(extents.height);
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ context->RSSetViewports(1, &viewport);
+
+ ID3D11ShaderResourceView *pixelViews[] = {
+ depthStencil->getShaderResourceView(), mStencilSRV,
+ };
+
+ context->PSSetShaderResources(0, 2, pixelViews);
+
+ // 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.
+ if (alsoDepth)
+ {
+ context->PSSetShader(mResolveDepthStencilPS.resolve(device), nullptr, 0);
+ }
+ else
+ {
+ context->PSSetShader(mResolveStencilPS.resolve(device), nullptr, 0);
+ }
+
+ // Trigger the blit on the GPU.
+ context->Draw(6, 0);
+
+ gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1);
+
+ TextureHelper11 dest;
+ ANGLE_TRY_RESULT(CreateStagingTexture(GL_TEXTURE_2D, depthStencil->getFormatSet(), extents,
+ StagingAccess::READ_WRITE, device),
+ dest);
+
+ const auto &copyFunction = GetCopyDepthStencilFunction(depthStencil->getInternalFormat());
+ const auto &dsFormatSet = depthStencil->getFormatSet();
+ const auto &dsDxgiInfo = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat);
+
+ ANGLE_TRY(copyAndConvertImpl(mResolvedDepthStencil, 0, copyBox, extents, dest, copyBox, extents,
+ nullptr, 0, 0, 0, 8u, dsDxgiInfo.pixelBytes, copyFunction));
+
+ // Return the resolved depth texture, which the caller must Release.
+ return dest;
+}
+
+void Blit11::releaseResolveDepthStencilResources()
+{
+ SafeRelease(mStencilSRV);
+ SafeRelease(mResolvedDepthStencilRTView);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h
new file mode 100755
index 000000000..e61f096c6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h
@@ -0,0 +1,295 @@
+//
+// Copyright (c) 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/angletypes.h"
+#include "libANGLE/Error.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();
+
+ gl::Error swizzleTexture(ID3D11ShaderResourceView *source,
+ ID3D11RenderTargetView *dest,
+ const gl::Extents &size,
+ const gl::SwizzleState &swizzleTarget);
+
+ gl::Error copyTexture(ID3D11ShaderResourceView *source,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ ID3D11RenderTargetView *dest,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ GLenum destFormat,
+ GLenum filter,
+ bool maskOffAlpha,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha);
+
+ gl::Error copyStencil(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);
+
+ gl::Error copyDepth(ID3D11ShaderResourceView *source,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ ID3D11DepthStencilView *dest,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor);
+
+ gl::Error copyDepthStencil(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);
+
+ gl::ErrorOrResult<TextureHelper11> resolveDepth(RenderTarget11 *depth);
+
+ gl::ErrorOrResult<TextureHelper11> resolveStencil(RenderTarget11 *depthStencil, bool alsoDepth);
+
+ 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 BlitShaderType
+ {
+ BLITSHADER_INVALID,
+ BLITSHADER_2D_RGBAF,
+ BLITSHADER_2D_RGBAF_PREMULTIPLY,
+ BLITSHADER_2D_RGBAF_UNMULTIPLY,
+ BLITSHADER_2D_BGRAF,
+ BLITSHADER_2D_BGRAF_PREMULTIPLY,
+ BLITSHADER_2D_BGRAF_UNMULTIPLY,
+ BLITSHADER_2D_RGBF,
+ BLITSHADER_2D_RGBF_PREMULTIPLY,
+ BLITSHADER_2D_RGBF_UNMULTIPLY,
+ 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_3D_RGBAF,
+ BLITSHADER_3D_RGBAUI,
+ BLITSHADER_3D_RGBAI,
+ BLITSHADER_3D_BGRAF,
+ BLITSHADER_3D_RGBF,
+ BLITSHADER_3D_RGBUI,
+ BLITSHADER_3D_RGBI,
+ BLITSHADER_3D_RGF,
+ BLITSHADER_3D_RGUI,
+ BLITSHADER_3D_RGI,
+ BLITSHADER_3D_RF,
+ BLITSHADER_3D_RUI,
+ BLITSHADER_3D_RI,
+ BLITSHADER_3D_ALPHA,
+ BLITSHADER_3D_LUMA,
+ BLITSHADER_3D_LUMAALPHA,
+ };
+
+ 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_2D,
+ SHADER_3D,
+ };
+
+ struct Shader
+ {
+ ShaderDimension dimension;
+ ID3D11PixelShader *pixelShader;
+ };
+
+ struct ShaderSupport
+ {
+ ID3D11InputLayout *inputLayout;
+ ID3D11VertexShader *vertexShader;
+ ID3D11GeometryShader *geometryShader;
+ WriteVertexFunction vertexWriteFunction;
+ };
+
+ gl::Error initResources();
+ void freeResources();
+
+ ShaderSupport getShaderSupport(const Shader &shader);
+
+ static BlitShaderType GetBlitShaderType(GLenum destinationFormat,
+ bool isSigned,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ ShaderDimension dimension);
+ static SwizzleShaderType GetSwizzleShaderType(GLenum type, D3D11_SRV_DIMENSION dimensionality);
+
+ gl::Error copyDepthStencilImpl(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);
+
+ gl::Error copyAndConvertImpl(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);
+
+ gl::Error copyAndConvert(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);
+
+ void addBlitShaderToMap(BlitShaderType blitShaderType,
+ ShaderDimension dimension,
+ ID3D11PixelShader *ps);
+
+ gl::Error getBlitShader(GLenum destFormat,
+ bool isSigned,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ ShaderDimension dimension,
+ const Shader **shaderOut);
+ gl::Error getSwizzleShader(GLenum type,
+ D3D11_SRV_DIMENSION viewDimension,
+ const Shader **shaderOut);
+
+ void addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType,
+ ShaderDimension dimension,
+ ID3D11PixelShader *ps);
+
+ void clearShaderMap();
+ void releaseResolveDepthStencilResources();
+ gl::Error initResolveDepthStencil(const gl::Extents &extents);
+
+ Renderer11 *mRenderer;
+
+ std::map<BlitShaderType, Shader> mBlitShaderMap;
+ std::map<SwizzleShaderType, Shader> mSwizzleShaderMap;
+
+ bool mResourcesInitialized;
+ ID3D11Buffer *mVertexBuffer;
+ ID3D11SamplerState *mPointSampler;
+ ID3D11SamplerState *mLinearSampler;
+ ID3D11RasterizerState *mScissorEnabledRasterizerState;
+ ID3D11RasterizerState *mScissorDisabledRasterizerState;
+ ID3D11DepthStencilState *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;
+
+ ID3D11Buffer *mSwizzleCB;
+
+ d3d11::LazyShader<ID3D11VertexShader> mResolveDepthStencilVS;
+ d3d11::LazyShader<ID3D11PixelShader> mResolveDepthPS;
+ d3d11::LazyShader<ID3D11PixelShader> mResolveDepthStencilPS;
+ d3d11::LazyShader<ID3D11PixelShader> mResolveStencilPS;
+ ID3D11ShaderResourceView *mStencilSRV;
+ TextureHelper11 mResolvedDepthStencil;
+ ID3D11RenderTargetView *mResolvedDepthStencilRTView;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
new file mode 100755
index 000000000..90668b759
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
@@ -0,0 +1,1556 @@
+//
+// 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/renderer/renderer_utils.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.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::roundUp(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 ? 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 isMappable(GLbitfield access) const = 0;
+
+ virtual gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset) = 0;
+ virtual gl::Error resize(size_t size, bool preserveData) = 0;
+
+ virtual gl::Error map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) = 0;
+ virtual void unmap() = 0;
+
+ gl::Error setData(const uint8_t *data, size_t offset, size_t size);
+
+ 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::BroadcastChannel *onStorageChanged);
+ ~NativeStorage() override;
+
+ bool isMappable(GLbitfield access) const override;
+
+ ID3D11Buffer *getNativeStorage() const { return mNativeStorage; }
+ gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset) override;
+ gl::Error resize(size_t size, bool preserveData) override;
+
+ gl::Error map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) override;
+ void unmap() override;
+
+ gl::ErrorOrResult<ID3D11ShaderResourceView *> getSRVForFormat(DXGI_FORMAT srvFormat);
+
+ private:
+ static void FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
+ Renderer11 *renderer,
+ BufferUsage usage,
+ unsigned int bufferSize);
+ void clearSRVs();
+
+ ID3D11Buffer *mNativeStorage;
+ const angle::BroadcastChannel *mOnStorageChanged;
+ std::map<DXGI_FORMAT, ID3D11ShaderResourceView *> mBufferResourceViews;
+};
+
+// 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 isMappable(GLbitfield access) const override { return true; }
+
+ gl::ErrorOrResult<ID3D11Buffer *> getNativeStorage(SourceIndexData *indexInfo,
+ const TranslatedAttribute &attribute,
+ GLint startVertex);
+
+ gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset) override;
+
+ gl::Error resize(size_t size, bool preserveData) override;
+
+ gl::Error map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) override;
+ void unmap() override;
+
+ private:
+ ID3D11Buffer *mNativeStorage; // contains expanded data for use by D3D
+ MemoryBuffer mMemoryBuffer; // original data (not expanded)
+ 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 isMappable(GLbitfield access) const override { return true; }
+ gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset) override;
+ gl::Error resize(size_t size, bool preserveData) override;
+
+ gl::Error map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) override;
+ void unmap() override;
+
+ gl::Error packPixels(const gl::FramebufferAttachment &readAttachment,
+ const PackPixelsParams &params);
+
+ private:
+ gl::Error flushQueuedPackCommand();
+
+ TextureHelper11 mStagingTexture;
+ 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 isMappable(GLbitfield access) const override { return true; }
+ gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset) override;
+ gl::Error resize(size_t size, bool preserveData) override;
+
+ gl::Error map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) override;
+ void unmap() override;
+
+ MemoryBuffer *getSystemCopy() { return &mSystemCopy; }
+
+ protected:
+ MemoryBuffer mSystemCopy;
+};
+
+Buffer11::Buffer11(const gl::BufferState &state, Renderer11 *renderer)
+ : BufferD3D(state, renderer),
+ mRenderer(renderer),
+ mSize(0),
+ mMappedStorage(nullptr),
+ mBufferStorages({}),
+ mDeallocThresholds({}),
+ mIdleness({}),
+ mConstantBufferStorageAdditionalSize(0),
+ mMaxConstantBufferLruCount(0)
+{
+}
+
+Buffer11::~Buffer11()
+{
+ for (auto &storage : mBufferStorages)
+ {
+ SafeDelete(storage);
+ }
+
+ for (auto &p : mConstantBufferRangeStoragesCache)
+ {
+ SafeDelete(p.second.storage);
+ }
+
+ mRenderer->onBufferDelete(this);
+}
+
+gl::Error Buffer11::setData(GLenum target, const void *data, size_t size, GLenum usage)
+{
+ updateD3DBufferUsage(usage);
+ ANGLE_TRY(setSubData(target, data, size, 0));
+ return gl::NoError();
+}
+
+gl::Error Buffer11::getData(const uint8_t **outData)
+{
+ SystemMemoryStorage *systemMemoryStorage = nullptr;
+ ANGLE_TRY_RESULT(getSystemMemoryStorage(), systemMemoryStorage);
+
+ ASSERT(systemMemoryStorage->getSize() >= mSize);
+
+ *outData = systemMemoryStorage->getSystemCopy()->data();
+ return gl::NoError();
+}
+
+gl::ErrorOrResult<Buffer11::SystemMemoryStorage *> Buffer11::getSystemMemoryStorage()
+{
+ BufferStorage *storage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_SYSTEM_MEMORY), storage);
+ return GetAs<SystemMemoryStorage>(storage);
+}
+
+gl::Error Buffer11::setSubData(GLenum 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_UNIFORM_BUFFER)
+ {
+ // 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->getWorkarounds().useSystemMemoryForConstantBuffers)
+ {
+ ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_UNIFORM), writeBuffer);
+ }
+ else
+ {
+ ANGLE_TRY_RESULT(getSystemMemoryStorage(), writeBuffer);
+ }
+ }
+ else if (supportsDirectBinding())
+ {
+ ANGLE_TRY_RESULT(getStagingStorage(), writeBuffer);
+ }
+ else
+ {
+ ANGLE_TRY_RESULT(getSystemMemoryStorage(), 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(requiredSize, preserveData));
+ }
+
+ writeBuffer->setData(static_cast<const uint8_t *>(data), offset, size);
+ writeBuffer->setDataRevision(writeBuffer->getDataRevision() + 1);
+ }
+
+ mSize = std::max(mSize, requiredSize);
+ invalidateStaticData();
+
+ return gl::NoError();
+}
+
+gl::Error Buffer11::copySubData(BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size)
+{
+ Buffer11 *sourceBuffer = GetAs<Buffer11>(source);
+ ASSERT(sourceBuffer != nullptr);
+
+ BufferStorage *copyDest = nullptr;
+ ANGLE_TRY_RESULT(getLatestBufferStorage(), copyDest);
+
+ if (!copyDest)
+ {
+ ANGLE_TRY_RESULT(getStagingStorage(), copyDest);
+ }
+
+ BufferStorage *copySource = nullptr;
+ ANGLE_TRY_RESULT(sourceBuffer->getLatestBufferStorage(), copySource);
+
+ if (!copySource || !copyDest)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer.");
+ }
+
+ // If copying to/from a pixel pack buffer, we must have a staging or
+ // pack buffer partner, because other native buffers can't be mapped
+ if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable(GL_MAP_READ_BIT))
+ {
+ ANGLE_TRY_RESULT(sourceBuffer->getStagingStorage(), copySource);
+ }
+ else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK &&
+ !copyDest->isMappable(GL_MAP_WRITE_BIT))
+ {
+ ANGLE_TRY_RESULT(getStagingStorage(), 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_RESULT(getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK),
+ copySource);
+ }
+ else
+ {
+ ANGLE_TRY_RESULT(getStagingStorage(), copySource);
+ }
+ }
+
+ CopyResult copyResult = CopyResult::NOT_RECREATED;
+ ANGLE_TRY_RESULT(copyDest->copyFromStorage(copySource, sourceOffset, size, destOffset),
+ copyResult);
+ copyDest->setDataRevision(copyDest->getDataRevision() + 1);
+
+ mSize = std::max<size_t>(mSize, destOffset + size);
+ invalidateStaticData();
+
+ return gl::NoError();
+}
+
+gl::Error Buffer11::map(GLenum access, GLvoid **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(0, mSize, GL_MAP_WRITE_BIT, mapPtr);
+}
+
+gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+{
+ ASSERT(!mMappedStorage);
+
+ BufferStorage *latestStorage = nullptr;
+ ANGLE_TRY_RESULT(getLatestBufferStorage(), 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_RESULT(getStagingStorage(), mMappedStorage);
+ }
+
+ if (!mMappedStorage)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate mappable internal buffer.");
+ }
+
+ if ((access & GL_MAP_WRITE_BIT) > 0)
+ {
+ // Update the data revision immediately, since the data might be changed at any time
+ mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1);
+ invalidateStaticData();
+ }
+
+ uint8_t *mappedBuffer = nullptr;
+ ANGLE_TRY(mMappedStorage->map(offset, length, access, &mappedBuffer));
+ ASSERT(mappedBuffer);
+
+ *mapPtr = static_cast<GLvoid *>(mappedBuffer);
+ return gl::NoError();
+}
+
+gl::Error Buffer11::unmap(GLboolean *result)
+{
+ ASSERT(mMappedStorage);
+ mMappedStorage->unmap();
+ mMappedStorage = nullptr;
+
+ // TODO: detect if we had corruption. if so, return false.
+ *result = GL_TRUE;
+
+ return gl::NoError();
+}
+
+gl::Error Buffer11::markTransformFeedbackUsage()
+{
+ BufferStorage *transformFeedbackStorage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK),
+ transformFeedbackStorage);
+
+ if (transformFeedbackStorage)
+ {
+ transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1);
+ }
+
+ invalidateStaticData();
+ return gl::NoError();
+}
+
+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.
+gl::Error Buffer11::checkForDeallocation(BufferUsage usage)
+{
+ mIdleness[usage]++;
+
+ BufferStorage *&storage = mBufferStorages[usage];
+ if (storage != nullptr && mIdleness[usage] > mDeallocThresholds[usage])
+ {
+ BufferStorage *latestStorage = nullptr;
+ ANGLE_TRY_RESULT(getLatestBufferStorage(), latestStorage);
+ if (latestStorage != storage)
+ {
+ SafeDelete(storage);
+ }
+ }
+
+ return gl::NoError();
+}
+
+// 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->getWorkarounds().useSystemMemoryForConstantBuffers)
+ {
+ return false;
+ }
+
+ return (!mBufferStorages[BUFFER_USAGE_UNIFORM] ||
+ mSize <= mRenderer->getNativeCaps().maxUniformBlockSize);
+}
+
+void Buffer11::markBufferUsage(BufferUsage usage)
+{
+ mIdleness[usage] = 0;
+}
+
+gl::Error Buffer11::garbageCollection(BufferUsage currentUsage)
+{
+ if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory())
+ {
+ ANGLE_TRY(checkForDeallocation(BUFFER_USAGE_SYSTEM_MEMORY));
+ }
+
+ if (currentUsage != BUFFER_USAGE_STAGING)
+ {
+ ANGLE_TRY(checkForDeallocation(BUFFER_USAGE_STAGING));
+ }
+
+ return gl::NoError();
+}
+
+gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getBuffer(BufferUsage usage)
+{
+ BufferStorage *storage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(usage), storage);
+ return GetAs<NativeStorage>(storage)->getNativeStorage();
+}
+
+gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer(
+ SourceIndexData *indexInfo,
+ const TranslatedAttribute &attribute,
+ GLint startVertex)
+{
+ ASSERT(indexInfo);
+
+ BufferStorage *untypedStorage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_EMULATED_INDEXED_VERTEX), untypedStorage);
+
+ EmulatedIndexedStorage *emulatedStorage = GetAs<EmulatedIndexedStorage>(untypedStorage);
+
+ ID3D11Buffer *nativeStorage = nullptr;
+ ANGLE_TRY_RESULT(emulatedStorage->getNativeStorage(indexInfo, attribute, startVertex),
+ nativeStorage);
+
+ return nativeStorage;
+}
+
+gl::Error Buffer11::getConstantBufferRange(GLintptr offset,
+ GLsizeiptr size,
+ ID3D11Buffer **bufferOut,
+ UINT *firstConstantOut,
+ UINT *numConstantsOut)
+{
+ BufferStorage *bufferStorage = nullptr;
+
+ if (offset == 0 || mRenderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets)
+ {
+ ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_UNIFORM), bufferStorage);
+ CalculateConstantBufferParams(offset, size, firstConstantOut, numConstantsOut);
+ }
+ else
+ {
+ ANGLE_TRY_RESULT(getConstantBufferRangeStorage(offset, size), bufferStorage);
+ *firstConstantOut = 0;
+ *numConstantsOut = 0;
+ }
+
+ *bufferOut = GetAs<NativeStorage>(bufferStorage)->getNativeStorage();
+
+ return gl::NoError();
+}
+
+gl::ErrorOrResult<ID3D11ShaderResourceView *> Buffer11::getSRV(DXGI_FORMAT srvFormat)
+{
+ BufferStorage *storage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK), storage);
+ NativeStorage *nativeStorage = GetAs<NativeStorage>(storage);
+ return nativeStorage->getSRVForFormat(srvFormat);
+}
+
+gl::Error Buffer11::packPixels(const gl::FramebufferAttachment &readAttachment,
+ const PackPixelsParams &params)
+{
+ PackStorage *packStorage = nullptr;
+ ANGLE_TRY_RESULT(getPackStorage(), packStorage);
+
+ BufferStorage *latestStorage = nullptr;
+ ANGLE_TRY_RESULT(getLatestBufferStorage(), latestStorage);
+
+ ASSERT(packStorage);
+ ANGLE_TRY(packStorage->packPixels(readAttachment, params));
+ packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1);
+
+ return gl::NoError();
+}
+
+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;
+}
+
+gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getBufferStorage(BufferUsage usage)
+{
+ 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(mSize, true));
+ }
+
+ ASSERT(newStorage);
+
+ ANGLE_TRY(updateBufferStorage(newStorage, 0, mSize));
+ ANGLE_TRY(garbageCollection(usage));
+
+ return newStorage;
+}
+
+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_VERTEX_OR_TRANSFORM_FEEDBACK:
+ return new NativeStorage(mRenderer, usage, &mDirectBroadcastChannel);
+ default:
+ return new NativeStorage(mRenderer, usage, nullptr);
+ }
+}
+
+gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getConstantBufferRangeStorage(
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ 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.
+ ConstantBufferCacheEntry *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 ConstantBufferCache::value_type &a,
+ const ConstantBufferCache::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(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(newStorage, offset, size));
+ ANGLE_TRY(garbageCollection(BUFFER_USAGE_UNIFORM));
+ return newStorage;
+}
+
+gl::Error Buffer11::updateBufferStorage(BufferStorage *storage,
+ size_t sourceOffset,
+ size_t storageSize)
+{
+ BufferStorage *latestBuffer = nullptr;
+ ANGLE_TRY_RESULT(getLatestBufferStorage(), latestBuffer);
+
+ ASSERT(storage);
+
+ if (latestBuffer && latestBuffer->getDataRevision() > storage->getDataRevision())
+ {
+ // 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->isMappable(GL_MAP_READ_BIT) || !storage->isMappable(GL_MAP_WRITE_BIT)))
+ {
+ NativeStorage *stagingBuffer = nullptr;
+ ANGLE_TRY_RESULT(getStagingStorage(), stagingBuffer);
+
+ CopyResult copyResult = CopyResult::NOT_RECREATED;
+ ANGLE_TRY_RESULT(
+ stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0),
+ copyResult);
+ stagingBuffer->setDataRevision(latestBuffer->getDataRevision());
+
+ latestBuffer = stagingBuffer;
+ }
+
+ CopyResult copyResult = CopyResult::NOT_RECREATED;
+ ANGLE_TRY_RESULT(storage->copyFromStorage(latestBuffer, sourceOffset, storageSize, 0),
+ copyResult);
+ // If the D3D buffer has been recreated, we should update our serial.
+ if (copyResult == CopyResult::RECREATED)
+ {
+ updateSerial();
+ }
+ storage->setDataRevision(latestBuffer->getDataRevision());
+ }
+
+ return gl::NoError();
+}
+
+gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getLatestBufferStorage() const
+{
+ // Even though we iterate over all the direct buffers, it is expected that only
+ // 1 or 2 will be present.
+ BufferStorage *latestStorage = nullptr;
+ DataRevision latestRevision = 0;
+ for (auto &storage : mBufferStorages)
+ {
+ if (storage && (!latestStorage || storage->getDataRevision() > latestRevision))
+ {
+ latestStorage = storage;
+ latestRevision = storage->getDataRevision();
+ }
+ }
+
+ // resize buffer
+ if (latestStorage && latestStorage->getSize() < mSize)
+ {
+ ANGLE_TRY(latestStorage->resize(mSize, true));
+ }
+
+ return latestStorage;
+}
+
+gl::ErrorOrResult<Buffer11::NativeStorage *> Buffer11::getStagingStorage()
+{
+ BufferStorage *stagingStorage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_STAGING), stagingStorage);
+ return GetAs<NativeStorage>(stagingStorage);
+}
+
+gl::ErrorOrResult<Buffer11::PackStorage *> Buffer11::getPackStorage()
+{
+ BufferStorage *packStorage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_PIXEL_PACK), packStorage);
+ return GetAs<PackStorage>(packStorage);
+}
+
+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()
+{
+ BufferD3D::initializeStaticData();
+
+ // Notify when static data changes.
+ mStaticBroadcastChannel.signal();
+}
+
+void Buffer11::invalidateStaticData()
+{
+ BufferD3D::invalidateStaticData();
+
+ // Notify when static data changes.
+ mStaticBroadcastChannel.signal();
+}
+
+angle::BroadcastChannel *Buffer11::getStaticBroadcastChannel()
+{
+ return &mStaticBroadcastChannel;
+}
+
+angle::BroadcastChannel *Buffer11::getDirectBroadcastChannel()
+{
+ return &mDirectBroadcastChannel;
+}
+
+// Buffer11::BufferStorage implementation
+
+Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
+ : mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0)
+{
+}
+
+gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, size_t size)
+{
+ ASSERT(isMappable(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(offset, mapSize, GL_MAP_WRITE_BIT, &writePointer));
+
+ memcpy(writePointer, data, mapSize);
+
+ unmap();
+
+ return gl::NoError();
+}
+
+// Buffer11::NativeStorage implementation
+
+Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer,
+ BufferUsage usage,
+ const angle::BroadcastChannel *onStorageChanged)
+ : BufferStorage(renderer, usage), mNativeStorage(nullptr), mOnStorageChanged(onStorageChanged)
+{
+}
+
+Buffer11::NativeStorage::~NativeStorage()
+{
+ SafeRelease(mNativeStorage);
+ clearSRVs();
+}
+
+bool Buffer11::NativeStorage::isMappable(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);
+}
+
+// Returns true if it recreates the direct buffer
+gl::ErrorOrResult<CopyResult> Buffer11::NativeStorage::copyFromStorage(BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset)
+{
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ size_t requiredSize = destOffset + size;
+ bool createBuffer = !mNativeStorage || mBufferSize < requiredSize;
+
+ // (Re)initialize D3D buffer if needed
+ bool preserveData = (destOffset > 0);
+ if (createBuffer)
+ {
+ resize(requiredSize, preserveData);
+ }
+
+ size_t clampedSize = size;
+ if (mUsage == BUFFER_USAGE_UNIFORM)
+ {
+ clampedSize = std::min(clampedSize, mBufferSize - destOffset);
+ }
+
+ if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
+ source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY)
+ {
+ ASSERT(source->isMappable(GL_MAP_READ_BIT) && isMappable(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(sourceOffset, clampedSize, GL_MAP_READ_BIT, &sourcePointer));
+
+ setData(sourcePointer, destOffset, clampedSize);
+
+ source->unmap();
+ }
+ 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;
+
+ ID3D11Buffer *sourceBuffer = GetAs<NativeStorage>(source)->getNativeStorage();
+
+ context->CopySubresourceRegion(mNativeStorage, 0, static_cast<unsigned int>(destOffset), 0,
+ 0, sourceBuffer, 0, &srcBox);
+ }
+
+ return createBuffer ? CopyResult::RECREATED : CopyResult::NOT_RECREATED;
+}
+
+gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
+{
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ D3D11_BUFFER_DESC bufferDesc;
+ FillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size));
+
+ ID3D11Buffer *newBuffer;
+ HRESULT result = device->CreateBuffer(&bufferDesc, nullptr, &newBuffer);
+
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.",
+ result);
+ }
+
+ d3d11::SetDebugName(newBuffer, "Buffer11::NativeStorage");
+
+ if (mNativeStorage && 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;
+
+ context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeStorage, 0, &srcBox);
+ }
+
+ // No longer need the old buffer
+ SafeRelease(mNativeStorage);
+ mNativeStorage = newBuffer;
+
+ mBufferSize = bufferDesc.ByteWidth;
+
+ // Free the SRVs.
+ clearSRVs();
+
+ // Notify that the storage has changed.
+ if (mOnStorageChanged)
+ {
+ mOnStorageChanged->signal();
+ }
+
+ return gl::NoError();
+}
+
+// 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_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 = roundUp(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)
+ bufferDesc->ByteWidth =
+ std::min<UINT>(bufferDesc->ByteWidth,
+ static_cast<UINT>(renderer->getNativeCaps().maxUniformBlockSize));
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+gl::Error Buffer11::NativeStorage::map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut)
+{
+ ASSERT(isMappable(access));
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(mUsage, access);
+ UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0);
+
+ HRESULT result = context->Map(mNativeStorage, 0, d3dMapType, d3dMapFlag, &mappedResource);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to map native storage in Buffer11::NativeStorage::map");
+ }
+ ASSERT(mappedResource.pData);
+ *mapPointerOut = static_cast<uint8_t *>(mappedResource.pData) + offset;
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Buffer11::NativeStorage::unmap()
+{
+ ASSERT(isMappable(GL_MAP_WRITE_BIT) || isMappable(GL_MAP_READ_BIT));
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ context->Unmap(mNativeStorage, 0);
+}
+
+gl::ErrorOrResult<ID3D11ShaderResourceView *> Buffer11::NativeStorage::getSRVForFormat(
+ DXGI_FORMAT srvFormat)
+{
+ auto bufferSRVIt = mBufferResourceViews.find(srvFormat);
+
+ if (bufferSRVIt != mBufferResourceViews.end())
+ {
+ return bufferSRVIt->second;
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11ShaderResourceView *bufferSRV = nullptr;
+
+ 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;
+
+ HRESULT result = device->CreateShaderResourceView(mNativeStorage, &bufferSRVDesc, &bufferSRV);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Error creating buffer SRV in Buffer11::NativeStorage::getSRVForFormat");
+ }
+
+ mBufferResourceViews[srvFormat] = bufferSRV;
+
+ return bufferSRV;
+}
+
+void Buffer11::NativeStorage::clearSRVs()
+{
+ for (auto &srv : mBufferResourceViews)
+ {
+ SafeRelease(srv.second);
+ }
+ mBufferResourceViews.clear();
+}
+
+// Buffer11::EmulatedIndexStorage implementation
+
+Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer)
+ : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mNativeStorage(nullptr)
+{
+}
+
+Buffer11::EmulatedIndexedStorage::~EmulatedIndexedStorage()
+{
+ SafeRelease(mNativeStorage);
+}
+
+gl::ErrorOrResult<ID3D11Buffer *> Buffer11::EmulatedIndexedStorage::getNativeStorage(
+ SourceIndexData *indexInfo,
+ const TranslatedAttribute &attribute,
+ GLint startVertex)
+{
+ // 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 (mNativeStorage == nullptr || indexInfo->srcIndicesChanged)
+ {
+ SafeRelease(mNativeStorage);
+
+ // 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_UNSIGNED_INT:
+ indicesDataSize = sizeof(GLuint) * indexInfo->srcCount;
+ break;
+ case GL_UNSIGNED_SHORT:
+ indicesDataSize = sizeof(GLushort) * indexInfo->srcCount;
+ break;
+ case GL_UNSIGNED_BYTE:
+ indicesDataSize = sizeof(GLubyte) * indexInfo->srcCount;
+ break;
+ default:
+ indicesDataSize = sizeof(GLushort) * indexInfo->srcCount;
+ break;
+ }
+
+ if (!mIndicesMemoryBuffer.resize(indicesDataSize))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Error resizing index memory buffer in "
+ "Buffer11::EmulatedIndexedStorage::getNativeStorage");
+ }
+
+ memcpy(mIndicesMemoryBuffer.data(), indexInfo->srcIndices, indicesDataSize);
+
+ indexInfo->srcIndicesChanged = false;
+ }
+
+ if (!mNativeStorage)
+ {
+ unsigned int offset = 0;
+ ANGLE_TRY_RESULT(attribute.computeOffset(startVertex), offset);
+
+ // Expand the memory storage upon request and cache the results.
+ unsigned int expandedDataSize =
+ static_cast<unsigned int>((indexInfo->srcCount * attribute.stride) + offset);
+ MemoryBuffer expandedData;
+ if (!expandedData.resize(expandedDataSize))
+ {
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Error resizing buffer in Buffer11::EmulatedIndexedStorage::getNativeStorage");
+ }
+
+ // 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_UNSIGNED_INT:
+ readIndexValue = ReadIndexValueFromIndices<GLuint>;
+ break;
+ case GL_UNSIGNED_SHORT:
+ readIndexValue = ReadIndexValueFromIndices<GLushort>;
+ break;
+ case GL_UNSIGNED_BYTE:
+ readIndexValue = ReadIndexValueFromIndices<GLubyte>;
+ break;
+ }
+
+ // 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.
+ ID3D11Device *device = mRenderer->getDevice();
+
+ 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};
+
+ HRESULT result = device->CreateBuffer(&bufferDesc, &subResourceData, &mNativeStorage);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Could not create emulated index data buffer: %08lX",
+ result);
+ }
+ d3d11::SetDebugName(mNativeStorage, "Buffer11::EmulatedIndexedStorage");
+ }
+
+ return mNativeStorage;
+}
+
+gl::ErrorOrResult<CopyResult> Buffer11::EmulatedIndexedStorage::copyFromStorage(
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset)
+{
+ ASSERT(source->isMappable(GL_MAP_READ_BIT));
+ uint8_t *sourceData = nullptr;
+ ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
+ ASSERT(destOffset + size <= mMemoryBuffer.size());
+ memcpy(mMemoryBuffer.data() + destOffset, sourceData, size);
+ source->unmap();
+ return CopyResult::RECREATED;
+}
+
+gl::Error Buffer11::EmulatedIndexedStorage::resize(size_t size, bool preserveData)
+{
+ if (mMemoryBuffer.size() < size)
+ {
+ if (!mMemoryBuffer.resize(size))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize EmulatedIndexedStorage");
+ }
+ mBufferSize = size;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Buffer11::EmulatedIndexedStorage::map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut)
+{
+ ASSERT(!mMemoryBuffer.empty() && offset + length <= mMemoryBuffer.size());
+ *mapPointerOut = mMemoryBuffer.data() + offset;
+ return gl::Error(GL_NO_ERROR);
+}
+
+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()
+{
+}
+
+gl::ErrorOrResult<CopyResult> Buffer11::PackStorage::copyFromStorage(BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset)
+{
+ ANGLE_TRY(flushQueuedPackCommand());
+
+ // For all use cases of pack buffers, we must copy through a readable buffer.
+ ASSERT(source->isMappable(GL_MAP_READ_BIT));
+ uint8_t *sourceData = nullptr;
+ ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
+ ASSERT(destOffset + size <= mMemoryBuffer.size());
+ memcpy(mMemoryBuffer.data() + destOffset, sourceData, size);
+ source->unmap();
+ return CopyResult::NOT_RECREATED;
+}
+
+gl::Error Buffer11::PackStorage::resize(size_t size, bool preserveData)
+{
+ if (size != mBufferSize)
+ {
+ if (!mMemoryBuffer.resize(size))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer storage.");
+ }
+ mBufferSize = size;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Buffer11::PackStorage::map(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());
+
+ mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0);
+
+ *mapPointerOut = mMemoryBuffer.data() + offset;
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Buffer11::PackStorage::unmap()
+{
+ // No-op
+}
+
+gl::Error Buffer11::PackStorage::packPixels(const gl::FramebufferAttachment &readAttachment,
+ const PackPixelsParams &params)
+{
+ ANGLE_TRY(flushQueuedPackCommand());
+
+ RenderTarget11 *renderTarget = nullptr;
+ ANGLE_TRY(readAttachment.getRenderTarget(&renderTarget));
+
+ ID3D11Resource *renderTargetResource = renderTarget->getTexture();
+ ASSERT(renderTargetResource);
+
+ unsigned int srcSubresource = renderTarget->getSubresourceIndex();
+ TextureHelper11 srcTexture =
+ TextureHelper11::MakeAndReference(renderTargetResource, renderTarget->getFormatSet());
+
+ mQueuedPackCommand.reset(new PackPixelsParams(params));
+
+ gl::Extents srcTextureSize(params.area.width, params.area.height, 1);
+ if (!mStagingTexture.getResource() || mStagingTexture.getFormat() != srcTexture.getFormat() ||
+ mStagingTexture.getExtents() != srcTextureSize)
+ {
+ ANGLE_TRY_RESULT(
+ CreateStagingTexture(srcTexture.getTextureType(), srcTexture.getFormatSet(),
+ srcTextureSize, StagingAccess::READ, mRenderer->getDevice()),
+ 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.getTextureType() == GL_TEXTURE_3D)
+ {
+ srcBox.front = static_cast<UINT>(readAttachment.layer());
+ }
+ srcBox.back = srcBox.front + 1;
+
+ // Asynchronous copy
+ immediateContext->CopySubresourceRegion(mStagingTexture.getResource(), 0, 0, 0, 0,
+ srcTexture.getResource(), srcSubresource, &srcBox);
+
+ return gl::NoError();
+}
+
+gl::Error Buffer11::PackStorage::flushQueuedPackCommand()
+{
+ ASSERT(mMemoryBuffer.size() > 0);
+
+ if (mQueuedPackCommand)
+ {
+ ANGLE_TRY(
+ mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()));
+ mQueuedPackCommand.reset(nullptr);
+ }
+
+ return gl::NoError();
+}
+
+// Buffer11::SystemMemoryStorage implementation
+
+Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer)
+ : Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY)
+{
+}
+
+gl::ErrorOrResult<CopyResult> Buffer11::SystemMemoryStorage::copyFromStorage(BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset)
+{
+ ASSERT(source->isMappable(GL_MAP_READ_BIT));
+ uint8_t *sourceData = nullptr;
+ ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
+ ASSERT(destOffset + size <= mSystemCopy.size());
+ memcpy(mSystemCopy.data() + destOffset, sourceData, size);
+ source->unmap();
+ return CopyResult::RECREATED;
+}
+
+gl::Error Buffer11::SystemMemoryStorage::resize(size_t size, bool preserveData)
+{
+ if (mSystemCopy.size() < size)
+ {
+ if (!mSystemCopy.resize(size))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize SystemMemoryStorage");
+ }
+ mBufferSize = size;
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Buffer11::SystemMemoryStorage::map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut)
+{
+ ASSERT(!mSystemCopy.empty() && offset + length <= mSystemCopy.size());
+ *mapPointerOut = mSystemCopy.data() + offset;
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Buffer11::SystemMemoryStorage::unmap()
+{
+ // No-op
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
new file mode 100755
index 000000000..3210f05bc
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
@@ -0,0 +1,156 @@
+//
+// 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/signal_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_PIXEL_UNPACK,
+ BUFFER_USAGE_PIXEL_PACK,
+ BUFFER_USAGE_UNIFORM,
+ BUFFER_USAGE_EMULATED_INDEXED_VERTEX,
+
+ BUFFER_USAGE_COUNT,
+};
+
+typedef size_t DataRevision;
+
+class Buffer11 : public BufferD3D
+{
+ public:
+ Buffer11(const gl::BufferState &state, Renderer11 *renderer);
+ virtual ~Buffer11();
+
+ gl::ErrorOrResult<ID3D11Buffer *> getBuffer(BufferUsage usage);
+ gl::ErrorOrResult<ID3D11Buffer *> getEmulatedIndexedBuffer(SourceIndexData *indexInfo,
+ const TranslatedAttribute &attribute,
+ GLint startVertex);
+ gl::Error getConstantBufferRange(GLintptr offset,
+ GLsizeiptr size,
+ ID3D11Buffer **bufferOut,
+ UINT *firstConstantOut,
+ UINT *numConstantsOut);
+ gl::ErrorOrResult<ID3D11ShaderResourceView *> getSRV(DXGI_FORMAT srvFormat);
+ bool isMapped() const { return mMappedStorage != nullptr; }
+ gl::Error packPixels(const gl::FramebufferAttachment &readAttachment,
+ const PackPixelsParams &params);
+ size_t getTotalCPUBufferMemoryBytes() const;
+
+ // BufferD3D implementation
+ size_t getSize() const override { return mSize; }
+ bool supportsDirectBinding() const override;
+ gl::Error getData(const uint8_t **outData) override;
+ void initializeStaticData() override;
+ void invalidateStaticData() override;
+
+ // BufferImpl implementation
+ gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) override;
+ gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) override;
+ gl::Error copySubData(BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size) override;
+ gl::Error map(GLenum access, GLvoid **mapPtr) override;
+ gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override;
+ gl::Error unmap(GLboolean *result) override;
+ gl::Error markTransformFeedbackUsage() override;
+
+ // We use two set of dirty events. Static buffers are marked dirty whenever
+ // data changes, because they must be re-translated. Direct buffers only need to be
+ // updated when the underlying ID3D11Buffer pointer changes - hopefully far less often.
+ angle::BroadcastChannel *getStaticBroadcastChannel();
+ angle::BroadcastChannel *getDirectBroadcastChannel();
+
+ private:
+ class BufferStorage;
+ class EmulatedIndexedStorage;
+ class NativeStorage;
+ class PackStorage;
+ class SystemMemoryStorage;
+
+ struct ConstantBufferCacheEntry
+ {
+ ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) { }
+
+ BufferStorage *storage;
+ unsigned int lruCount;
+ };
+
+ void markBufferUsage(BufferUsage usage);
+ gl::Error garbageCollection(BufferUsage currentUsage);
+ gl::ErrorOrResult<NativeStorage *> getStagingStorage();
+ gl::ErrorOrResult<PackStorage *> getPackStorage();
+ gl::ErrorOrResult<SystemMemoryStorage *> getSystemMemoryStorage();
+
+ gl::Error updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize);
+ gl::ErrorOrResult<BufferStorage *> getBufferStorage(BufferUsage usage);
+ gl::ErrorOrResult<BufferStorage *> getLatestBufferStorage() const;
+
+ gl::ErrorOrResult<BufferStorage *> getConstantBufferRangeStorage(GLintptr offset,
+ GLsizeiptr size);
+
+ BufferStorage *allocateStorage(BufferUsage usage);
+ void updateDeallocThreshold(BufferUsage usage);
+
+ // Free the storage if we decide it isn't being used very often.
+ gl::Error checkForDeallocation(BufferUsage usage);
+
+ // For some cases of uniform buffer storage, we can't deallocate system memory storage.
+ bool canDeallocateSystemMemory() const;
+
+ Renderer11 *mRenderer;
+ size_t mSize;
+
+ BufferStorage *mMappedStorage;
+
+ std::array<BufferStorage *, BUFFER_USAGE_COUNT> mBufferStorages;
+
+ // 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*/, ConstantBufferCacheEntry> ConstantBufferCache;
+ ConstantBufferCache mConstantBufferRangeStoragesCache;
+ size_t mConstantBufferStorageAdditionalSize;
+ unsigned int mMaxConstantBufferLruCount;
+
+ angle::BroadcastChannel mStaticBroadcastChannel;
+ angle::BroadcastChannel mDirectBroadcastChannel;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
new file mode 100755
index 000000000..f42a59ced
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
@@ -0,0 +1,672 @@
+//
+// Copyright (c) 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/FramebufferAttachment.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "third_party/trace_event/trace_event.h"
+
+// Precompiled shaders
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h"
+
+namespace rx
+{
+
+template <typename T>
+static void ApplyVertices(const gl::Extents &framebufferSize,
+ const gl::Rectangle *scissor,
+ const gl::Color<T> &color,
+ float depth,
+ void *buffer)
+{
+ d3d11::PositionDepthColorVertex<T> *vertices =
+ reinterpret_cast<d3d11::PositionDepthColorVertex<T> *>(buffer);
+
+ float depthClear = gl::clamp01(depth);
+ float left = -1.0f;
+ float right = 1.0f;
+ float top = -1.0f;
+ float bottom = 1.0f;
+
+ // Clip the quad coordinates to the scissor if needed
+ if (scissor != nullptr)
+ {
+ left = std::max(left, (scissor->x / float(framebufferSize.width)) * 2.0f - 1.0f);
+ right = std::min(
+ right, ((scissor->x + scissor->width) / float(framebufferSize.width)) * 2.0f - 1.0f);
+ top = std::max(top, ((framebufferSize.height - scissor->y - scissor->height) /
+ float(framebufferSize.height)) *
+ 2.0f -
+ 1.0f);
+ bottom = std::min(
+ bottom,
+ ((framebufferSize.height - scissor->y) / float(framebufferSize.height)) * 2.0f - 1.0f);
+ }
+
+ d3d11::SetPositionDepthColorVertex<T>(vertices + 0, left, bottom, depthClear, color);
+ d3d11::SetPositionDepthColorVertex<T>(vertices + 1, left, top, depthClear, color);
+ d3d11::SetPositionDepthColorVertex<T>(vertices + 2, right, bottom, depthClear, color);
+ d3d11::SetPositionDepthColorVertex<T>(vertices + 3, right, top, depthClear, color);
+}
+
+Clear11::ClearShader::ClearShader(DXGI_FORMAT colorType,
+ const char *inputLayoutName,
+ const BYTE *vsByteCode,
+ size_t vsSize,
+ const char *vsDebugName,
+ const BYTE *psByteCode,
+ size_t psSize,
+ const char *psDebugName)
+ : inputLayout(nullptr),
+ vertexShader(vsByteCode, vsSize, vsDebugName),
+ pixelShader(psByteCode, psSize, psDebugName)
+{
+ D3D11_INPUT_ELEMENT_DESC quadLayout[] = {
+ {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
+ {"COLOR", 0, colorType, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
+ };
+
+ inputLayout = new d3d11::LazyInputLayout(quadLayout, 2, vsByteCode, vsSize, inputLayoutName);
+}
+
+Clear11::ClearShader::~ClearShader()
+{
+ SafeDelete(inputLayout);
+ vertexShader.release();
+ pixelShader.release();
+}
+
+Clear11::Clear11(Renderer11 *renderer)
+ : mRenderer(renderer),
+ mClearBlendStates(StructLessThan<ClearBlendInfo>),
+ mFloatClearShader(nullptr),
+ mUintClearShader(nullptr),
+ mIntClearShader(nullptr),
+ mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>),
+ mVertexBuffer(nullptr),
+ mRasterizerState(nullptr)
+{
+ TRACE_EVENT0("gpu.angle", "Clear11::Clear11");
+
+ HRESULT result;
+ ID3D11Device *device = renderer->getDevice();
+
+ D3D11_BUFFER_DESC vbDesc;
+ vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex<float>) * 4;
+ vbDesc.Usage = D3D11_USAGE_DYNAMIC;
+ vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ vbDesc.MiscFlags = 0;
+ vbDesc.StructureByteStride = 0;
+
+ result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer");
+
+ 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;
+
+ result = device->CreateRasterizerState(&rsDesc, &mRasterizerState);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state");
+
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ mFloatClearShader =
+ new ClearShader(DXGI_FORMAT_R32G32B32A32_FLOAT, "Clear11 Float IL", g_VS_ClearFloat,
+ ArraySize(g_VS_ClearFloat), "Clear11 Float VS", g_PS_ClearFloat_FL9,
+ ArraySize(g_PS_ClearFloat_FL9), "Clear11 Float PS");
+ }
+ else
+ {
+ mFloatClearShader =
+ new ClearShader(DXGI_FORMAT_R32G32B32A32_FLOAT, "Clear11 Float IL", g_VS_ClearFloat,
+ ArraySize(g_VS_ClearFloat), "Clear11 Float VS", g_PS_ClearFloat,
+ ArraySize(g_PS_ClearFloat), "Clear11 Float PS");
+ }
+
+ if (renderer->isES3Capable())
+ {
+ mUintClearShader =
+ new ClearShader(DXGI_FORMAT_R32G32B32A32_UINT, "Clear11 UINT IL", g_VS_ClearUint,
+ ArraySize(g_VS_ClearUint), "Clear11 UINT VS", g_PS_ClearUint,
+ ArraySize(g_PS_ClearUint), "Clear11 UINT PS");
+ mIntClearShader =
+ new ClearShader(DXGI_FORMAT_R32G32B32A32_UINT, "Clear11 SINT IL", g_VS_ClearSint,
+ ArraySize(g_VS_ClearSint), "Clear11 SINT VS", g_PS_ClearSint,
+ ArraySize(g_PS_ClearSint), "Clear11 SINT PS");
+ }
+}
+
+Clear11::~Clear11()
+{
+ for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end();
+ i++)
+ {
+ SafeRelease(i->second);
+ }
+ mClearBlendStates.clear();
+
+ SafeDelete(mFloatClearShader);
+ SafeDelete(mUintClearShader);
+ SafeDelete(mIntClearShader);
+
+ for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin();
+ i != mClearDepthStencilStates.end(); i++)
+ {
+ SafeRelease(i->second);
+ }
+ mClearDepthStencilStates.clear();
+
+ SafeRelease(mVertexBuffer);
+ SafeRelease(mRasterizerState);
+}
+
+gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
+ const gl::FramebufferState &fboData)
+{
+ const auto &colorAttachments = fboData.getColorAttachments();
+ const auto &drawBufferStates = fboData.getDrawBufferStates();
+ const auto *depthAttachment = fboData.getDepthAttachment();
+ const auto *stencilAttachment = fboData.getStencilAttachment();
+
+ ASSERT(colorAttachments.size() == drawBufferStates.size());
+
+ // 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 draw a quad.
+ //
+ // Also determine if the depth stencil can be cleared with
+ // ID3D11DeviceContext::ClearDepthStencilView
+ // by checking if the stencil write mask covers the entire stencil.
+ //
+ // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex
+ // color
+ // attribute.
+
+ gl::Extents framebufferSize;
+
+ const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment();
+ if (colorAttachment != nullptr)
+ {
+ framebufferSize = colorAttachment->getSize();
+ }
+ else if (depthAttachment != nullptr)
+ {
+ framebufferSize = depthAttachment->getSize();
+ }
+ else if (stencilAttachment != nullptr)
+ {
+ framebufferSize = stencilAttachment->getSize();
+ }
+ else
+ {
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+ }
+
+ if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width ||
+ clearParams.scissor.y >= framebufferSize.height ||
+ clearParams.scissor.x + clearParams.scissor.width <= 0 ||
+ clearParams.scissor.y + clearParams.scissor.height <= 0))
+ {
+ // Scissor is enabled and the scissor rectangle is outside the renderbuffer
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ bool needScissoredClear =
+ clearParams.scissorEnabled &&
+ (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 ||
+ clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width ||
+ clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height);
+
+ std::vector<MaskedRenderTarget> maskedClearRenderTargets;
+ RenderTarget11 *maskedClearDepthStencil = nullptr;
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
+ ID3D11Device *device = mRenderer->getDevice();
+
+ for (size_t colorAttachmentIndex = 0; colorAttachmentIndex < colorAttachments.size();
+ colorAttachmentIndex++)
+ {
+ const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachmentIndex];
+
+ if (clearParams.clearColor[colorAttachmentIndex] && attachment.isAttached() &&
+ drawBufferStates[colorAttachmentIndex] != GL_NONE)
+ {
+ RenderTarget11 *renderTarget = nullptr;
+ ANGLE_TRY(attachment.getRenderTarget(&renderTarget));
+
+ const gl::InternalFormat &formatInfo = *attachment.getFormat().info;
+
+ if (clearParams.colorClearType == GL_FLOAT &&
+ !(formatInfo.componentType == GL_FLOAT ||
+ formatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+ formatInfo.componentType == GL_SIGNED_NORMALIZED))
+ {
+ ERR("It is undefined behaviour to clear a render buffer which is not normalized "
+ "fixed point or floating-"
+ "point to floating point values (color attachment %u has internal format "
+ "0x%X).",
+ colorAttachmentIndex, attachment.getFormat().asSized());
+ }
+
+ if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) &&
+ (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) &&
+ (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) &&
+ (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha))
+ {
+ // Every channel either does not exist in the render target or is masked out
+ continue;
+ }
+ else if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) &&
+ needScissoredClear) ||
+ clearParams.colorClearType != GL_FLOAT ||
+ (formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
+ (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
+ (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
+ (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
+ {
+ // A masked clear is required, or a scissored clear is required and
+ // ID3D11DeviceContext1::ClearView is unavailable
+ MaskedRenderTarget maskAndRt;
+ bool clearColor = clearParams.clearColor[colorAttachmentIndex];
+ maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed);
+ maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen);
+ maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue);
+ maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha);
+ maskAndRt.renderTarget = renderTarget;
+ maskedClearRenderTargets.push_back(maskAndRt);
+ }
+ else
+ {
+ // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is
+ // possible
+
+ ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
+ if (!framebufferRTV)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Internal render target view pointer unexpectedly null.");
+ }
+
+ 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.colorFClearValue.red),
+ ((formatInfo.greenBits == 0 && nativeFormat.greenBits > 0)
+ ? 0.0f
+ : clearParams.colorFClearValue.green),
+ ((formatInfo.blueBits == 0 && nativeFormat.blueBits > 0)
+ ? 0.0f
+ : clearParams.colorFClearValue.blue),
+ ((formatInfo.alphaBits == 0 && nativeFormat.alphaBits > 0)
+ ? 1.0f
+ : clearParams.colorFClearValue.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.colorFClearValue.alpha >= 0.5f) ? 1.0f : 0.0f;
+ }
+
+ if (needScissoredClear)
+ {
+ // We shouldn't reach here if deviceContext1 is unavailable.
+ ASSERT(deviceContext1);
+
+ D3D11_RECT rect;
+ rect.left = clearParams.scissor.x;
+ rect.right = clearParams.scissor.x + clearParams.scissor.width;
+ rect.top = clearParams.scissor.y;
+ rect.bottom = clearParams.scissor.y + clearParams.scissor.height;
+
+ deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1);
+
+ if (mRenderer->getWorkarounds().callClearTwice)
+ {
+ deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1);
+ }
+ }
+ else
+ {
+ deviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
+
+ if (mRenderer->getWorkarounds().callClearTwice)
+ {
+ deviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
+ }
+ }
+ }
+ }
+ }
+
+ if (clearParams.clearDepth || clearParams.clearStencil)
+ {
+ const gl::FramebufferAttachment *attachment =
+ (depthAttachment != nullptr) ? depthAttachment : stencilAttachment;
+ ASSERT(attachment != nullptr);
+
+ RenderTarget11 *renderTarget = nullptr;
+ ANGLE_TRY(attachment->getRenderTarget(&renderTarget));
+
+ const auto &nativeFormat = renderTarget->getFormatSet().format();
+
+ unsigned int stencilUnmasked =
+ (stencilAttachment != nullptr) ? (1 << nativeFormat.stencilBits) - 1 : 0;
+ bool needMaskedStencilClear =
+ clearParams.clearStencil &&
+ (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
+
+ if (needScissoredClear || needMaskedStencilClear)
+ {
+ maskedClearDepthStencil = renderTarget;
+ }
+ else
+ {
+ ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
+ if (!framebufferDSV)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Internal depth stencil view pointer unexpectedly null.");
+ }
+
+ UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) |
+ (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0);
+ FLOAT depthClear = gl::clamp01(clearParams.depthClearValue);
+ UINT8 stencilClear = clearParams.stencilClearValue & 0xFF;
+
+ deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear,
+ stencilClear);
+ }
+ }
+
+ if (maskedClearRenderTargets.empty() && !maskedClearDepthStencil)
+ {
+ return gl::NoError();
+ }
+
+ // To clear the render targets and depth stencil in one pass:
+ //
+ // Render a quad clipped to the scissor rectangle which draws the clear color and a blend
+ // state that will perform the required color masking.
+ //
+ // The quad's depth is equal to the depth clear value with a depth stencil state that
+ // will enable or disable depth test/writes if the depth buffer should be cleared or not.
+ //
+ // The rasterizer state's stencil is set to always pass or fail based on if the stencil
+ // should be cleared or not with a stencil write mask of the stencil clear value.
+ //
+ // ======================================================================================
+ //
+ // 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.
+
+ // Bind all the render targets which need clearing
+ ASSERT(maskedClearRenderTargets.size() <= mRenderer->getNativeCaps().maxDrawBuffers);
+ std::vector<ID3D11RenderTargetView *> rtvs(maskedClearRenderTargets.size());
+ for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++)
+ {
+ RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget;
+ ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView();
+ if (!rtv)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Internal render target view pointer unexpectedly null.");
+ }
+
+ rtvs[i] = rtv;
+ }
+ ID3D11DepthStencilView *dsv =
+ maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : nullptr;
+
+ ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets);
+ const FLOAT blendFactors[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ const UINT sampleMask = 0xFFFFFFFF;
+
+ ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams);
+ const UINT stencilClear = clearParams.stencilClearValue & 0xFF;
+
+ // Set the vertices
+ UINT vertexStride = 0;
+ const UINT startIdx = 0;
+ ClearShader *shader = nullptr;
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result =
+ deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.",
+ result);
+ }
+
+ const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : nullptr;
+ switch (clearParams.colorClearType)
+ {
+ case GL_FLOAT:
+ ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue,
+ clearParams.depthClearValue, mappedResource.pData);
+ vertexStride = sizeof(d3d11::PositionDepthColorVertex<float>);
+ shader = mFloatClearShader;
+ break;
+
+ case GL_UNSIGNED_INT:
+ ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue,
+ clearParams.depthClearValue, mappedResource.pData);
+ vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>);
+ shader = mUintClearShader;
+ break;
+
+ case GL_INT:
+ ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue,
+ clearParams.depthClearValue, mappedResource.pData);
+ vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>);
+ shader = mIntClearShader;
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ deviceContext->Unmap(mVertexBuffer, 0);
+
+ // Set the viewport to be the same size as the framebuffer
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = static_cast<FLOAT>(framebufferSize.width);
+ viewport.Height = static_cast<FLOAT>(framebufferSize.height);
+ viewport.MinDepth = 0;
+ viewport.MaxDepth = 1;
+ deviceContext->RSSetViewports(1, &viewport);
+
+ // Apply state
+ deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
+ deviceContext->OMSetDepthStencilState(dsState, stencilClear);
+ deviceContext->RSSetState(mRasterizerState);
+
+ // Apply shaders
+ deviceContext->IASetInputLayout(shader->inputLayout->resolve(device));
+ deviceContext->VSSetShader(shader->vertexShader.resolve(device), nullptr, 0);
+ deviceContext->PSSetShader(shader->pixelShader.resolve(device), nullptr, 0);
+ deviceContext->GSSetShader(nullptr, nullptr, 0);
+
+ // Apply vertex buffer
+ deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx);
+ deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+
+ // Apply render targets
+ mRenderer->getStateManager()->setOneTimeRenderTargets(rtvs, dsv);
+
+ // Draw the clear quad
+ deviceContext->Draw(4, 0);
+
+ // Clean up
+ mRenderer->markAllStateDirty();
+
+ return gl::NoError();
+}
+
+ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget> &rts)
+{
+ ClearBlendInfo blendKey = {};
+ for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ {
+ if (i < rts.size())
+ {
+ RenderTarget11 *rt = rts[i].renderTarget;
+ const gl::InternalFormat &formatInfo =
+ gl::GetInternalFormatInfo(rt->getInternalFormat());
+
+ blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && formatInfo.redBits > 0);
+ blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && formatInfo.greenBits > 0);
+ blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && formatInfo.blueBits > 0);
+ blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && formatInfo.alphaBits > 0);
+ }
+ else
+ {
+ blendKey.maskChannels[i][0] = false;
+ blendKey.maskChannels[i][1] = false;
+ blendKey.maskChannels[i][2] = false;
+ blendKey.maskChannels[i][3] = false;
+ }
+ }
+
+ ClearBlendStateMap::const_iterator i = mClearBlendStates.find(blendKey);
+ if (i != mClearBlendStates.end())
+ {
+ return i->second;
+ }
+ else
+ {
+ D3D11_BLEND_DESC blendDesc = {0};
+ blendDesc.AlphaToCoverageEnable = FALSE;
+ blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE;
+
+ for (unsigned int j = 0; j < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; j++)
+ {
+ blendDesc.RenderTarget[j].BlendEnable = FALSE;
+ blendDesc.RenderTarget[j].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(
+ blendKey.maskChannels[j][0], blendKey.maskChannels[j][1],
+ blendKey.maskChannels[j][2], blendKey.maskChannels[j][3]);
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11BlendState *blendState = nullptr;
+ HRESULT result = device->CreateBlendState(&blendDesc, &blendState);
+ if (FAILED(result) || !blendState)
+ {
+ ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
+ return nullptr;
+ }
+
+ mClearBlendStates[blendKey] = blendState;
+
+ return blendState;
+ }
+}
+
+ID3D11DepthStencilState *Clear11::getDepthStencilState(const ClearParameters &clearParams)
+{
+ ClearDepthStencilInfo dsKey = {0};
+ dsKey.clearDepth = clearParams.clearDepth;
+ dsKey.clearStencil = clearParams.clearStencil;
+ dsKey.stencilWriteMask = clearParams.stencilWriteMask & 0xFF;
+
+ ClearDepthStencilStateMap::const_iterator i = mClearDepthStencilStates.find(dsKey);
+ if (i != mClearDepthStencilStates.end())
+ {
+ return i->second;
+ }
+ else
+ {
+ D3D11_DEPTH_STENCIL_DESC dsDesc = {0};
+ dsDesc.DepthEnable = dsKey.clearDepth ? TRUE : FALSE;
+ dsDesc.DepthWriteMask =
+ dsKey.clearDepth ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
+ dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
+ dsDesc.StencilEnable = dsKey.clearStencil ? TRUE : FALSE;
+ dsDesc.StencilReadMask = 0;
+ dsDesc.StencilWriteMask = dsKey.stencilWriteMask;
+ dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE;
+ dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
+ dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
+ dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+ dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE;
+ dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
+ dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
+ dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DepthStencilState *dsState = nullptr;
+ HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState);
+ if (FAILED(result) || !dsState)
+ {
+ ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
+ return nullptr;
+ }
+
+ mClearDepthStencilStates[dsKey] = dsState;
+
+ return dsState;
+ }
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h
new file mode 100755
index 000000000..1594027ec
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 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/angletypes.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+class Renderer11;
+class RenderTarget11;
+struct ClearParameters;
+
+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.
+ gl::Error clearFramebuffer(const ClearParameters &clearParams,
+ const gl::FramebufferState &fboData);
+
+ private:
+ struct MaskedRenderTarget
+ {
+ bool colorMask[4];
+ RenderTarget11 *renderTarget;
+ };
+
+ ID3D11BlendState *getBlendState(const std::vector<MaskedRenderTarget> &rts);
+ ID3D11DepthStencilState *getDepthStencilState(const ClearParameters &clearParams);
+
+ struct ClearShader final : public angle::NonCopyable
+ {
+ ClearShader(DXGI_FORMAT colorType,
+ const char *inputLayoutName,
+ const BYTE *vsByteCode,
+ size_t vsSize,
+ const char *vsDebugName,
+ const BYTE *psByteCode,
+ size_t psSize,
+ const char *psDebugName);
+ ~ClearShader();
+
+ d3d11::LazyInputLayout *inputLayout;
+ d3d11::LazyShader<ID3D11VertexShader> vertexShader;
+ d3d11::LazyShader<ID3D11PixelShader> pixelShader;
+ };
+
+ template <unsigned int vsSize, unsigned int psSize>
+ static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE(&vsByteCode)[vsSize], const BYTE(&psByteCode)[psSize]);
+
+ struct ClearBlendInfo
+ {
+ bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4];
+ };
+ typedef bool(*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &);
+ typedef std::map<ClearBlendInfo, ID3D11BlendState*, ClearBlendInfoComparisonFunction> ClearBlendStateMap;
+
+ struct ClearDepthStencilInfo
+ {
+ bool clearDepth;
+ bool clearStencil;
+ UINT8 stencilWriteMask;
+ };
+ typedef bool(*ClearDepthStencilInfoComparisonFunction)(const ClearDepthStencilInfo&, const ClearDepthStencilInfo &);
+ typedef std::map<ClearDepthStencilInfo, ID3D11DepthStencilState*, ClearDepthStencilInfoComparisonFunction> ClearDepthStencilStateMap;
+
+ Renderer11 *mRenderer;
+
+ ClearBlendStateMap mClearBlendStates;
+
+ ClearShader *mFloatClearShader;
+ ClearShader *mUintClearShader;
+ ClearShader *mIntClearShader;
+
+ ClearDepthStencilStateMap mClearDepthStencilStates;
+
+ ID3D11Buffer *mVertexBuffer;
+ ID3D11RasterizerState *mRasterizerState;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
new file mode 100755
index 000000000..05da453f0
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
@@ -0,0 +1,270 @@
+//
+// 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/string_utils.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/SamplerD3D.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/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+
+namespace rx
+{
+
+Context11::Context11(const gl::ContextState &state, Renderer11 *renderer)
+ : ContextImpl(state), mRenderer(renderer)
+{
+}
+
+Context11::~Context11()
+{
+}
+
+gl::Error Context11::initialize()
+{
+ return gl::NoError();
+}
+
+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->getWorkarounds());
+}
+
+ProgramImpl *Context11::createProgram(const gl::ProgramState &data)
+{
+ return new ProgramD3D(data, mRenderer);
+}
+
+FramebufferImpl *Context11::createFramebuffer(const gl::FramebufferState &data)
+{
+ return new Framebuffer11(data, mRenderer);
+}
+
+TextureImpl *Context11::createTexture(const gl::TextureState &state)
+{
+ switch (state.getTarget())
+ {
+ case GL_TEXTURE_2D:
+ return new TextureD3D_2D(state, mRenderer);
+ case GL_TEXTURE_CUBE_MAP:
+ return new TextureD3D_Cube(state, mRenderer);
+ case GL_TEXTURE_3D:
+ return new TextureD3D_3D(state, mRenderer);
+ case GL_TEXTURE_2D_ARRAY:
+ return new TextureD3D_2DArray(state, mRenderer);
+ case GL_TEXTURE_EXTERNAL_OES:
+ return new TextureD3D_External(state, mRenderer);
+ default:
+ UNREACHABLE();
+ }
+
+ return nullptr;
+}
+
+RenderbufferImpl *Context11::createRenderbuffer()
+{
+ return new RenderbufferD3D(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(GLenum type)
+{
+ return new Query11(mRenderer, type);
+}
+
+FenceNVImpl *Context11::createFenceNV()
+{
+ return new FenceNV11(mRenderer);
+}
+
+FenceSyncImpl *Context11::createFenceSync()
+{
+ return new FenceSync11(mRenderer);
+}
+
+TransformFeedbackImpl *Context11::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+ return new TransformFeedback11(state, mRenderer);
+}
+
+SamplerImpl *Context11::createSampler()
+{
+ return new SamplerD3D();
+}
+
+std::vector<PathImpl *> Context11::createPaths(GLsizei)
+{
+ return std::vector<PathImpl *>();
+}
+
+gl::Error Context11::flush()
+{
+ return mRenderer->flush();
+}
+
+gl::Error Context11::finish()
+{
+ return mRenderer->finish();
+}
+
+gl::Error Context11::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ return mRenderer->genericDrawArrays(this, mode, first, count, 1);
+}
+
+gl::Error Context11::drawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ return mRenderer->genericDrawArrays(this, mode, first, count, instanceCount);
+}
+
+gl::Error Context11::drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange)
+{
+ return mRenderer->genericDrawElements(this, mode, count, type, indices, 1, indexRange);
+}
+
+gl::Error Context11::drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange)
+{
+ return mRenderer->genericDrawElements(this, mode, count, type, indices, instances, indexRange);
+}
+
+gl::Error Context11::drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange)
+{
+ return mRenderer->genericDrawElements(this, mode, count, type, indices, 1, indexRange);
+}
+
+GLenum Context11::getResetStatus()
+{
+ return mRenderer->getResetStatus();
+}
+
+std::string Context11::getVendorString() const
+{
+ return mRenderer->getVendorString();
+}
+
+std::string Context11::getRendererDescription() const
+{
+ return mRenderer->getRendererDescription();
+}
+
+void Context11::insertEventMarker(GLsizei length, const char *marker)
+{
+ auto optionalString = angle::WidenString(static_cast<size_t>(length), marker);
+ if (optionalString.valid())
+ {
+ mRenderer->getAnnotator()->setMarker(optionalString.value().data());
+ }
+}
+
+void Context11::pushGroupMarker(GLsizei length, const char *marker)
+{
+ auto optionalString = angle::WidenString(static_cast<size_t>(length), marker);
+ if (optionalString.valid())
+ {
+ mRenderer->getAnnotator()->beginEvent(optionalString.value().data());
+ }
+}
+
+void Context11::popGroupMarker()
+{
+ mRenderer->getAnnotator()->endEvent();
+}
+
+void Context11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
+{
+ mRenderer->getStateManager()->syncState(state, dirtyBits);
+}
+
+GLint Context11::getGPUDisjoint()
+{
+ return mRenderer->getGPUDisjoint();
+}
+
+GLint64 Context11::getTimestamp()
+{
+ return mRenderer->getTimestamp();
+}
+
+void Context11::onMakeCurrent(const gl::ContextState &data)
+{
+ mRenderer->getStateManager()->onMakeCurrent(data);
+}
+
+const gl::Caps &Context11::getNativeCaps() const
+{
+ return mRenderer->getNativeCaps();
+}
+
+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();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h
new file mode 100755
index 000000000..e36a6e978
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h
@@ -0,0 +1,128 @@
+//
+// 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 "libANGLE/renderer/ContextImpl.h"
+
+namespace rx
+{
+class Renderer11;
+
+class Context11 : public ContextImpl
+{
+ public:
+ Context11(const gl::ContextState &state, Renderer11 *renderer);
+ ~Context11() override;
+
+ gl::Error initialize() 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() 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(GLenum type) override;
+ FenceNVImpl *createFenceNV() override;
+ FenceSyncImpl *createFenceSync() override;
+
+ // Transform Feedback creation
+ TransformFeedbackImpl *createTransformFeedback(
+ const gl::TransformFeedbackState &state) override;
+
+ // Sampler object creation
+ SamplerImpl *createSampler() override;
+
+ // Path object creation.
+ std::vector<PathImpl *> createPaths(GLsizei) override;
+
+ // Flush and finish.
+ gl::Error flush() override;
+ gl::Error finish() override;
+
+ // Drawing methods.
+ gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override;
+ gl::Error drawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) override;
+
+ gl::Error drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange) override;
+ gl::Error drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange) override;
+ gl::Error drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange) override;
+
+ // Device loss
+ GLenum getResetStatus() override;
+
+ // Vendor and description strings.
+ std::string getVendorString() const override;
+ std::string getRendererDescription() const override;
+
+ // Debug markers.
+ void insertEventMarker(GLsizei length, const char *marker) override;
+ void pushGroupMarker(GLsizei length, const char *marker) override;
+ void popGroupMarker() override;
+
+ // State sync with dirty bits.
+ void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) override;
+
+ // Disjoint timer queries
+ GLint getGPUDisjoint() override;
+ GLint64 getTimestamp() override;
+
+ // Context switching
+ void onMakeCurrent(const gl::ContextState &data) override;
+
+ // Caps queries
+ const gl::Caps &getNativeCaps() const override;
+ const gl::TextureCapsMap &getNativeTextureCaps() const override;
+ const gl::Extensions &getNativeExtensions() const override;
+ const gl::Limitations &getNativeLimitations() const override;
+
+ Renderer11 *getRenderer() const { return mRenderer; }
+
+ private:
+ Renderer11 *mRenderer;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
new file mode 100755
index 000000000..93343f281
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
@@ -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.
+//
+// DebugAnnotator11.cpp: D3D11 helpers for adding trace annotations.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+DebugAnnotator11::DebugAnnotator11()
+ : mInitialized(false),
+ mD3d11Module(nullptr),
+ mUserDefinedAnnotation(nullptr)
+{
+ // D3D11 devices can't be created during DllMain.
+ // We defer device creation until the object is actually used.
+}
+
+DebugAnnotator11::~DebugAnnotator11()
+{
+ if (mInitialized)
+ {
+ SafeRelease(mUserDefinedAnnotation);
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ FreeLibrary(mD3d11Module);
+#endif // !ANGLE_ENABLE_WINDOWS_STORE
+ }
+}
+
+void DebugAnnotator11::beginEvent(const wchar_t *eventName)
+{
+ initializeDevice();
+
+ if (mUserDefinedAnnotation != nullptr)
+ {
+ mUserDefinedAnnotation->BeginEvent(eventName);
+ }
+}
+
+void DebugAnnotator11::endEvent()
+{
+ initializeDevice();
+
+ if (mUserDefinedAnnotation != nullptr)
+ {
+ mUserDefinedAnnotation->EndEvent();
+ }
+}
+
+void DebugAnnotator11::setMarker(const wchar_t *markerName)
+{
+ initializeDevice();
+
+ if (mUserDefinedAnnotation != nullptr)
+ {
+ mUserDefinedAnnotation->SetMarker(markerName);
+ }
+}
+
+bool DebugAnnotator11::getStatus()
+{
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+ static_assert(NTDDI_VERSION >= NTDDI_WIN10, "GetStatus only works on Win10 and above");
+ initializeDevice();
+
+ if (mUserDefinedAnnotation != nullptr)
+ {
+ return !!(mUserDefinedAnnotation->GetStatus());
+ }
+
+ return true; // Default if initializeDevice() failed
+#else
+ // We can't detect GetStatus() on desktop ANGLE builds so always return true.
+ return true;
+#endif // ANGLE_ENABLE_WINDOWS_STORE
+}
+
+void DebugAnnotator11::initializeDevice()
+{
+ if (!mInitialized)
+ {
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+ ASSERT(mD3d11Module);
+
+ PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
+ ASSERT(D3D11CreateDevice != nullptr);
+#endif // !ANGLE_ENABLE_WINDOWS_STORE
+
+ ID3D11Device *device = nullptr;
+ ID3D11DeviceContext *context = nullptr;
+
+ HRESULT hr = E_FAIL;
+
+ // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device.
+ hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &device, nullptr, &context);
+ ASSERT(SUCCEEDED(hr));
+ if (SUCCEEDED(hr))
+ {
+ mUserDefinedAnnotation = d3d11::DynamicCastComObject<ID3DUserDefinedAnnotation>(context);
+ ASSERT(mUserDefinedAnnotation != nullptr);
+ mInitialized = true;
+ }
+
+ SafeRelease(device);
+ SafeRelease(context);
+ }
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
new file mode 100755
index 000000000..9da4fa220
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
@@ -0,0 +1,37 @@
+//
+// 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 "common/debug.h"
+
+namespace rx
+{
+
+class DebugAnnotator11 : public gl::DebugAnnotator
+{
+ public:
+ DebugAnnotator11();
+ ~DebugAnnotator11() override;
+ void beginEvent(const wchar_t *eventName) override;
+ void endEvent() override;
+ void setMarker(const wchar_t *markerName) override;
+ bool getStatus() override;
+
+ private:
+ void initializeDevice();
+
+ bool mInitialized;
+ HMODULE mD3d11Module;
+ ID3DUserDefinedAnnotation *mUserDefinedAnnotation;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp
new file mode 100755
index 000000000..1f0eedb6e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp
@@ -0,0 +1,237 @@
+//
+// Copyright (c) 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::FenceSync11 classes which implement
+// rx::FenceNVImpl and rx::FenceSyncImpl.
+
+#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+#include "common/utilities.h"
+
+namespace rx
+{
+
+static const int kDeviceLostCheckPeriod = 64;
+
+//
+// Template helpers for set and test operations.
+//
+
+template <class FenceClass>
+gl::Error FenceSetHelper(FenceClass *fence)
+{
+ if (!fence->mQuery)
+ {
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = D3D11_QUERY_EVENT;
+ queryDesc.MiscFlags = 0;
+
+ HRESULT result = fence->mRenderer->getDevice()->CreateQuery(&queryDesc, &fence->mQuery);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.",
+ result);
+ }
+ }
+
+ fence->mRenderer->getDeviceContext()->End(fence->mQuery);
+ return gl::Error(GL_NO_ERROR);
+}
+
+template <class FenceClass>
+gl::Error FenceTestHelper(FenceClass *fence, bool flushCommandBuffer, GLboolean *outFinished)
+{
+ ASSERT(fence->mQuery);
+
+ UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH);
+ HRESULT result =
+ fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, NULL, 0, getDataFlags);
+
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result);
+ }
+
+ ASSERT(result == S_OK || result == S_FALSE);
+ *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
+ return gl::Error(GL_NO_ERROR);
+}
+
+//
+// FenceNV11
+//
+
+FenceNV11::FenceNV11(Renderer11 *renderer) : FenceNVImpl(), mRenderer(renderer), mQuery(NULL)
+{
+}
+
+FenceNV11::~FenceNV11()
+{
+ SafeRelease(mQuery);
+}
+
+gl::Error FenceNV11::set(GLenum condition)
+{
+ return FenceSetHelper(this);
+}
+
+gl::Error FenceNV11::test(GLboolean *outFinished)
+{
+ return FenceTestHelper(this, true, outFinished);
+}
+
+gl::Error FenceNV11::finish()
+{
+ GLboolean finished = GL_FALSE;
+
+ int loopCount = 0;
+ while (finished != GL_TRUE)
+ {
+ loopCount++;
+ ANGLE_TRY(FenceTestHelper(this, true, &finished));
+
+ if (loopCount % kDeviceLostCheckPeriod == 0 && mRenderer->testDeviceLost())
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Device was lost while querying result of an event query.");
+ }
+
+ ScheduleYield();
+ }
+
+ return gl::NoError();
+}
+
+//
+// FenceSync11
+//
+
+// 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.
+
+FenceSync11::FenceSync11(Renderer11 *renderer) : FenceSyncImpl(), mRenderer(renderer), mQuery(NULL)
+{
+ LARGE_INTEGER counterFreqency = {};
+ BOOL success = QueryPerformanceFrequency(&counterFreqency);
+ ASSERT(success);
+
+ mCounterFrequency = counterFreqency.QuadPart;
+}
+
+FenceSync11::~FenceSync11()
+{
+ SafeRelease(mQuery);
+}
+
+gl::Error FenceSync11::set(GLenum condition, GLbitfield flags)
+{
+ ASSERT(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0);
+ return FenceSetHelper(this);
+}
+
+gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+{
+ ASSERT(outResult);
+
+ bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0);
+
+ GLboolean result = GL_FALSE;
+ gl::Error error = FenceTestHelper(this, flushCommandBuffer, &result);
+ if (error.isError())
+ {
+ *outResult = GL_WAIT_FAILED;
+ return error;
+ }
+
+ if (result == GL_TRUE)
+ {
+ *outResult = GL_ALREADY_SIGNALED;
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ if (timeout == 0)
+ {
+ *outResult = GL_TIMEOUT_EXPIRED;
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ LARGE_INTEGER currentCounter = {};
+ BOOL success = QueryPerformanceCounter(&currentCounter);
+ ASSERT(success);
+
+ LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll);
+ LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;
+
+ int loopCount = 0;
+ while (currentCounter.QuadPart < endCounter && !result)
+ {
+ loopCount++;
+ ScheduleYield();
+ success = QueryPerformanceCounter(&currentCounter);
+ ASSERT(success);
+
+ error = FenceTestHelper(this, flushCommandBuffer, &result);
+ if (error.isError())
+ {
+ *outResult = GL_WAIT_FAILED;
+ return error;
+ }
+
+ if ((loopCount % kDeviceLostCheckPeriod) == 0 && mRenderer->testDeviceLost())
+ {
+ *outResult = GL_WAIT_FAILED;
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Device was lost while querying result of an event query.");
+ }
+ }
+
+ if (currentCounter.QuadPart >= endCounter)
+ {
+ *outResult = GL_TIMEOUT_EXPIRED;
+ }
+ else
+ {
+ *outResult = GL_CONDITION_SATISFIED;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FenceSync11::serverWait(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 gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FenceSync11::getStatus(GLint *outResult)
+{
+ GLboolean result = GL_FALSE;
+ gl::Error error = FenceTestHelper(this, false, &result);
+ if (error.isError())
+ {
+ // 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;
+
+ return error;
+ }
+
+ *outResult = (result ? GL_SIGNALED : GL_UNSIGNALED);
+ return gl::Error(GL_NO_ERROR);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h
new file mode 100755
index 000000000..595978885
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 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::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
+
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+namespace rx
+{
+class Renderer11;
+
+class FenceNV11 : public FenceNVImpl
+{
+ public:
+ explicit FenceNV11(Renderer11 *renderer);
+ ~FenceNV11() override;
+
+ gl::Error set(GLenum condition) override;
+ gl::Error test(GLboolean *outFinished) override;
+ gl::Error finish() override;
+
+ private:
+ template<class T> friend gl::Error FenceSetHelper(T *fence);
+ template<class T> friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished);
+
+ Renderer11 *mRenderer;
+ ID3D11Query *mQuery;
+};
+
+class FenceSync11 : public FenceSyncImpl
+{
+ public:
+ explicit FenceSync11(Renderer11 *renderer);
+ ~FenceSync11() override;
+
+ gl::Error set(GLenum condition, GLbitfield flags) override;
+ gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override;
+ gl::Error serverWait(GLbitfield flags, GLuint64 timeout) override;
+ gl::Error getStatus(GLint *outResult) override;
+
+ private:
+ template<class T> friend gl::Error FenceSetHelper(T *fence);
+ template<class T> friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished);
+
+ Renderer11 *mRenderer;
+ ID3D11Query *mQuery;
+ LONGLONG mCounterFrequency;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
new file mode 100755
index 000000000..90922914a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
@@ -0,0 +1,441 @@
+//
+// 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/debug.h"
+#include "common/BitSetIterator.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Texture.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace
+{
+gl::Error MarkAttachmentsDirty(const gl::FramebufferAttachment *attachment)
+{
+ if (attachment && attachment->type() == GL_TEXTURE)
+ {
+ gl::Texture *texture = attachment->getTexture();
+
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+
+ TextureStorage *texStorage = nullptr;
+ ANGLE_TRY(textureD3D->getNativeTexture(&texStorage));
+
+ if (texStorage)
+ {
+ TextureStorage11 *texStorage11 = GetAs<TextureStorage11>(texStorage);
+ ASSERT(texStorage11);
+
+ texStorage11->markLevelDirty(attachment->mipLevel());
+ }
+ }
+
+ return gl::NoError();
+}
+
+void UpdateCachedRenderTarget(const gl::FramebufferAttachment *attachment,
+ RenderTarget11 *&cachedRenderTarget,
+ ChannelBinding *channelBinding)
+{
+ RenderTarget11 *newRenderTarget = nullptr;
+ if (attachment)
+ {
+ attachment->getRenderTarget(&newRenderTarget);
+ }
+ if (newRenderTarget != cachedRenderTarget)
+ {
+ auto channel = (newRenderTarget ? newRenderTarget->getBroadcastChannel() : nullptr);
+ channelBinding->bind(channel);
+ cachedRenderTarget = newRenderTarget;
+ }
+}
+} // anonymous namespace
+
+Framebuffer11::Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer)
+ : FramebufferD3D(data, renderer),
+ mRenderer(renderer),
+ mCachedDepthStencilRenderTarget(nullptr),
+ mDepthStencilRenderTargetDirty(this, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS)
+{
+ ASSERT(mRenderer != nullptr);
+ mCachedColorRenderTargets.fill(nullptr);
+ for (size_t colorIndex = 0; colorIndex < data.getColorAttachments().size(); ++colorIndex)
+ {
+ mColorRenderTargetsDirty.push_back(
+ ChannelBinding(this, static_cast<SignalToken>(colorIndex)));
+ }
+}
+
+Framebuffer11::~Framebuffer11()
+{
+}
+
+gl::Error Framebuffer11::markAttachmentsDirty() const
+{
+ for (const auto &colorAttachment : mState.getColorAttachments())
+ {
+ if (colorAttachment.isAttached())
+ {
+ ANGLE_TRY(MarkAttachmentsDirty(&colorAttachment));
+ }
+ }
+
+ ANGLE_TRY(MarkAttachmentsDirty(mState.getDepthAttachment()));
+ ANGLE_TRY(MarkAttachmentsDirty(mState.getStencilAttachment()));
+
+ return gl::NoError();
+}
+
+gl::Error Framebuffer11::clearImpl(ContextImpl *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(presentPathFastClearParams, mState));
+ }
+ else
+ {
+ ANGLE_TRY(clearer->clearFramebuffer(clearParams, mState));
+ }
+
+ ANGLE_TRY(markAttachmentsDirty());
+
+ return gl::NoError();
+}
+
+gl::Error Framebuffer11::invalidate(size_t count, const GLenum *attachments)
+{
+ return invalidateBase(count, attachments, false);
+}
+
+gl::Error Framebuffer11::discard(size_t count, const GLenum *attachments)
+{
+ return invalidateBase(count, attachments, true);
+}
+
+gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const
+{
+ ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
+
+ if (!deviceContext1)
+ {
+ // DiscardView() is only supported on ID3D11DeviceContext1
+ return gl::NoError();
+ }
+
+ 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));
+ auto colorAttachment = mState.getColorAttachment(colorIndex);
+ if (colorAttachment)
+ {
+ ANGLE_TRY(invalidateAttachment(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(mState.getDepthAttachment()));
+ }
+
+ if (discardStencil && mState.getStencilAttachment())
+ {
+ ANGLE_TRY(invalidateAttachment(mState.getStencilAttachment()));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Framebuffer11::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
+{
+ // A no-op implementation conforms to the spec, so don't call UNIMPLEMENTED()
+ return gl::NoError();
+}
+
+gl::Error Framebuffer11::invalidateAttachment(const gl::FramebufferAttachment *attachment) const
+{
+ ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
+ ASSERT(deviceContext1);
+ ASSERT(attachment && attachment->isAttached());
+
+ RenderTarget11 *renderTarget = nullptr;
+ ANGLE_TRY(attachment->getRenderTarget(&renderTarget));
+ ID3D11View *view = renderTarget->getRenderTargetView();
+
+ if (view != nullptr)
+ {
+ deviceContext1->DiscardView(view);
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Framebuffer11::readPixelsImpl(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixels) const
+{
+ const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
+ ASSERT(readAttachment);
+
+ gl::Buffer *packBuffer = pack.pixelBuffer.get();
+ if (packBuffer != nullptr)
+ {
+ Buffer11 *packBufferStorage = GetImplAs<Buffer11>(packBuffer);
+ PackPixelsParams packParams(area, format, type, static_cast<GLuint>(outputPitch), pack,
+ reinterpret_cast<ptrdiff_t>(pixels));
+
+ return packBufferStorage->packPixels(*readAttachment, packParams);
+ }
+
+ return mRenderer->readFromAttachment(*readAttachment, area, format, type,
+ static_cast<GLuint>(outputPitch), pack, pixels);
+}
+
+gl::Error Framebuffer11::blitImpl(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->getReadColorbuffer();
+ ASSERT(readBuffer);
+
+ RenderTargetD3D *readRenderTarget = nullptr;
+ ANGLE_TRY(readBuffer->getRenderTarget(&readRenderTarget));
+ ASSERT(readRenderTarget);
+
+ const auto &colorAttachments = mState.getColorAttachments();
+ const auto &drawBufferStates = mState.getDrawBufferStates();
+
+ 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(&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;
+ if (invertColorDest)
+ {
+ RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
+ actualDestArea.y = drawRenderTarget11->getHeight() - destArea.y;
+ actualDestArea.height = -destArea.height;
+ }
+
+ ANGLE_TRY(mRenderer->blitRenderbufferRect(
+ actualSourceArea, actualDestArea, readRenderTarget, drawRenderTarget, filter,
+ scissor, blitRenderTarget, false, false));
+ }
+ }
+ }
+
+ if (blitDepth || blitStencil)
+ {
+ const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer();
+ ASSERT(readBuffer);
+
+ RenderTargetD3D *readRenderTarget = nullptr;
+ ANGLE_TRY(readBuffer->getRenderTarget(&readRenderTarget));
+ ASSERT(readRenderTarget);
+
+ const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
+ ASSERT(drawBuffer);
+
+ RenderTargetD3D *drawRenderTarget = nullptr;
+ ANGLE_TRY(drawBuffer->getRenderTarget(&drawRenderTarget));
+ ASSERT(drawRenderTarget);
+
+ ANGLE_TRY(mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget,
+ drawRenderTarget, filter, scissor, false,
+ blitDepth, blitStencil));
+ }
+
+ ANGLE_TRY(markAttachmentsDirty());
+ return gl::NoError();
+}
+
+GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
+{
+ RenderTarget11 *renderTarget11 = GetAs<RenderTarget11>(renderTarget);
+ return renderTarget11->getFormatSet().format().fboImplementationInternalFormat;
+}
+
+void Framebuffer11::updateColorRenderTarget(size_t colorIndex)
+{
+ UpdateCachedRenderTarget(mState.getColorAttachment(colorIndex),
+ mCachedColorRenderTargets[colorIndex],
+ &mColorRenderTargetsDirty[colorIndex]);
+}
+
+void Framebuffer11::updateDepthStencilRenderTarget()
+{
+ UpdateCachedRenderTarget(mState.getDepthOrStencilAttachment(), mCachedDepthStencilRenderTarget,
+ &mDepthStencilRenderTargetDirty);
+}
+
+void Framebuffer11::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
+{
+ mRenderer->getStateManager()->invalidateRenderTarget();
+
+ const auto &mergedDirtyBits = dirtyBits | mInternalDirtyBits;
+ mInternalDirtyBits.reset();
+
+ for (auto dirtyBit : IterateBitSet(mergedDirtyBits))
+ {
+ switch (dirtyBit)
+ {
+ case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
+ case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
+ updateDepthStencilRenderTarget();
+ break;
+ case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
+ case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
+ break;
+ default:
+ {
+ ASSERT(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
+ dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
+ size_t colorIndex =
+ static_cast<size_t>(dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
+ updateColorRenderTarget(colorIndex);
+ break;
+ }
+ }
+ }
+
+ // We should not have dirtied any additional state during our sync.
+ ASSERT(!mInternalDirtyBits.any());
+
+ FramebufferD3D::syncState(dirtyBits);
+}
+
+void Framebuffer11::signal(SignalToken token)
+{
+ if (token == gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS)
+ {
+ // Stencil is redundant in this case.
+ mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT);
+ mCachedDepthStencilRenderTarget = nullptr;
+ }
+ else
+ {
+ mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 + token);
+ mCachedColorRenderTargets[token] = nullptr;
+ }
+}
+
+bool Framebuffer11::hasAnyInternalDirtyBit() const
+{
+ return mInternalDirtyBits.any();
+}
+
+void Framebuffer11::syncInternalState()
+{
+ syncState(gl::Framebuffer::DirtyBits());
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
new file mode 100755
index 000000000..b1683a206
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
@@ -0,0 +1,88 @@
+//
+// 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/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/signal_utils.h"
+
+namespace rx
+{
+class Renderer11;
+
+class Framebuffer11 : public FramebufferD3D, public angle::SignalReceiver
+{
+ public:
+ Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer);
+ virtual ~Framebuffer11();
+
+ gl::Error discard(size_t count, const GLenum *attachments) override;
+ gl::Error invalidate(size_t count, const GLenum *attachments) override;
+ gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
+
+ // Invalidate the cached swizzles of all bound texture attachments.
+ gl::Error markAttachmentsDirty() const;
+
+ void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
+
+ const RenderTargetArray &getCachedColorRenderTargets() const
+ {
+ return mCachedColorRenderTargets;
+ }
+ const RenderTarget11 *getCachedDepthStencilRenderTarget() const
+ {
+ return mCachedDepthStencilRenderTarget;
+ }
+
+ bool hasAnyInternalDirtyBit() const;
+ void syncInternalState();
+
+ void signal(angle::SignalToken token) override;
+
+ private:
+ gl::Error clearImpl(ContextImpl *context, const ClearParameters &clearParams) override;
+
+ gl::Error readPixelsImpl(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixels) const override;
+
+ gl::Error blitImpl(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;
+
+ gl::Error invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const;
+ gl::Error invalidateAttachment(const gl::FramebufferAttachment *attachment) const;
+
+ GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
+
+ void updateColorRenderTarget(size_t colorIndex);
+ void updateDepthStencilRenderTarget();
+
+ Renderer11 *const mRenderer;
+ RenderTargetArray mCachedColorRenderTargets;
+ RenderTarget11 *mCachedDepthStencilRenderTarget;
+
+ std::vector<angle::ChannelBinding> mColorRenderTargetsDirty;
+ angle::ChannelBinding mDepthStencilRenderTargetDirty;
+
+ gl::Framebuffer::DirtyBits mInternalDirtyBits;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
new file mode 100755
index 000000000..3c797f820
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -0,0 +1,643 @@
+//
+// Copyright (c) 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/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+
+namespace rx
+{
+
+Image11::Image11(Renderer11 *renderer)
+ : mRenderer(renderer),
+ mDXGIFormat(DXGI_FORMAT_UNKNOWN),
+ mStagingTexture(NULL),
+ mStagingSubresource(0),
+ mRecoverFromStorage(false),
+ mAssociatedStorage(NULL),
+ mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()),
+ mRecoveredFromStorageCount(0)
+{
+}
+
+Image11::~Image11()
+{
+ disassociateStorage();
+ releaseStagingTexture();
+}
+
+gl::Error Image11::generateMipmap(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(D3D11_MAP_WRITE, &destMapped));
+
+ D3D11_MAPPED_SUBRESOURCE srcMapped;
+ gl::Error error = src->map(D3D11_MAP_READ, &srcMapped);
+ if (error.isError())
+ {
+ dest->unmap();
+ return error;
+ }
+
+ const uint8_t *sourceData = reinterpret_cast<const uint8_t *>(srcMapped.pData);
+ uint8_t *destData = reinterpret_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->unmap();
+ src->unmap();
+
+ dest->markDirty();
+
+ return gl::NoError();
+}
+
+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) then isDirty should still return false.
+ if (mDirty && !mStagingTexture && !mRecoverFromStorage)
+ {
+ const Renderer11DeviceCaps &deviceCaps = mRenderer->getRenderer11DeviceCaps();
+ const auto &formatInfo = d3d11::Format::Get(mInternalFormat, deviceCaps);
+ if (formatInfo.dataInitializerFunction == nullptr)
+ {
+ return false;
+ }
+ }
+
+ return mDirty;
+}
+
+gl::Error Image11::copyToStorage(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(index, this));
+ }
+
+ ID3D11Resource *stagingTexture = NULL;
+ unsigned int stagingSubresourceIndex = 0;
+ ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex));
+ ANGLE_TRY(
+ storage11->updateSubresourceLevel(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 gl::NoError();
+}
+
+bool Image11::isAssociatedStorageValid(TextureStorage11 *textureStorage) const
+{
+ return (mAssociatedStorage == textureStorage);
+}
+
+gl::Error Image11::recoverFromAssociatedStorage()
+{
+ if (mRecoverFromStorage)
+ {
+ ANGLE_TRY(createStagingTexture());
+
+ bool textureStorageCorrect =
+ mAssociatedStorage->isAssociatedImageValid(mAssociatedImageIndex, this);
+
+ // This means that the cached TextureStorage has been modified after this Image11 released
+ // its copy of its data. This should not have happened. The TextureStorage should have told
+ // this Image11 to recover its data before it was overwritten.
+ ASSERT(textureStorageCorrect);
+
+ if (textureStorageCorrect)
+ {
+ // CopySubResource from the Storage to the Staging texture
+ gl::Box region(0, 0, 0, mWidth, mHeight, mDepth);
+ ANGLE_TRY(mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource,
+ mAssociatedImageIndex, region));
+ mRecoveredFromStorageCount += 1;
+ }
+
+ // Reset all the recovery parameters, even if the texture storage association is broken.
+ disassociateStorage();
+ }
+
+ return gl::NoError();
+}
+
+void Image11::disassociateStorage()
+{
+ if (mRecoverFromStorage)
+ {
+ // Make the texturestorage release the Image11 too
+ mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this);
+
+ mRecoverFromStorage = false;
+ mAssociatedStorage = NULL;
+ mAssociatedImageIndex = gl::ImageIndex::MakeInvalid();
+ }
+}
+
+bool Image11::redefine(GLenum target,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease)
+{
+ if (mWidth != size.width || mHeight != size.height || 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;
+ mTarget = target;
+
+ // 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 != NULL);
+
+ 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.
+gl::Error Image11::loadData(const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum inputType,
+ const void *input,
+ bool applySkipImages)
+{
+ const auto sizedInputFormat = getSizedInputFormat(inputType);
+ const gl::InternalFormat &inputFormat = gl::GetInternalFormatInfo(sizedInputFormat);
+ GLuint inputRowPitch = 0;
+ ANGLE_TRY_RESULT(
+ inputFormat.computeRowPitch(area.width, unpack.alignment, unpack.rowLength),
+ inputRowPitch);
+ GLuint inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(area.height, unpack.imageHeight, inputRowPitch),
+ inputDepthPitch);
+ GLuint inputSkipBytes = 0;
+ ANGLE_TRY_RESULT(
+ inputFormat.computeSkipBytes(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()(inputType).loadFunction;
+
+ D3D11_MAPPED_SUBRESOURCE mappedImage;
+ ANGLE_TRY(map(D3D11_MAP_WRITE, &mappedImage));
+
+ uint8_t *offsetMappedData = (reinterpret_cast<uint8_t *>(mappedImage.pData) +
+ (area.y * mappedImage.RowPitch + area.x * outputPixelSize +
+ area.z * mappedImage.DepthPitch));
+ loadFunction(area.width, area.height, area.depth,
+ reinterpret_cast<const uint8_t *>(input) + inputSkipBytes, inputRowPitch,
+ inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
+
+ unmap();
+
+ return gl::NoError();
+}
+
+gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input)
+{
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+ GLsizei inputRowPitch = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeRowPitch(area.width, 1, 0), inputRowPitch);
+ GLsizei inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(gl::InternalFormat::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(D3D11_MAP_WRITE, &mappedImage));
+
+ uint8_t *offsetMappedData =
+ reinterpret_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, reinterpret_cast<const uint8_t *>(input),
+ inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch,
+ mappedImage.DepthPitch);
+
+ unmap();
+
+ return gl::NoError();
+}
+
+gl::Error Image11::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source)
+{
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(source);
+
+ ID3D11Resource *resource = nullptr;
+ ANGLE_TRY(storage11->getResource(&resource));
+
+ UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex);
+ TextureHelper11 textureHelper =
+ TextureHelper11::MakeAndReference(resource, storage11->getFormatSet());
+
+ gl::Box sourceBox(0, 0, 0, mWidth, mHeight, mDepth);
+ return copyWithoutConversion(gl::Offset(), sourceBox, textureHelper, subresourceIndex);
+}
+
+gl::Error Image11::copyFromFramebuffer(const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *sourceFBO)
+{
+ const gl::FramebufferAttachment *srcAttachment = sourceFBO->getReadColorbuffer();
+ ASSERT(srcAttachment);
+
+ GLenum sourceInternalFormat = srcAttachment->getFormat().asSized();
+ const auto &d3d11Format =
+ d3d11::Format::Get(sourceInternalFormat, mRenderer->getRenderer11DeviceCaps());
+
+ if (d3d11Format.texFormat == mDXGIFormat && sourceInternalFormat == mInternalFormat)
+ {
+ RenderTargetD3D *renderTarget = nullptr;
+ ANGLE_TRY(srcAttachment->getRenderTarget(&renderTarget));
+
+ RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget);
+ ASSERT(rt11->getTexture());
+
+ TextureHelper11 textureHelper =
+ TextureHelper11::MakeAndReference(rt11->getTexture(), rt11->getFormatSet());
+ unsigned int sourceSubResource = rt11->getSubresourceIndex();
+
+ gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1);
+ return copyWithoutConversion(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(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::GetInternalFormatInfo(mInternalFormat);
+ const auto &destD3D11Format =
+ d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
+
+ auto loadFunction = destD3D11Format.getLoadFunctions()(destFormatInfo.type);
+ gl::Error error = gl::NoError();
+ if (loadFunction.requiresConversion)
+ {
+ size_t bufferSize = destFormatInfo.pixelBytes * sourceArea.width * sourceArea.height;
+ MemoryBuffer *memoryBuffer = nullptr;
+ mRenderer->getScratchMemoryBuffer(bufferSize, &memoryBuffer);
+ GLuint memoryBufferRowPitch = destFormatInfo.pixelBytes * sourceArea.width;
+
+ error = mRenderer->readFromAttachment(*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
+ {
+ error = mRenderer->readFromAttachment(*srcAttachment, sourceArea, destFormatInfo.format,
+ destFormatInfo.type, mappedImage.RowPitch,
+ gl::PixelPackState(), dataOffset);
+ }
+
+ unmap();
+ mDirty = true;
+
+ return error;
+}
+
+gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset,
+ const gl::Box &sourceArea,
+ const TextureHelper11 &textureHelper,
+ UINT sourceSubResource)
+{
+ // No conversion needed-- use copyback fastpath
+ ID3D11Resource *stagingTexture = nullptr;
+ unsigned int stagingSubresourceIndex = 0;
+ ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex));
+
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ UINT subresourceAfterResolve = sourceSubResource;
+
+ ID3D11Resource *srcTex = nullptr;
+ const gl::Extents &extents = textureHelper.getExtents();
+
+ bool needResolve =
+ (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1);
+
+ if (needResolve)
+ {
+ 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;
+
+ ID3D11Texture2D *srcTex2D = NULL;
+ HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex2D);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.",
+ result);
+ }
+ srcTex = srcTex2D;
+
+ deviceContext->ResolveSubresource(srcTex, 0, textureHelper.getTexture2D(),
+ sourceSubResource, textureHelper.getFormat());
+ subresourceAfterResolve = 0;
+ }
+ else
+ {
+ srcTex = textureHelper.getResource();
+ }
+
+ 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;
+
+ deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x,
+ destOffset.y, destOffset.z, srcTex,
+ subresourceAfterResolve, &srcBox);
+
+ if (needResolve)
+ {
+ SafeRelease(srcTex);
+ }
+
+ mDirty = true;
+ return gl::NoError();
+}
+
+gl::Error Image11::getStagingTexture(ID3D11Resource **outStagingTexture,
+ unsigned int *outSubresourceIndex)
+{
+ ANGLE_TRY(createStagingTexture());
+
+ *outStagingTexture = mStagingTexture;
+ *outSubresourceIndex = mStagingSubresource;
+ return gl::NoError();
+}
+
+void Image11::releaseStagingTexture()
+{
+ SafeRelease(mStagingTexture);
+}
+
+gl::Error Image11::createStagingTexture()
+{
+ if (mStagingTexture)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0);
+
+ const DXGI_FORMAT dxgiFormat = getDXGIFormat();
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result;
+
+ int lodOffset = 1;
+ GLsizei width = mWidth;
+ GLsizei height = mHeight;
+
+ // adjust size if needed for compressed textures
+ d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset);
+
+ if (mTarget == GL_TEXTURE_3D)
+ {
+ ID3D11Texture3D *newTexture = NULL;
+
+ 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 (d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps())
+ .dataInitializerFunction != NULL)
+ {
+ std::vector<D3D11_SUBRESOURCE_DATA> initialData;
+ std::vector<std::vector<BYTE>> textureData;
+ d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(),
+ width, height, mDepth, lodOffset + 1, &initialData,
+ &textureData);
+
+ result = device->CreateTexture3D(&desc, initialData.data(), &newTexture);
+ }
+ else
+ {
+ result = device->CreateTexture3D(&desc, NULL, &newTexture);
+ }
+
+ if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.",
+ result);
+ }
+
+ mStagingTexture = newTexture;
+ mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
+ }
+ else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY ||
+ mTarget == GL_TEXTURE_CUBE_MAP)
+ {
+ ID3D11Texture2D *newTexture = NULL;
+
+ 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 (d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps())
+ .dataInitializerFunction != NULL)
+ {
+ std::vector<D3D11_SUBRESOURCE_DATA> initialData;
+ std::vector<std::vector<BYTE>> textureData;
+ d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(),
+ width, height, 1, lodOffset + 1, &initialData,
+ &textureData);
+
+ result = device->CreateTexture2D(&desc, initialData.data(), &newTexture);
+ }
+ else
+ {
+ result = device->CreateTexture2D(&desc, NULL, &newTexture);
+ }
+
+ if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.",
+ result);
+ }
+
+ mStagingTexture = newTexture;
+ mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ mDirty = false;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
+{
+ // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE.
+ ANGLE_TRY(recoverFromAssociatedStorage());
+
+ ID3D11Resource *stagingTexture = NULL;
+ unsigned int subresourceIndex = 0;
+ ANGLE_TRY(getStagingTexture(&stagingTexture, &subresourceIndex));
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ ASSERT(mStagingTexture);
+ HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map);
+
+ if (FAILED(result))
+ {
+ // this can fail if the device is removed (from TDR)
+ if (d3d11::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ }
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result);
+ }
+
+ mDirty = true;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Image11::unmap()
+{
+ if (mStagingTexture)
+ {
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->Unmap(mStagingTexture, mStagingSubresource);
+ }
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h
new file mode 100755
index 000000000..17c3688b4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 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 "libANGLE/renderer/d3d/ImageD3D.h"
+#include "libANGLE/ImageIndex.h"
+
+#include "common/debug.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Renderer11;
+class TextureHelper11;
+class TextureStorage11;
+struct Renderer11DeviceCaps;
+
+class Image11 : public ImageD3D
+{
+ public:
+ Image11(Renderer11 *renderer);
+ virtual ~Image11();
+
+ static gl::Error generateMipmap(Image11 *dest,
+ Image11 *src,
+ const Renderer11DeviceCaps &rendererCaps);
+
+ virtual bool isDirty() const;
+
+ virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+
+ bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override;
+
+ DXGI_FORMAT getDXGIFormat() const;
+
+ gl::Error loadData(const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages) override;
+ gl::Error loadCompressedData(const gl::Box &area, const void *input) override;
+
+ gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override;
+ gl::Error copyFromFramebuffer(const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error recoverFromAssociatedStorage();
+ bool isAssociatedStorageValid(TextureStorage11* textureStorage) const;
+ void disassociateStorage();
+
+ protected:
+ gl::Error map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
+ void unmap();
+
+ private:
+ gl::Error copyWithoutConversion(const gl::Offset &destOffset,
+ const gl::Box &sourceArea,
+ const TextureHelper11 &textureHelper,
+ UINT sourceSubResource);
+
+ gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex);
+ gl::Error createStagingTexture();
+ void releaseStagingTexture();
+
+ Renderer11 *mRenderer;
+
+ DXGI_FORMAT mDXGIFormat;
+ ID3D11Resource *mStagingTexture;
+ unsigned int mStagingSubresource;
+
+ bool mRecoverFromStorage;
+ TextureStorage11 *mAssociatedStorage;
+ gl::ImageIndex mAssociatedImageIndex;
+ unsigned int mRecoveredFromStorageCount;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp
new file mode 100755
index 000000000..a5e78a245
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp
@@ -0,0 +1,167 @@
+//
+// Copyright (c) 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/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
+{
+ mBuffer = NULL;
+ mBufferSize = 0;
+ mDynamicUsage = false;
+}
+
+IndexBuffer11::~IndexBuffer11()
+{
+ SafeRelease(mBuffer);
+}
+
+gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
+{
+ SafeRelease(mBuffer);
+
+ updateSerial();
+
+ if (bufferSize > 0)
+ {
+ ID3D11Device* dxDevice = mRenderer->getDevice();
+
+ 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;
+
+ HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize);
+ }
+
+ if (dynamic)
+ {
+ d3d11::SetDebugName(mBuffer, "IndexBuffer11 (dynamic)");
+ }
+ else
+ {
+ d3d11::SetDebugName(mBuffer, "IndexBuffer11 (static)");
+ }
+ }
+
+ mBufferSize = bufferSize;
+ mIndexType = indexType;
+ mDynamicUsage = dynamic;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
+{
+ if (!mBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+ }
+
+ // Check for integer overflows and out-out-bounds map requests
+ if (offset + size < offset || offset + size > mBufferSize)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Index buffer map range is not inside the buffer.");
+ }
+
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result);
+ }
+
+ *outMappedMemory = reinterpret_cast<char*>(mappedResource.pData) + offset;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error IndexBuffer11::unmapBuffer()
+{
+ if (!mBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+ }
+
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+ dxContext->Unmap(mBuffer, 0);
+ return gl::Error(GL_NO_ERROR);
+}
+
+GLenum IndexBuffer11::getIndexType() const
+{
+ return mIndexType;
+}
+
+unsigned int IndexBuffer11::getBufferSize() const
+{
+ return mBufferSize;
+}
+
+gl::Error IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType)
+{
+ if (bufferSize > mBufferSize || indexType != mIndexType)
+ {
+ return initialize(bufferSize, indexType, mDynamicUsage);
+ }
+ else
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+gl::Error IndexBuffer11::discard()
+{
+ if (!mBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+ }
+
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result);
+ }
+
+ dxContext->Unmap(mBuffer, 0);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+DXGI_FORMAT IndexBuffer11::getIndexFormat() const
+{
+ switch (mIndexType)
+ {
+ case GL_UNSIGNED_BYTE: return DXGI_FORMAT_R16_UINT;
+ case GL_UNSIGNED_SHORT: return DXGI_FORMAT_R16_UINT;
+ case GL_UNSIGNED_INT: return DXGI_FORMAT_R32_UINT;
+ default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN;
+ }
+}
+
+ID3D11Buffer *IndexBuffer11::getBuffer() const
+{
+ return mBuffer;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h
new file mode 100755
index 000000000..e730377e0
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h
@@ -0,0 +1,49 @@
+//
+// Copyright (c) 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"
+
+namespace rx
+{
+class Renderer11;
+
+class IndexBuffer11 : public IndexBuffer
+{
+ public:
+ explicit IndexBuffer11(Renderer11 *const renderer);
+ virtual ~IndexBuffer11();
+
+ virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
+
+ virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory);
+ virtual gl::Error unmapBuffer();
+
+ virtual GLenum getIndexType() const;
+ virtual unsigned int getBufferSize() const;
+ virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType);
+
+ virtual gl::Error discard();
+
+ DXGI_FORMAT getIndexFormat() const;
+ ID3D11Buffer *getBuffer() const;
+
+ private:
+ Renderer11 *const mRenderer;
+
+ ID3D11Buffer *mBuffer;
+ unsigned int mBufferSize;
+ GLenum mIndexType;
+ bool mDynamicUsage;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
new file mode 100755
index 000000000..89d5dc676
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
@@ -0,0 +1,651 @@
+//
+// Copyright (c) 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/BitSetIterator.h"
+#include "common/utilities.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "third_party/murmurhash/MurmurHash3.h"
+
+namespace rx
+{
+
+namespace
+{
+
+size_t GetReservedBufferCount(bool usesPointSpriteEmulation)
+{
+ return usesPointSpriteEmulation ? 1 : 0;
+}
+
+gl::InputLayout GetInputLayout(const std::vector<const TranslatedAttribute *> &translatedAttributes)
+{
+ gl::InputLayout inputLayout(translatedAttributes.size(), gl::VERTEX_FORMAT_INVALID);
+
+ for (size_t attributeIndex = 0; attributeIndex < translatedAttributes.size(); ++attributeIndex)
+ {
+ const TranslatedAttribute *translatedAttribute = translatedAttributes[attributeIndex];
+ inputLayout[attributeIndex] = gl::GetVertexFormatType(
+ *translatedAttribute->attribute, translatedAttribute->currentValueType);
+ }
+ return inputLayout;
+}
+
+GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes, int index)
+{
+ // Count matrices differently
+ for (const sh::Attribute &attrib : shaderAttributes)
+ {
+ if (attrib.location == -1)
+ {
+ continue;
+ }
+
+ GLenum transposedType = gl::TransposeMatrixType(attrib.type);
+ int rows = gl::VariableRowCount(transposedType);
+
+ if (index >= attrib.location && index < attrib.location + rows)
+ {
+ return transposedType;
+ }
+ }
+
+ UNREACHABLE();
+ return GL_NONE;
+}
+
+const unsigned int kDefaultCacheSize = 1024;
+
+struct PackedAttribute
+{
+ uint8_t attribType;
+ uint8_t semanticIndex;
+ uint8_t vertexFormatType;
+ uint8_t divisor;
+};
+
+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 gl::Program *program,
+ const std::vector<TranslatedAttribute> &vertexArrayAttribs,
+ const std::vector<TranslatedAttribute> &currentValueAttribs,
+ AttribIndexArray *sortedD3DSemanticsOut,
+ std::vector<const TranslatedAttribute *> *sortedAttributesOut)
+{
+ sortedAttributesOut->clear();
+
+ const auto &locationToSemantic =
+ GetImplAs<ProgramD3D>(program)->getAttribLocationToD3DSemantics();
+
+ for (auto locationIndex : angle::IterateBitSet(program->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];
+ }
+ }
+}
+
+} // anonymous namespace
+
+void InputLayoutCache::PackedAttributeLayout::addAttributeData(
+ GLenum glType,
+ UINT semanticIndex,
+ gl::VertexFormatType vertexFormatType,
+ 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>(vertexFormatType);
+ packedAttrib.divisor = static_cast<uint8_t>(divisor);
+
+ ASSERT(static_cast<gl::AttributeType>(packedAttrib.attribType) == attribType);
+ ASSERT(static_cast<UINT>(packedAttrib.semanticIndex) == semanticIndex);
+ ASSERT(static_cast<gl::VertexFormatType>(packedAttrib.vertexFormatType) == vertexFormatType);
+ ASSERT(static_cast<unsigned int>(packedAttrib.divisor) == divisor);
+
+ static_assert(sizeof(uint32_t) == sizeof(PackedAttribute), "PackedAttributes must be 32-bits exactly.");
+
+ attributeData[numAttributes++] = gl::bitCast<uint32_t>(packedAttrib);
+}
+
+bool InputLayoutCache::PackedAttributeLayout::operator<(const PackedAttributeLayout &other) const
+{
+ if (numAttributes != other.numAttributes)
+ {
+ return numAttributes < other.numAttributes;
+ }
+
+ if (flags != other.flags)
+ {
+ return flags < other.flags;
+ }
+
+ return memcmp(attributeData, other.attributeData, sizeof(uint32_t) * numAttributes) < 0;
+}
+
+InputLayoutCache::InputLayoutCache()
+ : mCurrentIL(nullptr),
+ mPointSpriteVertexBuffer(nullptr),
+ mPointSpriteIndexBuffer(nullptr),
+ mCacheSize(kDefaultCacheSize),
+ mDevice(nullptr),
+ mDeviceContext(nullptr)
+{
+ mCurrentBuffers.fill(nullptr);
+ mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max());
+ mCurrentVertexOffsets.fill(std::numeric_limits<UINT>::max());
+ mCurrentAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
+}
+
+InputLayoutCache::~InputLayoutCache()
+{
+ clear();
+}
+
+void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context)
+{
+ clear();
+ mDevice = device;
+ mDeviceContext = context;
+ mFeatureLevel = device->GetFeatureLevel();
+}
+
+void InputLayoutCache::clear()
+{
+ for (auto &layout : mLayoutMap)
+ {
+ SafeRelease(layout.second);
+ }
+ mLayoutMap.clear();
+ SafeRelease(mPointSpriteVertexBuffer);
+ SafeRelease(mPointSpriteIndexBuffer);
+ markDirty();
+}
+
+void InputLayoutCache::markDirty()
+{
+ mCurrentIL = nullptr;
+ for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mCurrentBuffers[i] = nullptr;
+ mCurrentVertexStrides[i] = static_cast<UINT>(-1);
+ mCurrentVertexOffsets[i] = static_cast<UINT>(-1);
+ }
+}
+
+gl::Error InputLayoutCache::applyVertexBuffers(
+ const gl::State &state,
+ const std::vector<TranslatedAttribute> &vertexArrayAttribs,
+ const std::vector<TranslatedAttribute> &currentValueAttribs,
+ GLenum mode,
+ GLint start,
+ TranslatedIndexData *indexInfo,
+ GLsizei numIndicesPerInstance)
+{
+ ASSERT(mDevice && mDeviceContext);
+
+ gl::Program *program = state.getProgram();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+
+ bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
+ bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS);
+
+ AttribIndexArray sortedSemanticIndices;
+ SortAttributesByLayout(program, vertexArrayAttribs, currentValueAttribs, &sortedSemanticIndices,
+ &mCurrentAttributes);
+
+ // If we are using FL 9_3, make sure the first attribute is not instanced
+ if (mFeatureLevel <= 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]);
+ }
+ }
+ }
+
+ ANGLE_TRY(updateInputLayout(state, mode, sortedSemanticIndices, numIndicesPerInstance));
+
+ bool dirtyBuffers = false;
+ size_t minDiff = gl::MAX_VERTEX_ATTRIBS;
+ size_t maxDiff = 0;
+
+ // 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 auto &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();
+ }
+ else if (instancedPointSpritesActive && (indexInfo != nullptr))
+ {
+ if (indexInfo->srcIndexData.srcBuffer != nullptr)
+ {
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(indexInfo->srcIndexData.srcBuffer->getData(&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_RESULT(bufferStorage->getEmulatedIndexedBuffer(&indexInfo->srcIndexData,
+ attrib, start),
+ buffer);
+ }
+ else
+ {
+ ANGLE_TRY_RESULT(
+ bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), buffer);
+ }
+
+ vertexStride = attrib.stride;
+ ANGLE_TRY_RESULT(attrib.computeOffset(start), vertexOffset);
+ }
+
+ size_t bufferIndex = reservedBuffers + attribIndex;
+
+ if (buffer != mCurrentBuffers[bufferIndex] ||
+ vertexStride != mCurrentVertexStrides[bufferIndex] ||
+ vertexOffset != mCurrentVertexOffsets[bufferIndex])
+ {
+ dirtyBuffers = true;
+ minDiff = std::min(minDiff, bufferIndex);
+ maxDiff = std::max(maxDiff, bufferIndex);
+
+ mCurrentBuffers[bufferIndex] = buffer;
+ mCurrentVertexStrides[bufferIndex] = vertexStride;
+ mCurrentVertexOffsets[bufferIndex] = vertexOffset;
+ }
+ }
+
+ // 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)
+ {
+ HRESULT result = S_OK;
+ const UINT pointSpriteVertexStride = sizeof(float) * 5;
+
+ if (!mPointSpriteVertexBuffer)
+ {
+ static const float pointSpriteVertices[] =
+ {
+ // Position // TexCoord
+ -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
+ -1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
+ 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
+ 1.0f, -1.0f, 0.0f, 1.0f, 1.0f,
+ -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
+ };
+
+ D3D11_SUBRESOURCE_DATA vertexBufferData = { pointSpriteVertices, 0, 0 };
+ D3D11_BUFFER_DESC vertexBufferDesc;
+ vertexBufferDesc.ByteWidth = sizeof(pointSpriteVertices);
+ vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ vertexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+ vertexBufferDesc.CPUAccessFlags = 0;
+ vertexBufferDesc.MiscFlags = 0;
+ vertexBufferDesc.StructureByteStride = 0;
+
+ result = mDevice->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &mPointSpriteVertexBuffer);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation vertex buffer, HRESULT: 0x%08x", result);
+ }
+ }
+
+ mCurrentBuffers[0] = 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.
+ mCurrentVertexStrides[0] = instancedPointSpritesActive ? pointSpriteVertexStride : 0;
+ mCurrentVertexOffsets[0] = 0;
+
+ // Update maxDiff to include the additional point sprite vertex buffer
+ // to ensure that IASetVertexBuffers uses the correct buffer count.
+ minDiff = 0;
+ maxDiff = std::max(maxDiff, static_cast<size_t>(0));
+
+ if (!mPointSpriteIndexBuffer)
+ {
+ // Create an index buffer and set it for pointsprite rendering
+ static const unsigned short pointSpriteIndices[] =
+ {
+ 0, 1, 2, 3, 4, 5,
+ };
+
+ D3D11_SUBRESOURCE_DATA indexBufferData = { pointSpriteIndices, 0, 0 };
+ D3D11_BUFFER_DESC indexBufferDesc;
+ indexBufferDesc.ByteWidth = sizeof(pointSpriteIndices);
+ indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+ indexBufferDesc.CPUAccessFlags = 0;
+ indexBufferDesc.MiscFlags = 0;
+ indexBufferDesc.StructureByteStride = 0;
+
+ result = mDevice->CreateBuffer(&indexBufferDesc, &indexBufferData, &mPointSpriteIndexBuffer);
+ if (FAILED(result))
+ {
+ SafeRelease(mPointSpriteVertexBuffer);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation index buffer, HRESULT: 0x%08x", result);
+ }
+ }
+
+ 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.
+ mDeviceContext->IASetIndexBuffer(mPointSpriteIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
+ }
+ }
+
+ if (dirtyBuffers)
+ {
+ ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS);
+ mDeviceContext->IASetVertexBuffers(
+ static_cast<UINT>(minDiff), static_cast<UINT>(maxDiff - minDiff + 1),
+ &mCurrentBuffers[minDiff], &mCurrentVertexStrides[minDiff],
+ &mCurrentVertexOffsets[minDiff]);
+ }
+
+ return gl::NoError();
+}
+
+gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(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_RESULT(attrib.computeOffset(startVertex), offset);
+ mCurrentVertexOffsets[bufferIndex] =
+ offset + (attrib.stride * (emulatedInstanceId / attrib.divisor));
+ }
+ }
+
+ mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, mCurrentBuffers.data(),
+ mCurrentVertexStrides.data(), mCurrentVertexOffsets.data());
+
+ return gl::NoError();
+}
+
+gl::Error InputLayoutCache::updateInputLayout(const gl::State &state,
+ GLenum mode,
+ const AttribIndexArray &sortedSemanticIndices,
+ GLsizei numIndicesPerInstance)
+{
+ 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_POINTS);
+
+ if (programUsesInstancedPointSprites)
+ {
+ layout.flags |= PackedAttributeLayout::FLAG_USES_INSTANCED_SPRITES;
+ }
+
+ if (instancedPointSpritesActive)
+ {
+ layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_SPRITES_ACTIVE;
+ }
+
+ if (numIndicesPerInstance > 0)
+ {
+ layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_RENDERING_ACTIVE;
+ }
+
+ const auto &attribs = state.getVertexArray()->getVertexAttributes();
+ const auto &locationToSemantic = programD3D->getAttribLocationToD3DSemantics();
+
+ for (unsigned long attribIndex : angle::IterateBitSet(program->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];
+ int d3dSemantic = locationToSemantic[attribIndex];
+
+ const auto &currentValue = state.getVertexAttribCurrentValue(attribIndex);
+ gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValue.Type);
+
+ layout.addAttributeData(glslElementType, d3dSemantic, vertexFormatType, attrib.divisor);
+ }
+
+ ID3D11InputLayout *inputLayout = nullptr;
+ if (layout.numAttributes > 0 || layout.flags != 0)
+ {
+ auto layoutMapIt = mLayoutMap.find(layout);
+ if (layoutMapIt != mLayoutMap.end())
+ {
+ inputLayout = layoutMapIt->second;
+ }
+ else
+ {
+ ANGLE_TRY(createInputLayout(sortedSemanticIndices, mode, program, numIndicesPerInstance,
+ &inputLayout));
+ if (mLayoutMap.size() >= mCacheSize)
+ {
+ TRACE("Overflowed the limit of %u input layouts, purging half the cache.",
+ mCacheSize);
+
+ // Randomly release every second element
+ auto it = mLayoutMap.begin();
+ while (it != mLayoutMap.end())
+ {
+ it++;
+ if (it != mLayoutMap.end())
+ {
+ // c++11 erase allows us to easily delete the current iterator.
+ SafeRelease(it->second);
+ it = mLayoutMap.erase(it);
+ }
+ }
+ }
+
+ mLayoutMap[layout] = inputLayout;
+ }
+ }
+
+ if (inputLayout != mCurrentIL)
+ {
+ mDeviceContext->IASetInputLayout(inputLayout);
+ mCurrentIL = inputLayout;
+ }
+
+ return gl::NoError();
+}
+
+gl::Error InputLayoutCache::createInputLayout(const AttribIndexArray &sortedSemanticIndices,
+ GLenum mode,
+ gl::Program *program,
+ GLsizei numIndicesPerInstance,
+ ID3D11InputLayout **inputLayoutOut)
+{
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+
+ bool programUsesInstancedPointSprites =
+ programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
+
+ unsigned int inputElementCount = 0;
+ std::array<D3D11_INPUT_ELEMENT_DESC, gl::MAX_VERTEX_ATTRIBS> inputElements;
+
+ for (size_t attribIndex = 0; attribIndex < mCurrentAttributes.size(); ++attribIndex)
+ {
+ const auto &attrib = *mCurrentAttributes[attribIndex];
+ const int sortedIndex = sortedSemanticIndices[attribIndex];
+
+ D3D11_INPUT_CLASSIFICATION inputClass =
+ attrib.divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
+
+ const auto &vertexFormatType =
+ gl::GetVertexFormatType(*attrib.attribute, attrib.currentValueType);
+ const auto &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormatType, mFeatureLevel);
+
+ 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.
+ 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_POINTS)
+ {
+ inputElements[elementIndex].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
+ inputElements[elementIndex].InstanceDataStepRate = 1;
+ if (numIndicesPerInstance > 0 && mCurrentAttributes[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++;
+ }
+
+ const gl::InputLayout &shaderInputLayout = GetInputLayout(mCurrentAttributes);
+
+ ShaderExecutableD3D *shader = nullptr;
+ ANGLE_TRY(programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr));
+
+ ShaderExecutableD3D *shader11 = GetAs<ShaderExecutable11>(shader);
+
+ HRESULT result =
+ mDevice->CreateInputLayout(inputElements.data(), inputElementCount, shader11->getFunction(),
+ shader11->getLength(), inputLayoutOut);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal input layout, HRESULT: 0x%08x", result);
+ }
+
+ return gl::NoError();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
new file mode 100755
index 000000000..62a1020f5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
@@ -0,0 +1,120 @@
+//
+// Copyright (c) 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/formatutils.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace gl
+{
+class Program;
+}
+
+namespace rx
+{
+struct TranslatedAttribute;
+struct TranslatedIndexData;
+struct SourceIndexData;
+class ProgramD3D;
+
+class InputLayoutCache : angle::NonCopyable
+{
+ public:
+ InputLayoutCache();
+ virtual ~InputLayoutCache();
+
+ void initialize(ID3D11Device *device, ID3D11DeviceContext *context);
+ void clear();
+ void markDirty();
+
+ gl::Error applyVertexBuffers(const gl::State &state,
+ const std::vector<TranslatedAttribute> &vertexArrayAttribs,
+ const std::vector<TranslatedAttribute> &currentValueAttribs,
+ GLenum mode,
+ GLint start,
+ TranslatedIndexData *indexInfo,
+ GLsizei numIndicesPerInstance);
+
+ gl::Error updateVertexOffsetsForPointSpritesEmulation(GLint startVertex,
+ GLsizei emulatedInstanceId);
+
+ // Useful for testing
+ void setCacheSize(unsigned int cacheSize) { mCacheSize = cacheSize; }
+
+ private:
+ struct PackedAttributeLayout
+ {
+ PackedAttributeLayout()
+ : numAttributes(0),
+ flags(0)
+ {
+ }
+
+ void addAttributeData(GLenum glType,
+ UINT semanticIndex,
+ gl::VertexFormatType vertexFormatType,
+ 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,
+ };
+
+ size_t numAttributes;
+ unsigned int flags;
+ uint32_t attributeData[gl::MAX_VERTEX_ATTRIBS];
+ };
+
+ gl::Error updateInputLayout(const gl::State &state,
+ GLenum mode,
+ const AttribIndexArray &sortedSemanticIndices,
+ GLsizei numIndicesPerInstance);
+ gl::Error createInputLayout(const AttribIndexArray &sortedSemanticIndices,
+ GLenum mode,
+ gl::Program *program,
+ GLsizei numIndicesPerInstance,
+ ID3D11InputLayout **inputLayoutOut);
+
+ std::map<PackedAttributeLayout, ID3D11InputLayout *> mLayoutMap;
+
+ ID3D11InputLayout *mCurrentIL;
+ std::array<ID3D11Buffer *, gl::MAX_VERTEX_ATTRIBS> mCurrentBuffers;
+ std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexStrides;
+ std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexOffsets;
+ std::vector<const TranslatedAttribute *> mCurrentAttributes;
+
+ ID3D11Buffer *mPointSpriteVertexBuffer;
+ ID3D11Buffer *mPointSpriteIndexBuffer;
+
+ unsigned int mCacheSize;
+
+ ID3D11Device *mDevice;
+ ID3D11DeviceContext *mDeviceContext;
+ D3D_FEATURE_LEVEL mFeatureLevel;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h
new file mode 100755
index 000000000..4f70beddf
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 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) {}
+
+#ifdef ANGLE_ENABLE_D3D11
+ virtual HRESULT createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ IDXGISwapChain **swapChain) = 0;
+ virtual void commitChange() = 0;
+#endif
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
new file mode 100755
index 000000000..e7ca56ef2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
@@ -0,0 +1,299 @@
+//
+// Copyright (c) 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/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/Texture.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(NULL),
+ mBufferToTextureGS(NULL),
+ mParamsConstantBuffer(NULL),
+ mCopyRasterizerState(NULL),
+ mCopyDepthStencilState(NULL)
+{
+}
+
+PixelTransfer11::~PixelTransfer11()
+{
+ for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++)
+ {
+ SafeRelease(shaderMapIt->second);
+ }
+
+ mBufferToTexturePSMap.clear();
+
+ SafeRelease(mBufferToTextureVS);
+ SafeRelease(mBufferToTextureGS);
+ SafeRelease(mParamsConstantBuffer);
+ SafeRelease(mCopyRasterizerState);
+ SafeRelease(mCopyDepthStencilState);
+}
+
+gl::Error PixelTransfer11::loadResources()
+{
+ if (mResourcesLoaded)
+ {
+ return gl::NoError();
+ }
+
+ HRESULT result = S_OK;
+ ID3D11Device *device = mRenderer->getDevice();
+
+ 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;
+
+ result = device->CreateRasterizerState(&rasterDesc, &mCopyRasterizerState);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer rasterizer state, result: 0x%X.", result);
+ }
+
+ 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;
+
+ result = device->CreateDepthStencilState(&depthStencilDesc, &mCopyDepthStencilState);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer depth stencil state, result: 0x%X.", result);
+ }
+
+ D3D11_BUFFER_DESC constantBufferDesc = { 0 };
+ constantBufferDesc.ByteWidth = roundUp<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;
+
+ result = device->CreateBuffer(&constantBufferDesc, NULL, &mParamsConstantBuffer);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer constant buffer, result: 0x%X.", result);
+ }
+ d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer");
+
+ // init shaders
+ mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS");
+ if (!mBufferToTextureVS)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader.");
+ }
+
+ mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
+ if (!mBufferToTextureGS)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader.");
+ }
+
+ ANGLE_TRY(buildShaderMap());
+
+ StructZero(&mParamsData);
+
+ mResourcesLoaded = true;
+
+ return gl::NoError();
+}
+
+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 - 1);
+ float texelCenterY = 0.5f / static_cast<float>(destSize.height - 1);
+
+ unsigned int bytesPerPixel = gl::GetInternalFormatInfo(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;
+}
+
+gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
+{
+ ANGLE_TRY(loadResources());
+
+ 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 );
+
+ const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get();
+
+ ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat));
+
+ ID3D11PixelShader *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::GetInternalFormatInfo(destinationFormat).format;
+ GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType);
+
+ const d3d11::Format &sourceFormatInfo =
+ d3d11::Format::Get(sourceFormat, mRenderer->getRenderer11DeviceCaps());
+ DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat;
+ ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN);
+ Buffer11 *bufferStorage11 = GetAs<Buffer11>(sourceBuffer.getImplementation());
+ ID3D11ShaderResourceView *bufferSRV = nullptr;
+ ANGLE_TRY_RESULT(bufferStorage11->getSRV(srvFormat), bufferSRV);
+ ASSERT(bufferSRV != nullptr);
+
+ ID3D11RenderTargetView *textureRTV = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
+ ASSERT(textureRTV != nullptr);
+
+ CopyShaderParams shaderParams;
+ setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams);
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ ID3D11Buffer *nullBuffer = nullptr;
+ UINT zero = 0;
+
+ // Are we doing a 2D or 3D copy?
+ ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL);
+ auto stateManager = mRenderer->getStateManager();
+
+ deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0);
+ deviceContext->GSSetShader(geometryShader, NULL, 0);
+ deviceContext->PSSetShader(pixelShader, NULL, 0);
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV);
+ deviceContext->IASetInputLayout(NULL);
+ deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
+
+ deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
+ deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
+ deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF);
+ deviceContext->RSSetState(mCopyRasterizerState);
+
+ stateManager->setOneTimeRenderTarget(textureRTV, nullptr);
+
+ if (!StructEquals(mParamsData, shaderParams))
+ {
+ d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams);
+ mParamsData = shaderParams;
+ }
+
+ deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer);
+
+ // Set the viewport
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = static_cast<FLOAT>(destSize.width);
+ viewport.Height = static_cast<FLOAT>(destSize.height);
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ deviceContext->RSSetViewports(1, &viewport);
+
+ UINT numPixels = (destArea.width * destArea.height * destArea.depth);
+ deviceContext->Draw(numPixels, 0);
+
+ // Unbind textures and render targets and vertex buffer
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
+ deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer);
+
+ mRenderer->markAllStateDirty();
+
+ return gl::NoError();
+}
+
+gl::Error PixelTransfer11::buildShaderMap()
+{
+ ID3D11Device *device = mRenderer->getDevice();
+
+ mBufferToTexturePSMap[GL_FLOAT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4F, "BufferToTexture RGBA ps");
+ mBufferToTexturePSMap[GL_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4I, "BufferToTexture RGBA-I ps");
+ mBufferToTexturePSMap[GL_UNSIGNED_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4UI, "BufferToTexture RGBA-UI ps");
+
+ // Check that all the shaders were created successfully
+ for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++)
+ {
+ if (shaderMapIt->second == NULL)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture pixel shader.");
+ }
+ }
+
+ return gl::NoError();
+}
+
+ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const
+{
+ GLenum componentType = gl::GetInternalFormatInfo(internalFormat).componentType;
+ if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED)
+ {
+ componentType = GL_FLOAT;
+ }
+
+ auto shaderMapIt = mBufferToTexturePSMap.find(componentType);
+ return (shaderMapIt == mBufferToTexturePSMap.end() ? NULL : shaderMapIt->second);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
new file mode 100755
index 000000000..1672121ec
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 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 "libANGLE/Error.h"
+
+#include "common/platform.h"
+
+#include <GLES2/gl2.h>
+
+#include <map>
+
+namespace gl
+{
+
+class Buffer;
+struct Box;
+struct Extents;
+struct PixelUnpackState;
+
+}
+
+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
+ gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, 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);
+
+ gl::Error loadResources();
+ gl::Error buildShaderMap();
+ ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const;
+
+ Renderer11 *mRenderer;
+
+ bool mResourcesLoaded;
+ std::map<GLenum, ID3D11PixelShader *> mBufferToTexturePSMap;
+ ID3D11VertexShader *mBufferToTextureVS;
+ ID3D11GeometryShader *mBufferToTextureGS;
+ ID3D11Buffer *mParamsConstantBuffer;
+ CopyShaderParams mParamsData;
+
+ ID3D11RasterizerState *mCopyRasterizerState;
+ ID3D11DepthStencilState *mCopyDepthStencilState;
+
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
new file mode 100755
index 000000000..58b18ded5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
@@ -0,0 +1,400 @@
+//
+// Copyright (c) 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/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace
+{
+
+GLuint64 MergeQueryResults(GLenum type, GLuint64 currentResult, GLuint64 newResult)
+{
+ switch (type)
+ {
+ case GL_ANY_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;
+
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ return currentResult + newResult;
+
+ case GL_TIME_ELAPSED_EXT:
+ return currentResult + newResult;
+
+ case GL_TIMESTAMP_EXT:
+ return newResult;
+
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ return newResult;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+} // anonymous namespace
+
+namespace rx
+{
+
+Query11::QueryState::QueryState()
+ : query(nullptr), beginTimestamp(nullptr), endTimestamp(nullptr), finished(false)
+{
+}
+
+Query11::QueryState::~QueryState()
+{
+ SafeRelease(beginTimestamp);
+ SafeRelease(endTimestamp);
+ SafeRelease(query);
+}
+
+Query11::Query11(Renderer11 *renderer, GLenum type)
+ : QueryImpl(type), mResult(0), mResultSum(0), mRenderer(renderer)
+{
+ mActiveQuery = std::unique_ptr<QueryState>(new QueryState());
+}
+
+Query11::~Query11()
+{
+ mRenderer->getStateManager()->onDeleteQueryObject(this);
+}
+
+gl::Error Query11::begin()
+{
+ mResultSum = 0;
+ mRenderer->getStateManager()->onBeginQuery(this);
+ return resume();
+}
+
+gl::Error Query11::end()
+{
+ return pause();
+}
+
+gl::Error Query11::queryCounter()
+{
+ // This doesn't do anything for D3D11 as we don't support timestamps
+ ASSERT(getType() == GL_TIMESTAMP_EXT);
+ mResultSum = 0;
+ mPendingQueries.push_back(std::unique_ptr<QueryState>(new QueryState()));
+ return gl::Error(GL_NO_ERROR);
+}
+
+template <typename T>
+gl::Error Query11::getResultBase(T *params)
+{
+ ASSERT(mActiveQuery->query == nullptr);
+ ANGLE_TRY(flush(true));
+ ASSERT(mPendingQueries.empty());
+ *params = static_cast<T>(mResultSum);
+
+ return gl::NoError();
+}
+
+gl::Error Query11::getResult(GLint *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error Query11::getResult(GLuint *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error Query11::getResult(GLint64 *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error Query11::getResult(GLuint64 *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error Query11::isResultAvailable(bool *available)
+{
+ ANGLE_TRY(flush(false));
+
+ *available = mPendingQueries.empty();
+ return gl::NoError();
+}
+
+gl::Error Query11::pause()
+{
+ if (mActiveQuery->query != nullptr)
+ {
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ GLenum queryType = getType();
+
+ // If we are doing time elapsed query the end timestamp
+ if (queryType == GL_TIME_ELAPSED_EXT)
+ {
+ context->End(mActiveQuery->endTimestamp);
+ }
+
+ context->End(mActiveQuery->query);
+
+ mPendingQueries.push_back(std::move(mActiveQuery));
+ mActiveQuery = std::unique_ptr<QueryState>(new QueryState());
+ }
+
+ return flush(false);
+}
+
+gl::Error Query11::resume()
+{
+ if (mActiveQuery->query == nullptr)
+ {
+ ANGLE_TRY(flush(false));
+
+ GLenum queryType = getType();
+ D3D11_QUERY d3dQueryType = gl_d3d11::ConvertQueryType(queryType);
+
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = d3dQueryType;
+ queryDesc.MiscFlags = 0;
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ HRESULT result = device->CreateQuery(&queryDesc, &mActiveQuery->query);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.",
+ result);
+ }
+
+ // If we are doing time elapsed we also need a query to actually query the timestamp
+ if (queryType == GL_TIME_ELAPSED_EXT)
+ {
+ D3D11_QUERY_DESC desc;
+ desc.Query = D3D11_QUERY_TIMESTAMP;
+ desc.MiscFlags = 0;
+ result = device->CreateQuery(&desc, &mActiveQuery->beginTimestamp);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.",
+ result);
+ }
+ result = device->CreateQuery(&desc, &mActiveQuery->endTimestamp);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.",
+ result);
+ }
+ }
+
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ if (d3dQueryType != D3D11_QUERY_EVENT)
+ {
+ context->Begin(mActiveQuery->query);
+ }
+
+ // If we are doing time elapsed, query the begin timestamp
+ if (queryType == GL_TIME_ELAPSED_EXT)
+ {
+ context->End(mActiveQuery->beginTimestamp);
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Query11::flush(bool force)
+{
+ while (!mPendingQueries.empty())
+ {
+ QueryState *query = mPendingQueries.front().get();
+
+ do
+ {
+ ANGLE_TRY(testQuery(query));
+ if (!query->finished && !force)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+ } while (!query->finished);
+
+ mResultSum = MergeQueryResults(getType(), mResultSum, mResult);
+ mPendingQueries.pop_front();
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Query11::testQuery(QueryState *queryState)
+{
+ if (!queryState->finished)
+ {
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ switch (getType())
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ {
+ ASSERT(queryState->query);
+ UINT64 numPixels = 0;
+ HRESULT result =
+ context->GetData(queryState->query, &numPixels, sizeof(numPixels), 0);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to get the data of an internal query, result: 0x%X.",
+ result);
+ }
+
+ if (result == S_OK)
+ {
+ queryState->finished = true;
+ mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ break;
+
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ {
+ ASSERT(queryState->query);
+ D3D11_QUERY_DATA_SO_STATISTICS soStats = {0};
+ HRESULT result = context->GetData(queryState->query, &soStats, sizeof(soStats), 0);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to get the data of an internal query, result: 0x%X.",
+ result);
+ }
+
+ if (result == S_OK)
+ {
+ queryState->finished = true;
+ mResult = static_cast<GLuint64>(soStats.NumPrimitivesWritten);
+ }
+ }
+ break;
+
+ case GL_TIME_ELAPSED_EXT:
+ {
+ ASSERT(queryState->query);
+ ASSERT(queryState->beginTimestamp);
+ ASSERT(queryState->endTimestamp);
+ D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timeStats = {0};
+ HRESULT result =
+ context->GetData(queryState->query, &timeStats, sizeof(timeStats), 0);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to get the data of an internal query, result: 0x%X.",
+ result);
+ }
+
+ if (result == S_OK)
+ {
+ UINT64 beginTime = 0;
+ HRESULT beginRes =
+ context->GetData(queryState->beginTimestamp, &beginTime, sizeof(UINT64), 0);
+ if (FAILED(beginRes))
+ {
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Failed to get the data of an internal query, result: 0x%X.", beginRes);
+ }
+ UINT64 endTime = 0;
+ HRESULT endRes =
+ context->GetData(queryState->endTimestamp, &endTime, sizeof(UINT64), 0);
+ if (FAILED(endRes))
+ {
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Failed to get the data of an internal query, result: 0x%X.", endRes);
+ }
+
+ 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_TIMESTAMP_EXT:
+ {
+ // 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 == nullptr);
+ mResult = 0;
+ queryState->finished = true;
+ }
+ break;
+
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ {
+ ASSERT(queryState->query);
+ BOOL completed = 0;
+ HRESULT result =
+ context->GetData(queryState->query, &completed, sizeof(completed), 0);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to get the data of an internal query, result: 0x%X.",
+ result);
+ }
+
+ if (result == S_OK)
+ {
+ queryState->finished = true;
+ ASSERT(completed == TRUE);
+ mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ if (!queryState->finished && mRenderer->testDeviceLost())
+ {
+ mRenderer->notifyDeviceLost();
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
+ }
+ }
+
+ return gl::NoError();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h
new file mode 100755
index 000000000..706f805df
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h
@@ -0,0 +1,67 @@
+//
+// Copyright (c) 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"
+
+namespace rx
+{
+class Renderer11;
+
+class Query11 : public QueryImpl
+{
+ public:
+ Query11(Renderer11 *renderer, GLenum type);
+ ~Query11() override;
+
+ gl::Error begin() override;
+ gl::Error end() override;
+ gl::Error queryCounter() override;
+ gl::Error getResult(GLint *params) override;
+ gl::Error getResult(GLuint *params) override;
+ gl::Error getResult(GLint64 *params) override;
+ gl::Error getResult(GLuint64 *params) override;
+ gl::Error isResultAvailable(bool *available) override;
+
+ gl::Error pause();
+ gl::Error resume();
+
+ private:
+ struct QueryState final : public angle::NonCopyable
+ {
+ QueryState();
+ ~QueryState();
+
+ ID3D11Query *query;
+ ID3D11Query *beginTimestamp;
+ ID3D11Query *endTimestamp;
+ bool finished;
+ };
+
+ gl::Error flush(bool force);
+ gl::Error testQuery(QueryState *queryState);
+
+ template <typename T>
+ gl::Error getResultBase(T *params);
+
+ GLuint64 mResult;
+ GLuint64 mResultSum;
+
+ Renderer11 *mRenderer;
+
+ std::unique_ptr<QueryState> mActiveQuery;
+ std::deque<std::unique_ptr<QueryState>> mPendingQueries;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
new file mode 100755
index 000000000..bd870bcbd
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
@@ -0,0 +1,473 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render
+// state objects.
+
+#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
+
+#include <float.h>
+
+#include "common/debug.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "third_party/murmurhash/MurmurHash3.h"
+
+namespace rx
+{
+using namespace gl_d3d11;
+
+template <typename mapType>
+static void ClearStateMap(mapType &map)
+{
+ for (typename mapType::iterator i = map.begin(); i != map.end(); i++)
+ {
+ SafeRelease(i->second.first);
+ }
+ map.clear();
+}
+
+// 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
+const unsigned int RenderStateCache::kMaxBlendStates = 4096;
+const unsigned int RenderStateCache::kMaxRasterizerStates = 4096;
+const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096;
+const unsigned int RenderStateCache::kMaxSamplerStates = 4096;
+
+RenderStateCache::RenderStateCache(Renderer11 *renderer)
+ : mRenderer(renderer),
+ mCounter(0),
+ mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates),
+ mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates),
+ mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates),
+ mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates),
+ mDevice(NULL)
+{
+}
+
+RenderStateCache::~RenderStateCache()
+{
+ clear();
+}
+
+void RenderStateCache::initialize(ID3D11Device *device)
+{
+ clear();
+ mDevice = device;
+}
+
+void RenderStateCache::clear()
+{
+ ClearStateMap(mBlendStateCache);
+ ClearStateMap(mRasterizerStateCache);
+ ClearStateMap(mDepthStencilStateCache);
+ ClearStateMap(mSamplerStateCache);
+}
+
+std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState)
+{
+ static const unsigned int seed = 0xABCDEF98;
+
+ std::size_t hash = 0;
+ MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash);
+ return hash;
+}
+
+bool RenderStateCache::compareBlendStates(const BlendStateKey &a, const BlendStateKey &b)
+{
+ return memcmp(&a, &b, sizeof(BlendStateKey)) == 0;
+}
+
+gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState,
+ ID3D11BlendState **outBlendState)
+{
+ if (!mDevice)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
+ }
+
+ bool mrt = false;
+
+ const FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer);
+ const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender();
+
+ BlendStateKey key = {};
+ key.blendState = blendState;
+ for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
+ {
+ const gl::FramebufferAttachment *attachment = colorbuffers[colorAttachment];
+
+ auto rtChannels = key.rtChannels[colorAttachment];
+
+ if (attachment)
+ {
+ if (colorAttachment > 0)
+ {
+ mrt = true;
+ }
+
+ rtChannels[0] = attachment->getRedSize() > 0;
+ rtChannels[1] = attachment->getGreenSize() > 0;
+ rtChannels[2] = attachment->getBlueSize() > 0;
+ rtChannels[3] = attachment->getAlphaSize() > 0;
+ }
+ }
+
+ BlendStateMap::iterator keyIter = mBlendStateCache.find(key);
+ if (keyIter != mBlendStateCache.end())
+ {
+ BlendStateCounterPair &state = keyIter->second;
+ state.second = mCounter++;
+ *outBlendState = state.first;
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ if (mBlendStateCache.size() >= kMaxBlendStates)
+ {
+ TRACE("Overflowed the limit of %u blend states, removing the least recently used "
+ "to make room.", kMaxBlendStates);
+
+ BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin();
+ for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++)
+ {
+ if (i->second.second < leastRecentlyUsed->second.second)
+ {
+ leastRecentlyUsed = i;
+ }
+ }
+ SafeRelease(leastRecentlyUsed->second.first);
+ mBlendStateCache.erase(leastRecentlyUsed);
+ }
+
+ // Create a new blend state and insert it into the cache
+ D3D11_BLEND_DESC blendDesc = { 0 };
+ blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage;
+ blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE;
+
+ for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ {
+ D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i];
+
+ rtBlend.BlendEnable = blendState.blend;
+ if (blendState.blend)
+ {
+ rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false);
+ rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false);
+ rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB);
+
+ rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true);
+ rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true);
+ rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha);
+ }
+
+ rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed,
+ key.rtChannels[i][1] && blendState.colorMaskGreen,
+ key.rtChannels[i][2] && blendState.colorMaskBlue,
+ key.rtChannels[i][3] && blendState.colorMaskAlpha);
+ }
+
+ ID3D11BlendState *dx11BlendState = NULL;
+ HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState);
+ if (FAILED(result) || !dx11BlendState)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
+ }
+
+ mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++)));
+
+ *outBlendState = dx11BlendState;
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState)
+{
+ static const unsigned int seed = 0xABCDEF98;
+
+ std::size_t hash = 0;
+ MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash);
+ return hash;
+}
+
+bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b)
+{
+ return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
+}
+
+gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled,
+ ID3D11RasterizerState **outRasterizerState)
+{
+ if (!mDevice)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
+ }
+
+ RasterizerStateKey key = {};
+ key.rasterizerState = rasterState;
+ key.scissorEnabled = scissorEnabled;
+
+ RasterizerStateMap::iterator keyIter = mRasterizerStateCache.find(key);
+ if (keyIter != mRasterizerStateCache.end())
+ {
+ RasterizerStateCounterPair &state = keyIter->second;
+ state.second = mCounter++;
+ *outRasterizerState = state.first;
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ if (mRasterizerStateCache.size() >= kMaxRasterizerStates)
+ {
+ TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used "
+ "to make room.", kMaxRasterizerStates);
+
+ RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin();
+ for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++)
+ {
+ if (i->second.second < leastRecentlyUsed->second.second)
+ {
+ leastRecentlyUsed = i;
+ }
+ }
+ SafeRelease(leastRecentlyUsed->second.first);
+ mRasterizerStateCache.erase(leastRecentlyUsed);
+ }
+
+ 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;
+ }
+
+ ID3D11RasterizerState *dx11RasterizerState = NULL;
+ HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState);
+ if (FAILED(result) || !dx11RasterizerState)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result);
+ }
+
+ mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++)));
+
+ *outRasterizerState = dx11RasterizerState;
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState)
+{
+ static const unsigned int seed = 0xABCDEF98;
+
+ std::size_t hash = 0;
+ MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash);
+ return hash;
+}
+
+bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b)
+{
+ return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0;
+}
+
+gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &originalState,
+ bool disableDepth,
+ bool disableStencil,
+ ID3D11DepthStencilState **outDSState)
+{
+ if (!mDevice)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
+ }
+
+ gl::DepthStencilState glState = originalState;
+ if (disableDepth)
+ {
+ glState.depthTest = false;
+ glState.depthMask = false;
+ }
+
+ if (disableStencil)
+ {
+ glState.stencilWritemask = 0;
+ glState.stencilBackWritemask = 0;
+ glState.stencilTest = false;
+ }
+
+ auto keyIter = mDepthStencilStateCache.find(glState);
+ if (keyIter != mDepthStencilStateCache.end())
+ {
+ DepthStencilStateCounterPair &state = keyIter->second;
+ state.second = mCounter++;
+ *outDSState = state.first;
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates)
+ {
+ TRACE(
+ "Overflowed the limit of %u depth stencil states, removing the least recently used "
+ "to make room.",
+ kMaxDepthStencilStates);
+
+ auto leastRecentlyUsed = mDepthStencilStateCache.begin();
+ for (auto i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
+ {
+ if (i->second.second < leastRecentlyUsed->second.second)
+ {
+ leastRecentlyUsed = i;
+ }
+ }
+ SafeRelease(leastRecentlyUsed->second.first);
+ mDepthStencilStateCache.erase(leastRecentlyUsed);
+ }
+
+ D3D11_DEPTH_STENCIL_DESC dsDesc = {0};
+ 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);
+
+ ID3D11DepthStencilState *dx11DepthStencilState = NULL;
+ HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState);
+ if (FAILED(result) || !dx11DepthStencilState)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
+ }
+
+ mDepthStencilStateCache.insert(
+ std::make_pair(glState, std::make_pair(dx11DepthStencilState, mCounter++)));
+
+ *outDSState = dx11DepthStencilState;
+ return gl::Error(GL_NO_ERROR);
+}
+
+std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState)
+{
+ static const unsigned int seed = 0xABCDEF98;
+
+ std::size_t hash = 0;
+ MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash);
+ return hash;
+}
+
+bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b)
+{
+ return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0;
+}
+
+gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState)
+{
+ if (!mDevice)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
+ }
+
+ SamplerStateMap::iterator keyIter = mSamplerStateCache.find(samplerState);
+ if (keyIter != mSamplerStateCache.end())
+ {
+ SamplerStateCounterPair &state = keyIter->second;
+ state.second = mCounter++;
+ *outSamplerState = state.first;
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ if (mSamplerStateCache.size() >= kMaxSamplerStates)
+ {
+ TRACE("Overflowed the limit of %u sampler states, removing the least recently used "
+ "to make room.", kMaxSamplerStates);
+
+ SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin();
+ for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++)
+ {
+ if (i->second.second < leastRecentlyUsed->second.second)
+ {
+ leastRecentlyUsed = i;
+ }
+ }
+ SafeRelease(leastRecentlyUsed->second.first);
+ mSamplerStateCache.erase(leastRecentlyUsed);
+ }
+
+ D3D11_SAMPLER_DESC samplerDesc;
+ samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter,
+ samplerState.maxAnisotropy, samplerState.compareMode);
+ samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS);
+ samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT);
+ samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR);
+ samplerDesc.MipLODBias = 0;
+ samplerDesc.MaxAnisotropy =
+ gl_d3d11::ConvertMaxAnisotropy(samplerState.maxAnisotropy, mDevice->GetFeatureLevel());
+ samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.compareFunc);
+ samplerDesc.BorderColor[0] = 0.0f;
+ samplerDesc.BorderColor[1] = 0.0f;
+ samplerDesc.BorderColor[2] = 0.0f;
+ samplerDesc.BorderColor[3] = 0.0f;
+ samplerDesc.MinLOD = samplerState.minLod;
+ samplerDesc.MaxLOD = samplerState.maxLod;
+
+ if (mRenderer->getRenderer11DeviceCaps().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.maxLod >= 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;
+ }
+
+ ID3D11SamplerState *dx11SamplerState = NULL;
+ HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState);
+ if (FAILED(result) || !dx11SamplerState)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11SamplerState, HRESULT: 0x%X.", result);
+ }
+
+ mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++)));
+
+ *outSamplerState = dx11SamplerState;
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
new file mode 100755
index 000000000..82cb13903
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
@@ -0,0 +1,114 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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 "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+#include "common/angleutils.h"
+
+#include <unordered_map>
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Renderer11;
+
+class RenderStateCache : angle::NonCopyable
+{
+ public:
+ RenderStateCache(Renderer11 *renderer);
+ virtual ~RenderStateCache();
+
+ void initialize(ID3D11Device *device);
+ void clear();
+
+ gl::Error getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, ID3D11BlendState **outBlendState);
+ gl::Error getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, ID3D11RasterizerState **outRasterizerState);
+ gl::Error getDepthStencilState(const gl::DepthStencilState &dsState,
+ bool disableDepth,
+ bool disableStencil,
+ ID3D11DepthStencilState **outDSState);
+ gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState);
+
+ private:
+ Renderer11 *mRenderer;
+ unsigned long long mCounter;
+
+ // Blend state cache
+ struct BlendStateKey
+ {
+ gl::BlendState blendState;
+ bool rtChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4];
+ };
+ static std::size_t hashBlendState(const BlendStateKey &blendState);
+ static bool compareBlendStates(const BlendStateKey &a, const BlendStateKey &b);
+ static const unsigned int kMaxBlendStates;
+
+ typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &);
+ typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &);
+ typedef std::pair<ID3D11BlendState*, unsigned long long> BlendStateCounterPair;
+ typedef std::unordered_map<BlendStateKey, BlendStateCounterPair, BlendStateHashFunction, BlendStateEqualityFunction> BlendStateMap;
+ BlendStateMap mBlendStateCache;
+
+ // Rasterizer state cache
+ struct RasterizerStateKey
+ {
+ gl::RasterizerState rasterizerState;
+ bool scissorEnabled;
+ };
+ static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState);
+ static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b);
+ static const unsigned int kMaxRasterizerStates;
+
+ typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &);
+ typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &);
+ typedef std::pair<ID3D11RasterizerState*, unsigned long long> RasterizerStateCounterPair;
+ typedef std::unordered_map<RasterizerStateKey, RasterizerStateCounterPair, RasterizerStateHashFunction, RasterizerStateEqualityFunction> RasterizerStateMap;
+ RasterizerStateMap mRasterizerStateCache;
+
+ // Depth stencil state cache
+ static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState);
+ static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b);
+ static const unsigned int kMaxDepthStencilStates;
+
+ typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &);
+ typedef bool (*DepthStencilStateEqualityFunction)(const gl::DepthStencilState &, const gl::DepthStencilState &);
+ typedef std::pair<ID3D11DepthStencilState*, unsigned long long> DepthStencilStateCounterPair;
+ typedef std::unordered_map<gl::DepthStencilState,
+ DepthStencilStateCounterPair,
+ DepthStencilStateHashFunction,
+ DepthStencilStateEqualityFunction> DepthStencilStateMap;
+ DepthStencilStateMap mDepthStencilStateCache;
+
+ // Sample state cache
+ static std::size_t hashSamplerState(const gl::SamplerState &samplerState);
+ static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b);
+ static const unsigned int kMaxSamplerStates;
+
+ typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &);
+ typedef bool (*SamplerStateEqualityFunction)(const gl::SamplerState &, const gl::SamplerState &);
+ typedef std::pair<ID3D11SamplerState*, unsigned long long> SamplerStateCounterPair;
+ typedef std::unordered_map<gl::SamplerState,
+ SamplerStateCounterPair,
+ SamplerStateHashFunction,
+ SamplerStateEqualityFunction> SamplerStateMap;
+ SamplerStateMap mSamplerStateCache;
+
+ ID3D11Device *mDevice;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
new file mode 100755
index 000000000..a042f447d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
@@ -0,0 +1,444 @@
+//
+// Copyright (c) 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/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.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()
+{
+ signalDirty();
+}
+
+void RenderTarget11::signalDirty()
+{
+ mBroadcastChannel.signal();
+
+ // Clear the list. We can't do this in the receiver because it would mutate during iteration.
+ mBroadcastChannel.reset();
+}
+
+TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv,
+ ID3D11Resource *resource,
+ ID3D11ShaderResourceView *srv,
+ ID3D11ShaderResourceView *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(rtv),
+ mDepthStencil(NULL),
+ mShaderResource(srv),
+ mBlitShaderResource(blitSRV)
+{
+ if (mTexture)
+ {
+ mTexture->AddRef();
+ }
+
+ if (mRenderTarget)
+ {
+ mRenderTarget->AddRef();
+ }
+
+ if (mShaderResource)
+ {
+ mShaderResource->AddRef();
+ }
+
+ if (mBlitShaderResource)
+ {
+ mBlitShaderResource->AddRef();
+ }
+
+ if (mRenderTarget && mTexture)
+ {
+ mSubresourceIndex = GetRTVSubresourceIndex(mTexture, mRenderTarget);
+ }
+ ASSERT(mFormatSet.formatID != angle::Format::ID::NONE || mWidth == 0 || mHeight == 0);
+}
+
+TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv,
+ ID3D11Resource *resource,
+ ID3D11ShaderResourceView *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(NULL),
+ mDepthStencil(dsv),
+ mShaderResource(srv),
+ mBlitShaderResource(nullptr)
+{
+ if (mTexture)
+ {
+ mTexture->AddRef();
+ }
+
+ if (mDepthStencil)
+ {
+ mDepthStencil->AddRef();
+ }
+
+ if (mShaderResource)
+ {
+ mShaderResource->AddRef();
+ }
+
+ if (mDepthStencil && mTexture)
+ {
+ mSubresourceIndex = GetDSVSubresourceIndex(mTexture, mDepthStencil);
+ }
+ ASSERT(mFormatSet.formatID != angle::Format::ID::NONE || mWidth == 0 || mHeight == 0);
+}
+
+TextureRenderTarget11::~TextureRenderTarget11()
+{
+ SafeRelease(mTexture);
+ SafeRelease(mRenderTarget);
+ SafeRelease(mDepthStencil);
+ SafeRelease(mShaderResource);
+ SafeRelease(mBlitShaderResource);
+}
+
+ID3D11Resource *TextureRenderTarget11::getTexture() const
+{
+ return mTexture;
+}
+
+ID3D11RenderTargetView *TextureRenderTarget11::getRenderTargetView() const
+{
+ return mRenderTarget;
+}
+
+ID3D11DepthStencilView *TextureRenderTarget11::getDepthStencilView() const
+{
+ return mDepthStencil;
+}
+
+ID3D11ShaderResourceView *TextureRenderTarget11::getShaderResourceView() const
+{
+ return mShaderResource;
+}
+
+ID3D11ShaderResourceView *TextureRenderTarget11::getBlitShaderResourceView() const
+{
+ return mBlitShaderResource;
+}
+
+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
+{
+ // Our EGL surfaces do not support multisampling.
+ return 0;
+}
+
+ID3D11Resource *SurfaceRenderTarget11::getTexture() const
+{
+ return (mDepth ? mSwapChain->getDepthStencilTexture() : mSwapChain->getOffscreenTexture());
+}
+
+ID3D11RenderTargetView *SurfaceRenderTarget11::getRenderTargetView() const
+{
+ return (mDepth ? NULL : mSwapChain->getRenderTarget());
+}
+
+ID3D11DepthStencilView *SurfaceRenderTarget11::getDepthStencilView() const
+{
+ return (mDepth ? mSwapChain->getDepthStencil() : NULL);
+}
+
+ID3D11ShaderResourceView *SurfaceRenderTarget11::getShaderResourceView() const
+{
+ return (mDepth ? mSwapChain->getDepthStencilShaderResource()
+ : mSwapChain->getRenderTargetShaderResource());
+}
+
+ID3D11ShaderResourceView *SurfaceRenderTarget11::getBlitShaderResourceView() const
+{
+ // The SurfaceRenderTargetView format should always be such that the normal SRV works for blits.
+ return getShaderResourceView();
+}
+
+unsigned int SurfaceRenderTarget11::getSubresourceIndex() const
+{
+ return 0;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h
new file mode 100755
index 000000000..4ee0de292
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h
@@ -0,0 +1,131 @@
+//
+// Copyright (c) 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/texture_format_table.h"
+#include "libANGLE/signal_utils.h"
+
+namespace rx
+{
+class SwapChain11;
+class Renderer11;
+
+class RenderTarget11 : public RenderTargetD3D
+{
+ public:
+ RenderTarget11(const d3d11::Format &formatSet);
+ virtual ~RenderTarget11();
+
+ virtual ID3D11Resource *getTexture() const = 0;
+ virtual ID3D11RenderTargetView *getRenderTargetView() const = 0;
+ virtual ID3D11DepthStencilView *getDepthStencilView() const = 0;
+ virtual ID3D11ShaderResourceView *getShaderResourceView() const = 0;
+ virtual ID3D11ShaderResourceView *getBlitShaderResourceView() const = 0;
+
+ virtual unsigned int getSubresourceIndex() const = 0;
+
+ void signalDirty() override;
+ angle::BroadcastChannel *getBroadcastChannel() { return &mBroadcastChannel; }
+
+ const d3d11::Format &getFormatSet() const { return mFormatSet; }
+
+ protected:
+ angle::BroadcastChannel mBroadcastChannel;
+ const d3d11::Format &mFormatSet;
+};
+
+class TextureRenderTarget11 : public RenderTarget11
+{
+ public:
+ // TextureRenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them
+ TextureRenderTarget11(ID3D11RenderTargetView *rtv,
+ ID3D11Resource *resource,
+ ID3D11ShaderResourceView *srv,
+ ID3D11ShaderResourceView *blitSRV,
+ GLenum internalFormat,
+ const d3d11::Format &formatSet,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei samples);
+ TextureRenderTarget11(ID3D11DepthStencilView *dsv,
+ ID3D11Resource *resource,
+ ID3D11ShaderResourceView *srv,
+ GLenum internalFormat,
+ const d3d11::Format &formatSet,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei samples);
+ virtual ~TextureRenderTarget11();
+
+ GLsizei getWidth() const override;
+ GLsizei getHeight() const override;
+ GLsizei getDepth() const override;
+ GLenum getInternalFormat() const override;
+ GLsizei getSamples() const override;
+
+ ID3D11Resource *getTexture() const override;
+ ID3D11RenderTargetView *getRenderTargetView() const override;
+ ID3D11DepthStencilView *getDepthStencilView() const override;
+ ID3D11ShaderResourceView *getShaderResourceView() const override;
+ ID3D11ShaderResourceView *getBlitShaderResourceView() const override;
+
+ unsigned int getSubresourceIndex() const override;
+
+ private:
+ GLsizei mWidth;
+ GLsizei mHeight;
+ GLsizei mDepth;
+ GLenum mInternalFormat;
+ GLsizei mSamples;
+
+ unsigned int mSubresourceIndex;
+ ID3D11Resource *mTexture;
+ ID3D11RenderTargetView *mRenderTarget;
+ ID3D11DepthStencilView *mDepthStencil;
+ ID3D11ShaderResourceView *mShaderResource;
+
+ // Shader resource view to use with internal blit shaders. Not set for depth/stencil render
+ // targets.
+ ID3D11ShaderResourceView *mBlitShaderResource;
+};
+
+class SurfaceRenderTarget11 : public RenderTarget11
+{
+ public:
+ SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth);
+ virtual ~SurfaceRenderTarget11();
+
+ GLsizei getWidth() const override;
+ GLsizei getHeight() const override;
+ GLsizei getDepth() const override;
+ GLenum getInternalFormat() const override;
+ GLsizei getSamples() const override;
+
+ ID3D11Resource *getTexture() const override;
+ ID3D11RenderTargetView *getRenderTargetView() const override;
+ ID3D11DepthStencilView *getDepthStencilView() const override;
+ ID3D11ShaderResourceView *getShaderResourceView() const override;
+ ID3D11ShaderResourceView *getBlitShaderResourceView() const 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/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
new file mode 100755
index 000000000..8b4abaf9c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -0,0 +1,4614 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
+
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+#include <EGL/eglext.h>
+#include <iomanip>
+#include <sstream>
+#include <versionhelpers.h>
+
+#include "common/tls.h"
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/DisplayD3D.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/dxgi_support_table.h"
+#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.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/Query11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.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/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.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/VertexDataManager.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "third_party/trace_event/trace_event.h"
+
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+#include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h"
+#else
+#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h"
+#endif
+
+// Include the D3D9 debug annotator header for use by the desktop D3D11 renderer
+// because the D3D11 interface method ID3DUserDefinedAnnotation::GetStatus
+// doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
+#ifdef ANGLE_ENABLE_D3D9
+#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.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
+
+#ifdef _DEBUG
+// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples
+// and conformance tests. to enable all warnings, remove this define.
+#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1
+#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;
+ // Note: we don't ever request a 11_1 device, because this gives
+ // an E_INVALIDARG error on systems that don't have the platform update.
+ 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 GLvoid *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;
+ }
+}
+
+template <typename T>
+void CopyLineLoopIndicesWithRestart(const GLvoid *indices,
+ size_t count,
+ GLenum indexType,
+ std::vector<GLuint> *bufferOut)
+{
+ GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType);
+ GLuint d3dRestartIndex = static_cast<GLuint>(d3d11::GetPrimitiveRestartIndex());
+ const T *srcPtr = static_cast<const T *>(indices);
+ Optional<GLuint> currentLoopStart;
+
+ bufferOut->clear();
+
+ for (size_t indexIdx = 0; indexIdx < count; ++indexIdx)
+ {
+ GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);
+
+ if (value == restartIndex)
+ {
+ if (currentLoopStart.valid())
+ {
+ bufferOut->push_back(currentLoopStart.value());
+ bufferOut->push_back(d3dRestartIndex);
+ currentLoopStart.reset();
+ }
+ }
+ else
+ {
+ bufferOut->push_back(value);
+ if (!currentLoopStart.valid())
+ {
+ currentLoopStart = value;
+ }
+ }
+ }
+
+ if (currentLoopStart.valid())
+ {
+ bufferOut->push_back(currentLoopStart.value());
+ }
+}
+
+void GetLineLoopIndices(const GLvoid *indices,
+ GLenum indexType,
+ GLuint count,
+ bool usePrimitiveRestartFixedIndex,
+ std::vector<GLuint> *bufferOut)
+{
+ if (indexType != GL_NONE && usePrimitiveRestartFixedIndex)
+ {
+ switch (indexType)
+ {
+ case GL_UNSIGNED_BYTE:
+ CopyLineLoopIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
+ break;
+ case GL_UNSIGNED_SHORT:
+ CopyLineLoopIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
+ break;
+ case GL_UNSIGNED_INT:
+ CopyLineLoopIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
+ 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_NONE:
+ SetLineLoopIndices(&(*bufferOut)[0], count);
+ break;
+ case GL_UNSIGNED_BYTE:
+ CopyLineLoopIndices<GLubyte>(indices, &(*bufferOut)[0], count);
+ break;
+ case GL_UNSIGNED_SHORT:
+ CopyLineLoopIndices<GLushort>(indices, &(*bufferOut)[0], count);
+ break;
+ case GL_UNSIGNED_INT:
+ CopyLineLoopIndices<GLuint>(indices, &(*bufferOut)[0], count);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename T>
+void CopyTriangleFanIndices(const GLvoid *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 GLvoid *indices,
+ GLuint indexCount,
+ GLenum indexType,
+ std::vector<GLuint> *bufferOut)
+{
+ GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType);
+ GLuint d3dRestartIndex = gl::GetPrimitiveRestartIndex(GL_UNSIGNED_INT);
+ 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 GLvoid *indices,
+ GLenum indexType,
+ GLuint count,
+ bool usePrimitiveRestartFixedIndex,
+ std::vector<GLuint> *bufferOut)
+{
+ if (indexType != GL_NONE && usePrimitiveRestartFixedIndex)
+ {
+ switch (indexType)
+ {
+ case GL_UNSIGNED_BYTE:
+ CopyTriangleFanIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
+ break;
+ case GL_UNSIGNED_SHORT:
+ CopyTriangleFanIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
+ break;
+ case GL_UNSIGNED_INT:
+ 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_NONE:
+ SetTriangleFanIndices(&(*bufferOut)[0], numTris);
+ break;
+ case GL_UNSIGNED_BYTE:
+ CopyTriangleFanIndices<GLubyte>(indices, &(*bufferOut)[0], numTris);
+ break;
+ case GL_UNSIGNED_SHORT:
+ CopyTriangleFanIndices<GLushort>(indices, &(*bufferOut)[0], numTris);
+ break;
+ case GL_UNSIGNED_INT:
+ CopyTriangleFanIndices<GLuint>(indices, &(*bufferOut)[0], numTris);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+int GetWrapBits(GLenum wrap)
+{
+ switch (wrap)
+ {
+ case GL_CLAMP_TO_EDGE:
+ return 0x1;
+ case GL_REPEAT:
+ return 0x2;
+ case GL_MIRRORED_REPEAT:
+ return 0x3;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+// If we request a scratch buffer requesting a smaller size this many times,
+// release and recreate the scratch buffer. This ensures we don't have a
+// degenerate case where we are stuck hogging memory.
+const int ScratchMemoryBufferLifetime = 1000;
+
+} // anonymous namespace
+
+Renderer11::Renderer11(egl::Display *display)
+ : RendererD3D(display),
+ mStateCache(this),
+ mStateManager(this),
+ mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime()),
+ mDebug(nullptr),
+ mScratchMemoryBufferResetCounter(0),
+ mAnnotator(nullptr)
+{
+ mVertexDataManager = NULL;
+ mIndexDataManager = NULL;
+
+ mLineLoopIB = NULL;
+ mTriangleFanIB = NULL;
+ mAppliedIBChanged = false;
+
+ mBlit = NULL;
+ mPixelTransfer = NULL;
+
+ mClear = NULL;
+
+ mTrim = NULL;
+
+ mSyncQuery = NULL;
+
+ mRenderer11DeviceCaps.supportsClearView = false;
+ mRenderer11DeviceCaps.supportsConstantBufferOffsets = false;
+ mRenderer11DeviceCaps.supportsDXGI1_2 = false;
+ mRenderer11DeviceCaps.B5G6R5support = 0;
+ mRenderer11DeviceCaps.B4G4R4A4support = 0;
+ mRenderer11DeviceCaps.B5G5R5A1support = 0;
+
+ mD3d11Module = NULL;
+ mDxgiModule = NULL;
+ mDCompModule = NULL;
+ mCreatedWithDeviceEXT = false;
+ mEGLDevice = nullptr;
+
+ mDevice = NULL;
+ mDeviceContext = NULL;
+ mDeviceContext1 = NULL;
+ mDxgiAdapter = NULL;
+ mDxgiFactory = NULL;
+
+ mDriverConstantBufferVS = NULL;
+ mDriverConstantBufferPS = NULL;
+
+ mAppliedVertexShader = NULL;
+ mAppliedGeometryShader = NULL;
+ mAppliedPixelShader = NULL;
+
+ mAppliedTFObject = angle::DirtyPointer;
+
+ ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription));
+
+ if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
+ {
+ const auto &attributes = mDisplay->getAttributeMap();
+
+ 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 >= 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_WARP_ANGLE:
+ mRequestedDriverType = D3D_DRIVER_TYPE_WARP;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
+ mRequestedDriverType = D3D_DRIVER_TYPE_REFERENCE;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+ mRequestedDriverType = D3D_DRIVER_TYPE_NULL;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ 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);
+ }
+ else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
+ {
+ mEGLDevice = GetImplAs<DeviceD3D>(display->getDevice());
+ ASSERT(mEGLDevice != 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;
+ mPresentPathFastEnabled = false;
+ }
+
+// The D3D11 renderer must choose the D3D9 debug annotator because the D3D11 interface
+// method ID3DUserDefinedAnnotation::GetStatus on desktop builds doesn't work with the Graphics
+// Diagnostics tools in Visual Studio 2013.
+// The D3D9 annotator works properly for both D3D11 and D3D9.
+// Incorrect status reporting can cause ANGLE to log unnecessary debug events.
+#ifdef ANGLE_ENABLE_D3D9
+ mAnnotator = new DebugAnnotator9();
+#else
+ mAnnotator = new DebugAnnotator11();
+#endif
+ ASSERT(mAnnotator);
+ gl::InitializeDebugAnnotations(mAnnotator);
+}
+
+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_STORE)
+#if !ANGLE_SKIP_DXGI_1_2_CHECK
+ {
+ 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 = NULL;
+ result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void **)&dxgiDevice2);
+ if (FAILED(result))
+ {
+ return egl::Error(
+ EGL_NOT_INITIALIZED, D3D11_INIT_INCOMPATIBLE_DXGI,
+ "DXGI 1.2 required to present to HWNDs owned by another process.");
+ }
+ SafeRelease(dxgiDevice2);
+ }
+ }
+#endif
+#endif
+
+ {
+ TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)");
+ // Cast the DeviceContext to a DeviceContext1.
+ // This could fail on Windows 7 without the Platform Update.
+ // Don't error in this case- just don't use mDeviceContext1.
+ mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext);
+
+ IDXGIDevice *dxgiDevice = NULL;
+ result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
+
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR,
+ "Could not query DXGI device.");
+ }
+
+ result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&mDxgiAdapter);
+
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, 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 != NULL)
+ {
+ 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::Error(EGL_NOT_INITIALIZED, 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::Error(EGL_NOT_INITIALIZED, D3D11_INIT_OTHER_ERROR,
+ "Could not create DXGI factory.");
+ }
+ }
+
+// Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
+#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
+ {
+ 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};
+
+ D3D11_INFO_QUEUE_FILTER filter = {};
+ filter.DenyList.NumIDs = static_cast<unsigned int>(ArraySize(hideMessages));
+ filter.DenyList.pIDList = hideMessages;
+
+ infoQueue->AddStorageFilterEntries(&filter);
+ SafeRelease(infoQueue);
+ }
+ }
+#endif
+
+#if !defined(NDEBUG)
+ mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice);
+#endif
+
+ initializeDevice();
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error Renderer11::initializeD3DDevice()
+{
+ HRESULT result = S_OK;
+
+ if (!mCreatedWithDeviceEXT)
+ {
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr;
+ {
+ SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS");
+ TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
+ mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
+ mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+ mDCompModule = LoadLibrary(TEXT("dcomp.dll"));
+
+ if (mD3d11Module == nullptr || mDxgiModule == nullptr)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP,
+ "Could not load D3D11 or DXGI library.");
+ }
+
+ // create the D3D11 device
+ ASSERT(mDevice == nullptr);
+ D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
+ GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
+
+ if (D3D11CreateDevice == nullptr)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP,
+ "Could not retrieve D3D11CreateDevice address.");
+ }
+ }
+#endif
+
+#ifdef _DEBUG
+ {
+ TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)");
+ result = D3D11CreateDevice(nullptr, mRequestedDriverType, nullptr,
+ D3D11_CREATE_DEVICE_DEBUG, mAvailableFeatureLevels.data(),
+ static_cast<unsigned int>(mAvailableFeatureLevels.size()),
+ D3D11_SDK_VERSION, &mDevice,
+ &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
+ }
+
+ if (!mDevice || FAILED(result))
+ {
+ ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
+ }
+
+ if (!mDevice || FAILED(result))
+#endif
+ {
+ SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS");
+ TRACE_EVENT0("gpu.angle", "D3D11CreateDevice");
+
+ result = D3D11CreateDevice(
+ nullptr, mRequestedDriverType, nullptr, 0, mAvailableFeatureLevels.data(),
+ static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION,
+ &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
+
+ // Cleanup done by destructor
+ if (!mDevice || FAILED(result))
+ {
+ ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError",
+ static_cast<int>(result));
+ return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_CREATEDEVICE_ERROR,
+ "Could not create D3D11 device.");
+ }
+ }
+ }
+ else
+ {
+ // We should use the inputted D3D11 device instead
+ void *device = nullptr;
+ ANGLE_TRY(mEGLDevice->getDevice(&device));
+
+ ID3D11Device *d3dDevice = reinterpret_cast<ID3D11Device *>(device);
+ if (FAILED(d3dDevice->GetDeviceRemovedReason()))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Inputted D3D11 device has been lost.");
+ }
+
+ if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED,
+ "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();
+ }
+
+ d3d11::SetDebugName(mDeviceContext, "DeviceContext");
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+// 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.
+void Renderer11::initializeDevice()
+{
+ SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDeviceMS");
+ TRACE_EVENT0("gpu.angle", "Renderer11::initializeDevice");
+
+ populateRenderer11DeviceCaps();
+
+ mStateCache.initialize(mDevice);
+ mInputLayoutCache.initialize(mDevice, mDeviceContext);
+
+ ASSERT(!mVertexDataManager && !mIndexDataManager);
+ mVertexDataManager = new VertexDataManager(this);
+ mIndexDataManager = new IndexDataManager(this, getRendererClass());
+
+ 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);
+
+ const gl::Caps &rendererCaps = getNativeCaps();
+
+ mStateManager.initialize(rendererCaps);
+
+ mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
+ mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
+ mSamplerMetadataVS.initData(rendererCaps.maxVertexTextureImageUnits);
+
+ mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
+ mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
+ mSamplerMetadataPS.initData(rendererCaps.maxTextureImageUnits);
+
+ mStateManager.initialize(rendererCaps);
+
+ markAllStateDirty();
+
+ // 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);
+}
+
+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 (getWorkarounds().disableB5G6R5Support)
+ {
+ mRenderer11DeviceCaps.B5G6R5support = 0;
+ }
+ else
+ {
+ hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G6R5_UNORM,
+ &(mRenderer11DeviceCaps.B5G6R5support));
+ if (FAILED(hr))
+ {
+ mRenderer11DeviceCaps.B5G6R5support = 0;
+ }
+ }
+
+ hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B4G4R4A4_UNORM,
+ &(mRenderer11DeviceCaps.B4G4R4A4support));
+ if (FAILED(hr))
+ {
+ mRenderer11DeviceCaps.B4G4R4A4support = 0;
+ }
+
+ hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G5R5A1_UNORM,
+ &(mRenderer11DeviceCaps.B5G5R5A1support));
+ if (FAILED(hr))
+ {
+ mRenderer11DeviceCaps.B5G5R5A1support = 0;
+ }
+
+ IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
+ mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr);
+ SafeRelease(dxgiAdapter2);
+}
+
+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 (!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_COMPONENT16,
+ };
+
+ 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.renderable)
+ {
+ continue;
+ }
+
+ for (GLenum depthStencilBufferInternalFormat : depthStencilBufferFormats)
+ {
+ const gl::TextureCaps &depthStencilBufferFormatCaps =
+ rendererTextureCaps.get(depthStencilBufferInternalFormat);
+ if (!depthStencilBufferFormatCaps.renderable &&
+ depthStencilBufferInternalFormat != GL_NONE)
+ {
+ continue;
+ }
+
+ const gl::InternalFormat &colorBufferFormatInfo =
+ gl::GetInternalFormatInfo(colorBufferInternalFormat);
+ const gl::InternalFormat &depthStencilBufferFormatInfo =
+ gl::GetInternalFormatInfo(depthStencilBufferInternalFormat);
+ const gl::Version &maxVersion = getMaxSupportedESVersion();
+
+ 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;
+ 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 = 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.optimalOrientation = optimalSurfaceOrientation;
+
+ 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->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->deviceQuery = true;
+
+ outExtensions->image = true;
+ outExtensions->imageBase = true;
+ outExtensions->glTexture2DImage = true;
+ outExtensions->glTextureCubemapImage = true;
+ outExtensions->glRenderbufferImage = true;
+
+ outExtensions->stream = true;
+ outExtensions->streamConsumerGLTexture = true;
+ outExtensions->streamConsumerGLTextureYUV = true;
+ // Not all D3D11 devices support NV12 textures
+ if (getNV12TextureSupport())
+ {
+ outExtensions->streamProducerD3DTextureNV12 = true;
+ }
+
+ outExtensions->flexibleSurfaceCompatibility = true;
+ outExtensions->directComposition = !!mDCompModule;
+}
+
+gl::Error Renderer11::flush()
+{
+ mDeviceContext->Flush();
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::finish()
+{
+ HRESULT result;
+
+ if (!mSyncQuery)
+ {
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = D3D11_QUERY_EVENT;
+ queryDesc.MiscFlags = 0;
+
+ result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.",
+ result);
+ }
+ }
+
+ mDeviceContext->End(mSyncQuery);
+
+ unsigned int attempt = 0;
+ do
+ {
+ unsigned int flushFrequency = 100;
+ UINT flags = (attempt % flushFrequency == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH;
+ attempt++;
+
+ result = mDeviceContext->GetData(mSyncQuery, NULL, 0, flags);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.",
+ result);
+ }
+
+ // Keep polling, but allow other threads to do something useful first
+ ScheduleYield();
+
+ if (testDeviceLost())
+ {
+ mDisplay->notifyDeviceLost();
+ return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync.");
+ }
+ } while (result == S_FALSE);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+bool Renderer11::isValidNativeWindow(EGLNativeWindowType window) const
+{
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ return NativeWindow11WinRT::IsValidNativeWindow(window);
+#else
+ return NativeWindow11Win32::IsValidNativeWindow(window);
+#endif
+}
+
+NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window,
+ const egl::Config *config,
+ const egl::AttributeMap &attribs) const
+{
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ UNUSED_VARIABLE(attribs);
+ return new NativeWindow11WinRT(window, config->alphaSize > 0);
+#else
+ return new NativeWindow11Win32(
+ window, config->alphaSize > 0,
+ attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
+#endif
+}
+
+egl::Error Renderer11::getD3DTextureInfo(IUnknown *d3dTexture,
+ EGLint *width,
+ EGLint *height,
+ GLenum *fboFormat) const
+{
+ ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture);
+ if (texture == nullptr)
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "client buffer is not a ID3D11Texture2D");
+ }
+
+ ID3D11Device *textureDevice = nullptr;
+ texture->GetDevice(&textureDevice);
+ if (textureDevice != mDevice)
+ {
+ SafeRelease(texture);
+ return egl::Error(EGL_BAD_PARAMETER, "Texture's device does not match.");
+ }
+ SafeRelease(textureDevice);
+
+ D3D11_TEXTURE2D_DESC desc = {0};
+ texture->GetDesc(&desc);
+ SafeRelease(texture);
+
+ if (width)
+ {
+ *width = static_cast<EGLint>(desc.Width);
+ }
+ if (height)
+ {
+ *height = static_cast<EGLint>(desc.Height);
+ }
+
+ // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+ switch (desc.Format)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ break;
+
+ default:
+ return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
+ desc.Format);
+ }
+
+ if (fboFormat)
+ {
+ const angle::Format &angleFormat = d3d11_angle::GetFormat(desc.Format);
+ *fboFormat = angleFormat.fboImplementationInternalFormat;
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error Renderer11::validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const
+{
+ if (shareHandle == nullptr)
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "NULL share handle.");
+ }
+
+ ID3D11Resource *tempResource11 = nullptr;
+ HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
+ (void **)&tempResource11);
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "Failed to open share handle, result: 0x%X.", result);
+ }
+
+ ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11);
+ SafeRelease(tempResource11);
+
+ if (texture2D == nullptr)
+ {
+ return egl::Error(EGL_BAD_PARAMETER,
+ "Failed to query ID3D11Texture2D object from share handle.");
+ }
+
+ D3D11_TEXTURE2D_DESC desc = {0};
+ 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::Error(EGL_BAD_PARAMETER, "Invalid texture parameters in share handle texture.");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow,
+ HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation)
+{
+ return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, d3dTexture,
+ backBufferFormat, depthBufferFormat, orientation);
+}
+
+void *Renderer11::getD3DDevice()
+{
+ return reinterpret_cast<void *>(mDevice);
+}
+
+gl::Error Renderer11::generateSwizzle(gl::Texture *texture)
+{
+ if (texture)
+ {
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+ ASSERT(textureD3D);
+
+ TextureStorage *texStorage = nullptr;
+ ANGLE_TRY(textureD3D->getNativeTexture(&texStorage));
+
+ if (texStorage)
+ {
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
+ const gl::TextureState &textureState = texture->getTextureState();
+ ANGLE_TRY(storage11->generateSwizzles(textureState.getSwizzleState()));
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::generateSwizzles(const gl::ContextState &data, gl::SamplerType type)
+{
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.getState().getProgram());
+
+ unsigned int samplerRange = programD3D->getUsedSamplerRange(type);
+
+ for (unsigned int i = 0; i < samplerRange; i++)
+ {
+ GLenum textureType = programD3D->getSamplerTextureType(type, i);
+ GLint textureUnit = programD3D->getSamplerMapping(type, i, data.getCaps());
+ if (textureUnit != -1)
+ {
+ gl::Texture *texture = data.getState().getSamplerTexture(textureUnit, textureType);
+ ASSERT(texture);
+ if (texture->getTextureState().swizzleRequired())
+ {
+ ANGLE_TRY(generateSwizzle(texture));
+ }
+ }
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::generateSwizzles(const gl::ContextState &data)
+{
+ ANGLE_TRY(generateSwizzles(data, gl::SAMPLER_VERTEX));
+ ANGLE_TRY(generateSwizzles(data, gl::SAMPLER_PIXEL));
+ return gl::NoError();
+}
+gl::Error Renderer11::setSamplerState(gl::SamplerType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &samplerState)
+{
+ // 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(&storage));
+
+ // Storage should exist, texture should be complete
+ ASSERT(storage);
+
+ // 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.
+ SamplerMetadataD3D11 *metadata = nullptr;
+
+ if (type == gl::SAMPLER_PIXEL)
+ {
+ ASSERT(static_cast<unsigned int>(index) < getNativeCaps().maxTextureImageUnits);
+
+ if (mForceSetPixelSamplerStates[index] ||
+ memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+ {
+ ID3D11SamplerState *dxSamplerState = NULL;
+ ANGLE_TRY(mStateCache.getSamplerState(samplerState, &dxSamplerState));
+
+ ASSERT(dxSamplerState != NULL);
+ mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
+
+ mCurPixelSamplerStates[index] = samplerState;
+ }
+
+ mForceSetPixelSamplerStates[index] = false;
+
+ metadata = &mSamplerMetadataPS;
+ }
+ else if (type == gl::SAMPLER_VERTEX)
+ {
+ ASSERT(static_cast<unsigned int>(index) < getNativeCaps().maxVertexTextureImageUnits);
+
+ if (mForceSetVertexSamplerStates[index] ||
+ memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+ {
+ ID3D11SamplerState *dxSamplerState = NULL;
+ ANGLE_TRY(mStateCache.getSamplerState(samplerState, &dxSamplerState));
+
+ ASSERT(dxSamplerState != NULL);
+ mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
+
+ mCurVertexSamplerStates[index] = samplerState;
+ }
+
+ mForceSetVertexSamplerStates[index] = false;
+
+ metadata = &mSamplerMetadataVS;
+ }
+ else
+ UNREACHABLE();
+
+ ASSERT(metadata != nullptr);
+ metadata->update(index, *texture);
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
+{
+ ID3D11ShaderResourceView *textureSRV = NULL;
+
+ if (texture)
+ {
+ TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
+
+ TextureStorage *texStorage = nullptr;
+ ANGLE_TRY(textureImpl->getNativeTexture(&texStorage));
+
+ // Texture should be complete and have a storage
+ ASSERT(texStorage);
+
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
+
+ ANGLE_TRY(storage11->getSRV(texture->getTextureState(), &textureSRV));
+
+ // If we get NULL back from getSRV here, something went wrong in the texture class and we're
+ // unexpectedly missing the shader resource view
+ ASSERT(textureSRV != NULL);
+
+ textureImpl->resetDirty();
+ }
+
+ ASSERT((type == gl::SAMPLER_PIXEL &&
+ static_cast<unsigned int>(index) < getNativeCaps().maxTextureImageUnits) ||
+ (type == gl::SAMPLER_VERTEX &&
+ static_cast<unsigned int>(index) < getNativeCaps().maxVertexTextureImageUnits));
+
+ mStateManager.setShaderResource(type, index, textureSRV);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::setUniformBuffers(const gl::ContextState &data,
+ const std::vector<GLint> &vertexUniformBuffers,
+ const std::vector<GLint> &fragmentUniformBuffers)
+{
+ for (size_t uniformBufferIndex = 0; uniformBufferIndex < vertexUniformBuffers.size();
+ uniformBufferIndex++)
+ {
+ GLint binding = vertexUniformBuffers[uniformBufferIndex];
+
+ if (binding == -1)
+ {
+ continue;
+ }
+
+ const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
+ data.getState().getIndexedUniformBuffer(binding);
+ GLintptr uniformBufferOffset = uniformBuffer.getOffset();
+ GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
+
+ if (uniformBuffer.get() == nullptr)
+ {
+ continue;
+ }
+
+ Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
+ ID3D11Buffer *constantBuffer = nullptr;
+ UINT firstConstant = 0;
+ UINT numConstants = 0;
+
+ ANGLE_TRY(bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize,
+ &constantBuffer, &firstConstant,
+ &numConstants));
+
+ if (!constantBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Error retrieving constant buffer");
+ }
+
+ if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial() ||
+ mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset ||
+ mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize)
+ {
+ if (firstConstant != 0 && uniformBufferSize != 0)
+ {
+ ASSERT(numConstants != 0);
+ mDeviceContext1->VSSetConstantBuffers1(
+ getReservedVertexUniformBuffers() +
+ static_cast<unsigned int>(uniformBufferIndex),
+ 1, &constantBuffer, &firstConstant, &numConstants);
+ }
+ else
+ {
+ mDeviceContext->VSSetConstantBuffers(
+ getReservedVertexUniformBuffers() +
+ static_cast<unsigned int>(uniformBufferIndex),
+ 1, &constantBuffer);
+ }
+
+ mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial();
+ mCurrentConstantBufferVSOffset[uniformBufferIndex] = uniformBufferOffset;
+ mCurrentConstantBufferVSSize[uniformBufferIndex] = uniformBufferSize;
+ }
+ }
+
+ for (size_t uniformBufferIndex = 0; uniformBufferIndex < fragmentUniformBuffers.size();
+ uniformBufferIndex++)
+ {
+ GLint binding = fragmentUniformBuffers[uniformBufferIndex];
+
+ if (binding == -1)
+ {
+ continue;
+ }
+
+ const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
+ data.getState().getIndexedUniformBuffer(binding);
+ GLintptr uniformBufferOffset = uniformBuffer.getOffset();
+ GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
+
+ if (uniformBuffer.get() == nullptr)
+ {
+ continue;
+ }
+
+ Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
+ ID3D11Buffer *constantBuffer = nullptr;
+ UINT firstConstant = 0;
+ UINT numConstants = 0;
+
+ ANGLE_TRY(bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize,
+ &constantBuffer, &firstConstant,
+ &numConstants));
+
+ if (!constantBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Error retrieving constant buffer");
+ }
+
+ if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial() ||
+ mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset ||
+ mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize)
+ {
+ if (firstConstant != 0 && uniformBufferSize != 0)
+ {
+ mDeviceContext1->PSSetConstantBuffers1(
+ getReservedFragmentUniformBuffers() +
+ static_cast<unsigned int>(uniformBufferIndex),
+ 1, &constantBuffer, &firstConstant, &numConstants);
+ }
+ else
+ {
+ mDeviceContext->PSSetConstantBuffers(
+ getReservedFragmentUniformBuffers() +
+ static_cast<unsigned int>(uniformBufferIndex),
+ 1, &constantBuffer);
+ }
+
+ mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial();
+ mCurrentConstantBufferPSOffset[uniformBufferIndex] = uniformBufferOffset;
+ mCurrentConstantBufferPSSize[uniformBufferIndex] = uniformBufferSize;
+ }
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::updateState(const gl::ContextState &data, GLenum drawMode)
+{
+ const auto &glState = data.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() && framebuffer->complete(data));
+ ANGLE_TRY(applyRenderTarget(framebuffer));
+
+ // Set the present path state
+ auto firstColorAttachment = framebuffer->getFirstColorbuffer();
+ const bool presentPathFastActive = UsePresentPathFast(this, firstColorAttachment);
+ mStateManager.updatePresentPath(presentPathFastActive, firstColorAttachment);
+
+ // Setting viewport state
+ mStateManager.setViewport(&data.getCaps(), glState.getViewport(), glState.getNearPlane(),
+ glState.getFarPlane());
+
+ // Setting scissor state
+ mStateManager.setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
+
+ // Applying rasterizer state to D3D11 device
+ // 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;
+ if (firstColorAttachment)
+ {
+ ASSERT(firstColorAttachment->isAttached());
+ RenderTarget11 *renderTarget = nullptr;
+ ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
+ samples = renderTarget->getSamples();
+ }
+ gl::RasterizerState rasterizer = glState.getRasterizerState();
+ rasterizer.pointDrawMode = (drawMode == GL_POINTS);
+ rasterizer.multiSample = (samples != 0);
+
+ ANGLE_TRY(mStateManager.setRasterizerState(rasterizer));
+
+ // Setting blend state
+ unsigned int mask = GetBlendSampleMask(data, samples);
+ ANGLE_TRY(mStateManager.setBlendState(framebuffer, glState.getBlendState(),
+ glState.getBlendColor(), mask));
+
+ // Setting depth stencil state
+ ANGLE_TRY(mStateManager.setDepthStencilState(glState));
+
+ return gl::NoError();
+}
+
+bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
+{
+ D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+
+ GLsizei minCount = 0;
+
+ switch (mode)
+ {
+ case GL_POINTS:
+ primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
+ minCount = 1;
+ break;
+ case GL_LINES:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
+ minCount = 2;
+ break;
+ case GL_LINE_LOOP:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
+ minCount = 2;
+ break;
+ case GL_LINE_STRIP:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
+ minCount = 2;
+ break;
+ case GL_TRIANGLES:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ minCount = 3;
+ break;
+ case GL_TRIANGLE_STRIP:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
+ minCount = 3;
+ break;
+ // emulate fans via rewriting index buffer
+ case GL_TRIANGLE_FAN:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ minCount = 3;
+ break;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+
+ // If instanced pointsprite emulation is being used and If gl_PointSize is used in the shader,
+ // GL_POINTS mode is expected to render pointsprites.
+ // Instanced PointSprite emulation requires that the topology to be
+ // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
+ if (mode == GL_POINTS && usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
+ {
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ }
+
+ if (primitiveTopology != mCurrentPrimitiveTopology)
+ {
+ mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
+ mCurrentPrimitiveTopology = primitiveTopology;
+ }
+
+ return count >= minCount;
+}
+
+gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
+{
+ return mStateManager.syncFramebuffer(framebuffer);
+}
+
+gl::Error Renderer11::applyVertexBuffer(const gl::State &state,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances,
+ TranslatedIndexData *indexInfo)
+{
+ const auto &vertexArray = state.getVertexArray();
+ auto *vertexArray11 = GetImplAs<VertexArray11>(vertexArray);
+
+ ANGLE_TRY(vertexArray11->updateDirtyAndDynamicAttribs(mVertexDataManager, state, first, count,
+ instances));
+
+ ANGLE_TRY(mStateManager.updateCurrentValueAttribs(state, mVertexDataManager));
+
+ // If index information is passed, mark it with the current changed status.
+ if (indexInfo)
+ {
+ indexInfo->srcIndexData.srcIndicesChanged = mAppliedIBChanged;
+ }
+
+ GLsizei numIndicesPerInstance = 0;
+ if (instances > 0)
+ {
+ numIndicesPerInstance = count;
+ }
+ const auto &vertexArrayAttribs = vertexArray11->getTranslatedAttribs();
+ const auto &currentValueAttribs = mStateManager.getCurrentValueAttribs();
+ ANGLE_TRY(mInputLayoutCache.applyVertexBuffers(state, vertexArrayAttribs, currentValueAttribs,
+ mode, first, indexInfo, numIndicesPerInstance));
+
+ // InputLayoutCache::applyVertexBuffers calls through to the Bufer11 to get the native vertex
+ // buffer (ID3D11Buffer *). Because we allocate these buffers lazily, this will trigger
+ // allocation. This in turn will signal that the buffer is dirty. Since we just resolved the
+ // dirty-ness in VertexArray11::updateDirtyAndDynamicAttribs, this can make us do a needless
+ // update on the second draw call.
+ // Hence we clear the flags here, after we've applied vertex data, since we know everything
+ // is clean. This is a bit of a hack.
+ vertexArray11->clearDirtyAndPromoteDynamicAttribs(state, count);
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::applyIndexBuffer(const gl::ContextState &data,
+ const GLvoid *indices,
+ GLsizei count,
+ GLenum mode,
+ GLenum type,
+ TranslatedIndexData *indexInfo)
+{
+ const auto &glState = data.getState();
+ gl::VertexArray *vao = glState.getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+ ANGLE_TRY(mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices,
+ indexInfo, glState.isPrimitiveRestartEnabled()));
+
+ ID3D11Buffer *buffer = nullptr;
+ DXGI_FORMAT bufferFormat =
+ (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;
+
+ if (indexInfo->storage)
+ {
+ Buffer11 *storage = GetAs<Buffer11>(indexInfo->storage);
+ ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_INDEX), buffer);
+ }
+ else
+ {
+ IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo->indexBuffer);
+ buffer = indexBuffer->getBuffer();
+ }
+
+ mAppliedIBChanged = false;
+ if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat ||
+ indexInfo->startOffset != mAppliedIBOffset)
+ {
+ mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset);
+
+ mAppliedIB = buffer;
+ mAppliedIBFormat = bufferFormat;
+ mAppliedIBOffset = indexInfo->startOffset;
+ mAppliedIBChanged = true;
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::applyTransformFeedbackBuffers(const gl::ContextState &data)
+{
+ const auto &state = data.getState();
+
+ // If transform feedback is not active, unbind all buffers
+ if (!state.isTransformFeedbackActiveUnpaused())
+ {
+ if (mAppliedTFObject != 0)
+ {
+ mDeviceContext->SOSetTargets(0, nullptr, nullptr);
+ mAppliedTFObject = 0;
+ }
+ return gl::NoError();
+ }
+
+ gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
+ TransformFeedback11 *transformFeedback11 = GetImplAs<TransformFeedback11>(transformFeedback);
+ uintptr_t transformFeedbackId = reinterpret_cast<uintptr_t>(transformFeedback11);
+ if (mAppliedTFObject == transformFeedbackId && !transformFeedback11->isDirty())
+ {
+ return gl::NoError();
+ }
+
+ const std::vector<ID3D11Buffer *> *soBuffers = nullptr;
+ ANGLE_TRY_RESULT(transformFeedback11->getSOBuffers(), soBuffers);
+ const std::vector<UINT> &soOffsets = transformFeedback11->getSOBufferOffsets();
+
+ mDeviceContext->SOSetTargets(transformFeedback11->getNumSOBuffers(), soBuffers->data(),
+ soOffsets.data());
+
+ mAppliedTFObject = transformFeedbackId;
+ transformFeedback11->onApply();
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::drawArraysImpl(const gl::ContextState &data,
+ GLenum mode,
+ GLint startVertex,
+ GLsizei count,
+ GLsizei instances)
+{
+ const auto &glState = data.getState();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+ if (programD3D->usesGeometryShader(mode) && glState.isTransformFeedbackActiveUnpaused())
+ {
+ // 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.
+ mDeviceContext->PSSetShader(nullptr, nullptr, 0);
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ }
+ else
+ {
+ mDeviceContext->Draw(count, 0);
+ }
+
+ rx::ShaderExecutableD3D *pixelExe = nullptr;
+ ANGLE_TRY(
+ programD3D->getPixelExecutableForFramebuffer(glState.getDrawFramebuffer(), &pixelExe));
+
+ // Skip the draw call if rasterizer discard is enabled (or no fragment shader).
+ if (!pixelExe || glState.getRasterizerState().rasterizerDiscard)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ ID3D11PixelShader *pixelShader = GetAs<ShaderExecutable11>(pixelExe)->getPixelShader();
+ ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader);
+ mDeviceContext->PSSetShader(pixelShader, NULL, 0);
+
+ // Retrieve the geometry shader.
+ rx::ShaderExecutableD3D *geometryExe = nullptr;
+ ANGLE_TRY(
+ programD3D->getGeometryExecutableForPrimitiveType(data, mode, &geometryExe, nullptr));
+
+ ID3D11GeometryShader *geometryShader =
+ (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL);
+ mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
+ ASSERT(geometryShader);
+ mDeviceContext->GSSetShader(geometryShader, NULL, 0);
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ }
+ else
+ {
+ mDeviceContext->Draw(count, 0);
+ }
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ if (mode == GL_LINE_LOOP)
+ {
+ return drawLineLoop(data, count, GL_NONE, nullptr, nullptr, instances);
+ }
+
+ if (mode == GL_TRIANGLE_FAN)
+ {
+ return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances);
+ }
+
+ bool useInstancedPointSpriteEmulation =
+ programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation;
+
+ if (instances > 0)
+ {
+ if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
+ {
+ // 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 < instances; i++)
+ {
+ ANGLE_TRY(
+ mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(startVertex, i));
+ mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
+ }
+ }
+ else
+ {
+ mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ }
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ // 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 (mode == GL_POINTS && useInstancedPointSpriteEmulation)
+ {
+ mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
+ }
+ else
+ {
+ mDeviceContext->Draw(count, 0);
+ }
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::drawElementsImpl(const gl::ContextState &data,
+ const TranslatedIndexData &indexInfo,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances)
+{
+ int minIndex = static_cast<int>(indexInfo.indexRange.start);
+
+ if (mode == GL_LINE_LOOP)
+ {
+ return drawLineLoop(data, count, type, indices, &indexInfo, instances);
+ }
+
+ if (mode == GL_TRIANGLE_FAN)
+ {
+ return drawTriangleFan(data, count, type, indices, minIndex, instances);
+ }
+
+ const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.getState().getProgram());
+ if (instances > 0)
+ {
+ if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation())
+ {
+ // 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.
+ GLsizei elementsToRender = static_cast<GLsizei>(indexInfo.indexRange.vertexCount());
+
+ // Each instance being rendered requires the inputlayout cache to reapply buffers and
+ // offsets.
+ for (GLsizei i = 0; i < instances; i++)
+ {
+ ANGLE_TRY(
+ mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(minIndex, i));
+ mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0);
+ }
+ }
+ else
+ {
+ mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0);
+ }
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ // 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 (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation())
+ {
+ // 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.
+ mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
+ }
+ else
+ {
+ mDeviceContext->DrawIndexed(count, 0, -minIndex);
+ }
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::drawLineLoop(const gl::ContextState &data,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indexPointer,
+ const TranslatedIndexData *indexInfo,
+ int instances)
+{
+ const auto &glState = data.getState();
+ gl::VertexArray *vao = glState.getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
+ const GLvoid *indices = indexPointer;
+
+ // Get the raw indices for an indexed draw
+ if (type != GL_NONE && elementArrayBuffer)
+ {
+ BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+
+ const uint8_t *bufferData = NULL;
+ ANGLE_TRY(storage->getData(&bufferData));
+
+ indices = bufferData + offset;
+ }
+
+ if (!mLineLoopIB)
+ {
+ mLineLoopIB = new StreamingIndexBufferInterface(this);
+ gl::Error error =
+ mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+ if (error.isError())
+ {
+ SafeDelete(mLineLoopIB);
+ return error;
+ }
+ }
+
+ // Checked by Renderer11::applyPrimitiveType
+ ASSERT(count >= 0);
+
+ if (static_cast<unsigned int>(count) + 1 >
+ (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too "
+ "many indices required.");
+ }
+
+ 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(spaceNeeded, GL_UNSIGNED_INT));
+
+ void *mappedMemory = NULL;
+ unsigned int offset;
+ ANGLE_TRY(mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset));
+
+ // Copy over the converted index data.
+ memcpy(mappedMemory, &mScratchIndexDataBuffer[0],
+ sizeof(GLuint) * mScratchIndexDataBuffer.size());
+
+ ANGLE_TRY(mLineLoopIB->unmapBuffer());
+
+ IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer());
+ ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer();
+ DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
+
+ if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat ||
+ mAppliedIBOffset != offset)
+ {
+ mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset);
+ mAppliedIB = d3dIndexBuffer;
+ mAppliedIBFormat = indexFormat;
+ mAppliedIBOffset = offset;
+ }
+
+ INT baseVertexLocation = (indexInfo ? -static_cast<int>(indexInfo->indexRange.start) : 0);
+ UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertexLocation, 0);
+ }
+ else
+ {
+ mDeviceContext->DrawIndexed(indexCount, 0, baseVertexLocation);
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::drawTriangleFan(const gl::ContextState &data,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ int minIndex,
+ int instances)
+{
+ gl::VertexArray *vao = data.getState().getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
+ const GLvoid *indexPointer = indices;
+
+ // Get the raw indices for an indexed draw
+ if (type != GL_NONE && elementArrayBuffer)
+ {
+ BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+
+ const uint8_t *bufferData = NULL;
+ ANGLE_TRY(storage->getData(&bufferData));
+
+ indexPointer = bufferData + offset;
+ }
+
+ if (!mTriangleFanIB)
+ {
+ mTriangleFanIB = new StreamingIndexBufferInterface(this);
+ gl::Error error =
+ mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+ if (error.isError())
+ {
+ SafeDelete(mTriangleFanIB);
+ return error;
+ }
+ }
+
+ // Checked by Renderer11::applyPrimitiveType
+ ASSERT(count >= 3);
+
+ const GLuint numTris = count - 2;
+
+ if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many "
+ "indices required.");
+ }
+
+ GetTriFanIndices(indexPointer, type, count, data.getState().isPrimitiveRestartEnabled(),
+ &mScratchIndexDataBuffer);
+
+ const unsigned int spaceNeeded =
+ static_cast<unsigned int>(mScratchIndexDataBuffer.size() * sizeof(unsigned int));
+ ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT));
+
+ void *mappedMemory = nullptr;
+ unsigned int offset;
+ ANGLE_TRY(mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset));
+
+ memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded);
+
+ ANGLE_TRY(mTriangleFanIB->unmapBuffer());
+
+ IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer());
+ ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer();
+ DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
+
+ if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat ||
+ mAppliedIBOffset != offset)
+ {
+ mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset);
+ mAppliedIB = d3dIndexBuffer;
+ mAppliedIBFormat = indexFormat;
+ mAppliedIBOffset = offset;
+ }
+
+ UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, -minIndex, 0);
+ }
+ else
+ {
+ mDeviceContext->DrawIndexed(indexCount, 0, -minIndex);
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::applyShaders(const gl::ContextState &data, GLenum drawMode)
+{
+ const auto &glState = data.getState();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+ programD3D->updateCachedInputLayout(glState);
+
+ const auto &inputLayout = programD3D->getCachedInputLayout();
+
+ ShaderExecutableD3D *vertexExe = nullptr;
+ ANGLE_TRY(programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr));
+
+ const gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
+ ShaderExecutableD3D *pixelExe = nullptr;
+ ANGLE_TRY(programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe));
+
+ ShaderExecutableD3D *geometryExe = nullptr;
+ ANGLE_TRY(
+ programD3D->getGeometryExecutableForPrimitiveType(data, drawMode, &geometryExe, nullptr));
+
+ ID3D11VertexShader *vertexShader =
+ (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr);
+
+ ID3D11PixelShader *pixelShader = nullptr;
+ // Skip pixel shader if we're doing rasterizer discard.
+ bool rasterizerDiscard = glState.getRasterizerState().rasterizerDiscard;
+ if (!rasterizerDiscard)
+ {
+ pixelShader = (pixelExe ? GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : nullptr);
+ }
+
+ ID3D11GeometryShader *geometryShader = nullptr;
+ bool transformFeedbackActive = glState.isTransformFeedbackActiveUnpaused();
+ if (transformFeedbackActive)
+ {
+ geometryShader =
+ (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr);
+ }
+ else
+ {
+ geometryShader =
+ (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr);
+ }
+
+ bool dirtyUniforms = false;
+
+ if (reinterpret_cast<uintptr_t>(vertexShader) != mAppliedVertexShader)
+ {
+ mDeviceContext->VSSetShader(vertexShader, nullptr, 0);
+ mAppliedVertexShader = reinterpret_cast<uintptr_t>(vertexShader);
+ dirtyUniforms = true;
+ }
+
+ if (reinterpret_cast<uintptr_t>(geometryShader) != mAppliedGeometryShader)
+ {
+ mDeviceContext->GSSetShader(geometryShader, nullptr, 0);
+ mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
+ dirtyUniforms = true;
+ }
+
+ if (reinterpret_cast<uintptr_t>(pixelShader) != mAppliedPixelShader)
+ {
+ mDeviceContext->PSSetShader(pixelShader, nullptr, 0);
+ mAppliedPixelShader = reinterpret_cast<uintptr_t>(pixelShader);
+ dirtyUniforms = true;
+ }
+
+ if (dirtyUniforms)
+ {
+ programD3D->dirtyAllUniforms();
+ }
+
+ return programD3D->applyUniforms(drawMode);
+}
+
+gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
+ GLenum drawMode,
+ const std::vector<D3DUniform *> &uniformArray)
+{
+ unsigned int totalRegisterCountVS = 0;
+ unsigned int totalRegisterCountPS = 0;
+
+ bool vertexUniformsDirty = false;
+ bool pixelUniformsDirty = false;
+
+ for (const D3DUniform *uniform : uniformArray)
+ {
+ if (uniform->isReferencedByVertexShader() && !uniform->isSampler())
+ {
+ totalRegisterCountVS += uniform->registerCount;
+ vertexUniformsDirty = (vertexUniformsDirty || uniform->dirty);
+ }
+
+ if (uniform->isReferencedByFragmentShader() && !uniform->isSampler())
+ {
+ totalRegisterCountPS += uniform->registerCount;
+ pixelUniformsDirty = (pixelUniformsDirty || uniform->dirty);
+ }
+ }
+
+ const UniformStorage11 *vertexUniformStorage =
+ GetAs<UniformStorage11>(&programD3D.getVertexUniformStorage());
+ const UniformStorage11 *fragmentUniformStorage =
+ GetAs<UniformStorage11>(&programD3D.getFragmentUniformStorage());
+ ASSERT(vertexUniformStorage);
+ ASSERT(fragmentUniformStorage);
+
+ ID3D11Buffer *vertexConstantBuffer = vertexUniformStorage->getConstantBuffer();
+ ID3D11Buffer *pixelConstantBuffer = fragmentUniformStorage->getConstantBuffer();
+
+ float(*mapVS)[4] = NULL;
+ float(*mapPS)[4] = NULL;
+
+ if (totalRegisterCountVS > 0 && vertexUniformsDirty)
+ {
+ D3D11_MAPPED_SUBRESOURCE map = {0};
+ HRESULT result =
+ mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+ ASSERT(SUCCEEDED(result));
+ mapVS = (float(*)[4])map.pData;
+ }
+
+ if (totalRegisterCountPS > 0 && pixelUniformsDirty)
+ {
+ D3D11_MAPPED_SUBRESOURCE map = {0};
+ HRESULT result =
+ mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+ ASSERT(SUCCEEDED(result));
+ mapPS = (float(*)[4])map.pData;
+ }
+
+ for (const D3DUniform *uniform : uniformArray)
+ {
+ if (uniform->isSampler())
+ continue;
+
+ unsigned int componentCount = (4 - uniform->registerElement);
+
+ // we assume that uniforms from structs are arranged in struct order in our uniforms list.
+ // otherwise we would overwrite previously written regions of memory.
+
+ if (uniform->isReferencedByVertexShader() && mapVS)
+ {
+ memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data,
+ uniform->registerCount * sizeof(float) * componentCount);
+ }
+
+ if (uniform->isReferencedByFragmentShader() && mapPS)
+ {
+ memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data,
+ uniform->registerCount * sizeof(float) * componentCount);
+ }
+ }
+
+ if (mapVS)
+ {
+ mDeviceContext->Unmap(vertexConstantBuffer, 0);
+ }
+
+ if (mapPS)
+ {
+ mDeviceContext->Unmap(pixelConstantBuffer, 0);
+ }
+
+ if (mCurrentVertexConstantBuffer != vertexConstantBuffer)
+ {
+ mDeviceContext->VSSetConstantBuffers(
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, &vertexConstantBuffer);
+ mCurrentVertexConstantBuffer = vertexConstantBuffer;
+ }
+
+ if (mCurrentPixelConstantBuffer != pixelConstantBuffer)
+ {
+ mDeviceContext->PSSetConstantBuffers(
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, &pixelConstantBuffer);
+ mCurrentPixelConstantBuffer = pixelConstantBuffer;
+ }
+
+ if (!mDriverConstantBufferVS)
+ {
+ D3D11_BUFFER_DESC constantBufferDescription = {0};
+ d3d11::InitConstantBufferDesc(
+ &constantBufferDescription,
+ sizeof(dx_VertexConstants11) + mSamplerMetadataVS.sizeBytes());
+ HRESULT result =
+ mDevice->CreateBuffer(&constantBufferDescription, nullptr, &mDriverConstantBufferVS);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create vertex shader constant buffer, result: 0x%X.",
+ result);
+ }
+ mDeviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
+ &mDriverConstantBufferVS);
+ }
+ if (!mDriverConstantBufferPS)
+ {
+ D3D11_BUFFER_DESC constantBufferDescription = {0};
+ d3d11::InitConstantBufferDesc(&constantBufferDescription,
+ sizeof(dx_PixelConstants11) + mSamplerMetadataPS.sizeBytes());
+ HRESULT result =
+ mDevice->CreateBuffer(&constantBufferDescription, nullptr, &mDriverConstantBufferPS);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create pixel shader constant buffer, result: 0x%X.",
+ result);
+ }
+ mDeviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
+ &mDriverConstantBufferPS);
+ }
+
+ // 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.
+ const dx_VertexConstants11 &vertexConstants = mStateManager.getVertexConstants();
+ size_t samplerMetadataReferencedBytesVS = sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) *
+ programD3D.getUsedSamplerRange(gl::SAMPLER_VERTEX);
+ applyDriverConstantsIfNeeded(&mAppliedVertexConstants, vertexConstants, &mSamplerMetadataVS,
+ samplerMetadataReferencedBytesVS, mDriverConstantBufferVS);
+
+ const dx_PixelConstants11 &pixelConstants = mStateManager.getPixelConstants();
+ size_t samplerMetadataReferencedBytesPS = sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) *
+ programD3D.getUsedSamplerRange(gl::SAMPLER_PIXEL);
+ applyDriverConstantsIfNeeded(&mAppliedPixelConstants, pixelConstants, &mSamplerMetadataPS,
+ samplerMetadataReferencedBytesPS, mDriverConstantBufferPS);
+
+ // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary
+ if (programD3D.usesGeometryShader(drawMode))
+ {
+ // needed for the point sprite geometry shader
+ if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
+ {
+ ASSERT(mDriverConstantBufferPS != nullptr);
+ mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
+ mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+// SamplerMetadataD3D11 implementation
+
+Renderer11::SamplerMetadataD3D11::SamplerMetadataD3D11() : mDirty(true)
+{
+}
+
+Renderer11::SamplerMetadataD3D11::~SamplerMetadataD3D11()
+{
+}
+
+void Renderer11::SamplerMetadataD3D11::initData(unsigned int samplerCount)
+{
+ mSamplerMetadata.resize(samplerCount);
+}
+
+void Renderer11::SamplerMetadataD3D11::update(unsigned int samplerIndex, const gl::Texture &texture)
+{
+ unsigned int baseLevel = texture.getTextureState().getEffectiveBaseLevel();
+ GLenum sizedFormat = texture.getFormat(texture.getTarget(), baseLevel).asSized();
+ if (mSamplerMetadata[samplerIndex].baseLevel != static_cast<int>(baseLevel))
+ {
+ mSamplerMetadata[samplerIndex].baseLevel = static_cast<int>(baseLevel);
+ mDirty = 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 (mSamplerMetadata[samplerIndex].internalFormatBits != internalFormatBits)
+ {
+ mSamplerMetadata[samplerIndex].internalFormatBits = internalFormatBits;
+ mDirty = true;
+ }
+ // Pack the wrap values into one integer so we can fit all the metadata in one 4-integer
+ // vector.
+ GLenum wrapS = texture.getWrapS();
+ GLenum wrapT = texture.getWrapT();
+ GLenum wrapR = texture.getWrapR();
+ int wrapModes = GetWrapBits(wrapS) | (GetWrapBits(wrapT) << 2) | (GetWrapBits(wrapR) << 4);
+ if (mSamplerMetadata[samplerIndex].wrapModes != wrapModes)
+ {
+ mSamplerMetadata[samplerIndex].wrapModes = wrapModes;
+ mDirty = true;
+ }
+ }
+}
+
+const Renderer11::SamplerMetadataD3D11::dx_SamplerMetadata *
+Renderer11::SamplerMetadataD3D11::getData() const
+{
+ return mSamplerMetadata.data();
+}
+
+size_t Renderer11::SamplerMetadataD3D11::sizeBytes() const
+{
+ return sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) * mSamplerMetadata.size();
+}
+
+template <class TShaderConstants>
+void Renderer11::applyDriverConstantsIfNeeded(TShaderConstants *appliedConstants,
+ const TShaderConstants &constants,
+ SamplerMetadataD3D11 *samplerMetadata,
+ size_t samplerMetadataReferencedBytes,
+ ID3D11Buffer *driverConstantBuffer)
+{
+ ASSERT(driverConstantBuffer != nullptr);
+ if (memcmp(appliedConstants, &constants, sizeof(TShaderConstants)) != 0 ||
+ samplerMetadata->isDirty())
+ {
+ memcpy(appliedConstants, &constants, sizeof(TShaderConstants));
+
+ D3D11_MAPPED_SUBRESOURCE mapping = {0};
+ HRESULT result =
+ mDeviceContext->Map(driverConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapping);
+ ASSERT(SUCCEEDED(result));
+ memcpy(mapping.pData, appliedConstants, sizeof(TShaderConstants));
+ // Previous buffer contents were discarded, so we need to refresh also the area of the
+ // buffer that isn't used by this program.
+ memcpy(&reinterpret_cast<uint8_t *>(mapping.pData)[sizeof(TShaderConstants)],
+ samplerMetadata->getData(), samplerMetadata->sizeBytes());
+ mDeviceContext->Unmap(driverConstantBuffer, 0);
+
+ samplerMetadata->markClean();
+ }
+}
+
+template void Renderer11::applyDriverConstantsIfNeeded<dx_VertexConstants11>(
+ dx_VertexConstants11 *appliedConstants,
+ const dx_VertexConstants11 &constants,
+ SamplerMetadataD3D11 *samplerMetadata,
+ size_t samplerMetadataReferencedBytes,
+ ID3D11Buffer *driverConstantBuffer);
+template void Renderer11::applyDriverConstantsIfNeeded<dx_PixelConstants11>(
+ dx_PixelConstants11 *appliedConstants,
+ const dx_PixelConstants11 &constants,
+ SamplerMetadataD3D11 *samplerMetadata,
+ size_t samplerMetadataReferencedBytes,
+ ID3D11Buffer *driverConstantBuffer);
+
+void Renderer11::markAllStateDirty()
+{
+ TRACE_EVENT0("gpu.angle", "Renderer11::markAllStateDirty");
+
+ for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId)
+ {
+ mForceSetVertexSamplerStates[vsamplerId] = true;
+ }
+
+ for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId)
+ {
+ mForceSetPixelSamplerStates[fsamplerId] = true;
+ }
+
+ mStateManager.invalidateEverything();
+
+ mAppliedIB = NULL;
+ mAppliedIBFormat = DXGI_FORMAT_UNKNOWN;
+ mAppliedIBOffset = 0;
+
+ mAppliedVertexShader = angle::DirtyPointer;
+ mAppliedGeometryShader = angle::DirtyPointer;
+ mAppliedPixelShader = angle::DirtyPointer;
+
+ mAppliedTFObject = angle::DirtyPointer;
+
+ memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants11));
+ memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants11));
+
+ mInputLayoutCache.markDirty();
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++)
+ {
+ mCurrentConstantBufferVS[i] = static_cast<unsigned int>(-1);
+ mCurrentConstantBufferVSOffset[i] = 0;
+ mCurrentConstantBufferVSSize[i] = 0;
+ mCurrentConstantBufferPS[i] = static_cast<unsigned int>(-1);
+ mCurrentConstantBufferPSOffset[i] = 0;
+ mCurrentConstantBufferPSSize[i] = 0;
+ }
+
+ mCurrentVertexConstantBuffer = NULL;
+ mCurrentPixelConstantBuffer = NULL;
+ mCurrentGeometryConstantBuffer = NULL;
+
+ mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+}
+
+void Renderer11::releaseDeviceResources()
+{
+ mStateManager.deinitialize();
+ mStateCache.clear();
+ mInputLayoutCache.clear();
+
+ SafeDelete(mVertexDataManager);
+ SafeDelete(mIndexDataManager);
+ SafeDelete(mLineLoopIB);
+ SafeDelete(mTriangleFanIB);
+ SafeDelete(mBlit);
+ SafeDelete(mClear);
+ SafeDelete(mTrim);
+ SafeDelete(mPixelTransfer);
+
+ SafeRelease(mDriverConstantBufferVS);
+ SafeRelease(mDriverConstantBufferPS);
+ SafeRelease(mSyncQuery);
+}
+
+// set notify to true to broadcast a message to all contexts of the device loss
+bool Renderer11::testDeviceLost()
+{
+ bool isLost = false;
+
+ if (!mDevice)
+ {
+ return true;
+ }
+
+ // GetRemovedReason is used to test if the device is removed
+ HRESULT result = mDevice->GetDeviceRemovedReason();
+ isLost = d3d11::isDeviceLostError(result);
+
+ if (isLost)
+ {
+ ERR("The D3D11 device was removed: 0x%08X", result);
+ }
+
+ return isLost;
+}
+
+bool Renderer11::testDeviceResettable()
+{
+ // determine if the device is resettable by creating a dummy device
+ PFN_D3D11_CREATE_DEVICE D3D11CreateDevice =
+ (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
+
+ if (D3D11CreateDevice == NULL)
+ {
+ return false;
+ }
+
+ ID3D11Device *dummyDevice;
+ D3D_FEATURE_LEVEL dummyFeatureLevel;
+ ID3D11DeviceContext *dummyContext;
+
+ ASSERT(mRequestedDriverType != D3D_DRIVER_TYPE_UNKNOWN);
+ HRESULT result = D3D11CreateDevice(
+ NULL, mRequestedDriverType, NULL,
+#if defined(_DEBUG)
+ D3D11_CREATE_DEVICE_DEBUG,
+#else
+ 0,
+#endif
+ mAvailableFeatureLevels.data(), static_cast<unsigned int>(mAvailableFeatureLevels.size()),
+ D3D11_SDK_VERSION, &dummyDevice, &dummyFeatureLevel, &dummyContext);
+
+ if (!mDevice || FAILED(result))
+ {
+ return false;
+ }
+
+ SafeRelease(dummyContext);
+ SafeRelease(dummyDevice);
+
+ return true;
+}
+
+void Renderer11::release()
+{
+ RendererD3D::cleanup();
+
+ mScratchMemoryBuffer.resize(0);
+
+ if (mAnnotator != nullptr)
+ {
+ gl::UninitializeDebugAnnotations();
+ SafeDelete(mAnnotator);
+ }
+
+ releaseDeviceResources();
+
+ if (!mCreatedWithDeviceEXT)
+ {
+ // Only delete the device if the Renderer11 owns it
+ // Otherwise we should keep it around in case we try to reinitialize the renderer later
+ SafeDelete(mEGLDevice);
+ }
+
+ SafeRelease(mDxgiFactory);
+ SafeRelease(mDxgiAdapter);
+
+ SafeRelease(mDeviceContext1);
+
+ if (mDeviceContext)
+ {
+ mDeviceContext->ClearState();
+ mDeviceContext->Flush();
+ SafeRelease(mDeviceContext);
+ }
+
+ SafeRelease(mDevice);
+ SafeRelease(mDebug);
+
+ if (mD3d11Module)
+ {
+ FreeLibrary(mD3d11Module);
+ mD3d11Module = NULL;
+ }
+
+ if (mDxgiModule)
+ {
+ FreeLibrary(mDxgiModule);
+ mDxgiModule = NULL;
+ }
+
+ if (mDCompModule)
+ {
+ FreeLibrary(mDCompModule);
+ mDCompModule = NULL;
+ }
+
+ mCompiler.release();
+
+ mSupportsShareHandles.reset();
+}
+
+bool Renderer11::resetDevice()
+{
+ // recreate everything
+ release();
+ egl::Error result = initialize();
+
+ if (result.isError())
+ {
+ ERR("Could not reinitialize D3D11 device: %08X", result.getCode());
+ return false;
+ }
+
+ return true;
+}
+
+SIZE_T Renderer11::getMaxResourceSize() const
+{
+ // This formula comes from http://msdn.microsoft.com/en-us/library/windows/desktop/ff819065%28v=vs.85%29.aspx
+ return std::min(std::max(SIZE_T(128 * 1024 * 1024), mAdapterDescription.DedicatedVideoMemory), SIZE_T(2048) * 1024 * 1024);
+}
+
+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 = {0};
+ 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);
+}
+
+unsigned int Renderer11::getReservedVertexUniformBuffers() const
+{
+ // we reserve one buffer for the application uniforms, and one for driver uniforms
+ return 2;
+}
+
+unsigned int Renderer11::getReservedFragmentUniformBuffers() const
+{
+ // we reserve one buffer for the application uniforms, and one for driver uniforms
+ return 2;
+}
+
+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().textureFormatBGRA8888)
+ {
+ mSupportsShareHandles = false;
+ return false;
+ }
+
+ // PIX doesn't seem to support using share handles, so disable them.
+ if (gl::DebugAnnotationsActive())
+ {
+ 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)
+ {
+#ifndef ANGLE_ENABLE_WINDOWS_STORE
+ if (!IsWindows8OrGreater())
+ {
+ // WARP on Windows 7 doesn't support shared handles
+ mSupportsShareHandles = false;
+ return false;
+ }
+#endif // ANGLE_ENABLE_WINDOWS_STORE
+
+ // 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;
+}
+
+bool Renderer11::getNV12TextureSupport() const
+{
+ HRESULT result;
+ UINT formatSupport;
+ result = mDevice->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport);
+ if (result == E_FAIL)
+ {
+ return false;
+ }
+ return (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
+}
+
+int Renderer11::getMajorShaderModel() const
+{
+ switch (mRenderer11DeviceCaps.featureLevel)
+ {
+ 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_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_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 "";
+ }
+}
+
+const WorkaroundsD3D &RendererD3D::getWorkarounds() const
+{
+ if (!mWorkaroundsInitialized)
+ {
+ mWorkarounds = generateWorkarounds();
+ mWorkaroundsInitialized = true;
+ }
+
+ return mWorkarounds;
+}
+
+gl::Error Renderer11::copyImageInternal(const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ RenderTargetD3D *destRenderTarget)
+{
+ const gl::FramebufferAttachment *colorAttachment = framebuffer->getReadColorbuffer();
+ ASSERT(colorAttachment);
+
+ RenderTarget11 *sourceRenderTarget = nullptr;
+ ANGLE_TRY(colorAttachment->getRenderTarget(&sourceRenderTarget));
+ ASSERT(sourceRenderTarget);
+
+ ID3D11ShaderResourceView *source = sourceRenderTarget->getBlitShaderResourceView();
+ ASSERT(source);
+
+ ID3D11RenderTargetView *dest = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
+ ASSERT(dest);
+
+ 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.
+ const gl::InternalFormat &internalFormat = gl::GetInternalFormatInfo(destFormat);
+ ANGLE_TRY(mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, nullptr,
+ internalFormat.format, GL_NEAREST, false, false, false));
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::copyImage2D(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(index, &destRenderTarget));
+ ASSERT(destRenderTarget);
+
+ ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget));
+
+ storage11->markLevelDirty(level);
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum target,
+ GLint level)
+{
+ TextureStorage11_Cube *storage11 = GetAs<TextureStorage11_Cube>(storage);
+ ASSERT(storage11);
+
+ gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
+ ASSERT(destRenderTarget);
+
+ ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget));
+
+ storage11->markLevelDirty(level);
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::copyImage3D(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(index, &destRenderTarget));
+ ASSERT(destRenderTarget);
+
+ ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget));
+
+ storage11->markLevelDirty(level);
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::copyImage2DArray(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(index, &destRenderTarget));
+ ASSERT(destRenderTarget);
+
+ ANGLE_TRY(copyImageInternal(framebuffer, sourceRect, destFormat, destOffset, destRenderTarget));
+ storage11->markLevelDirty(level);
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::copyTexture(const gl::Texture *source,
+ GLint sourceLevel,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ const TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+
+ TextureStorage *sourceStorage = nullptr;
+ ANGLE_TRY(const_cast<TextureD3D *>(sourceD3D)->getNativeTexture(&sourceStorage));
+
+ TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
+ ASSERT(sourceStorage11);
+
+ TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage);
+ ASSERT(destStorage11);
+
+ // Check for fast path where a CopySubresourceRegion can be used.
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !unpackFlipY &&
+ sourceStorage11->getFormatSet().texFormat == destStorage11->getFormatSet().texFormat)
+ {
+ ID3D11Resource *sourceResource = nullptr;
+ ANGLE_TRY(sourceStorage11->getResource(&sourceResource));
+
+ gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
+ UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex);
+
+ ID3D11Resource *destResource = nullptr;
+ ANGLE_TRY(destStorage11->getResource(&destResource));
+
+ gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
+ UINT destSubresource = destStorage11->getSubresourceIndex(destIndex);
+
+ D3D11_BOX sourceBox{
+ static_cast<UINT>(sourceRect.x),
+ static_cast<UINT>(sourceRect.y),
+ 0u,
+ static_cast<UINT>(sourceRect.x + sourceRect.width),
+ static_cast<UINT>(sourceRect.y + sourceRect.height),
+ 1u,
+ };
+
+ mDeviceContext->CopySubresourceRegion(destResource, destSubresource, destOffset.x,
+ destOffset.y, destOffset.z, sourceResource,
+ sourceSubresource, &sourceBox);
+ }
+ else
+ {
+ ID3D11ShaderResourceView *sourceSRV = nullptr;
+ ANGLE_TRY(sourceStorage11->getSRVLevels(sourceLevel, sourceLevel, &sourceSRV));
+
+ gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
+ RenderTargetD3D *destRenderTargetD3D = nullptr;
+ ANGLE_TRY(destStorage11->getRenderTarget(destIndex, &destRenderTargetD3D));
+
+ RenderTarget11 *destRenderTarget11 = GetAs<RenderTarget11>(destRenderTargetD3D);
+
+ ID3D11RenderTargetView *destRTV = destRenderTarget11->getRenderTargetView();
+ ASSERT(destRTV);
+
+ gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
+ gl::Extents sourceSize(
+ static_cast<int>(source->getWidth(source->getTarget(), sourceLevel)),
+ static_cast<int>(source->getHeight(source->getTarget(), sourceLevel)), 1);
+ if (unpackFlipY)
+ {
+ 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(destRenderTarget11->getWidth(), destRenderTarget11->getHeight(), 1);
+
+ // Use nearest filtering because source and destination are the same size for the direct
+ // copy
+ ANGLE_TRY(mBlit->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize,
+ nullptr, destFormat, GL_NEAREST, false, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha));
+ }
+
+ destStorage11->markLevelDirty(destLevel);
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::copyCompressedTexture(const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel)
+{
+ TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage);
+ ASSERT(destStorage11);
+
+ ID3D11Resource *destResource = nullptr;
+ ANGLE_TRY(destStorage11->getResource(&destResource));
+
+ gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
+ UINT destSubresource = destStorage11->getSubresourceIndex(destIndex);
+
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ASSERT(sourceD3D);
+
+ TextureStorage *sourceStorage = nullptr;
+ ANGLE_TRY(sourceD3D->getNativeTexture(&sourceStorage));
+
+ TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
+ ASSERT(sourceStorage11);
+
+ ID3D11Resource *sourceResource = nullptr;
+ ANGLE_TRY(sourceStorage11->getResource(&sourceResource));
+
+ gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
+ UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex);
+
+ mDeviceContext->CopySubresourceRegion(destResource, destSubresource, 0, 0, 0, sourceResource,
+ sourceSubresource, nullptr);
+
+ return gl::NoError();
+}
+
+UINT64 EstimateSize(D3D11_TEXTURE2D_DESC &desc)
+{
+ //XXX: handle overflow (64 bits should be enough for anyone...)
+ const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(desc.Format);
+ // NVIDIA seems to align the width of buffers by 8 and the height by 64, so we do the same.
+ UINT64 total = UINT64(rx::roundUp(desc.Width, UINT(8))) * rx::roundUp(desc.Height, UINT(64)) * desc.SampleDesc.Count * dxgiFormatInfo.pixelBytes;
+ return total;
+}
+
+gl::Error Renderer11::createRenderTarget(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);
+
+ 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 = 0;
+ 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);
+
+ // D3D feature level 10.0 no longer allows creation of textures with both the bind SRV and
+ // DSV flags when multisampled. crbug.com/656989
+ bool supportsMultisampledDepthStencilSRVs =
+ mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_10_0;
+ bool isMultisampledDepthStencil = bindDSV && desc.SampleDesc.Count > 1;
+ if (isMultisampledDepthStencil && !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);
+
+ ID3D11Texture2D *texture = NULL;
+ HRESULT result;
+
+ // Some Nvidia drivers (GeForce GT 610 w/ 9.18.13.3523) crash with very large render targets
+ if (EstimateSize(desc) > getMaxResourceSize())
+ {
+ result = E_OUTOFMEMORY;
+ }
+ else
+ {
+ result = mDevice->CreateTexture2D(&desc, NULL, &texture);
+ }
+
+ if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create render target texture, result: 0x%X.", result);
+ }
+
+ ID3D11ShaderResourceView *srv = nullptr;
+ ID3D11ShaderResourceView *blitSRV = nullptr;
+ 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;
+
+ result = mDevice->CreateShaderResourceView(texture, &srvDesc, &srv);
+ if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ SafeRelease(texture);
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Failed to create render target shader resource view, result: 0x%X.", result);
+ }
+
+ 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;
+
+ result = mDevice->CreateShaderResourceView(texture, &blitSRVDesc, &blitSRV);
+ if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ SafeRelease(texture);
+ SafeRelease(srv);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create render target shader resource view for "
+ "blits, result: 0x%X.",
+ result);
+ }
+ }
+ else
+ {
+ blitSRV = srv;
+ srv->AddRef();
+ }
+ }
+
+ 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;
+
+ ID3D11DepthStencilView *dsv = NULL;
+ result = mDevice->CreateDepthStencilView(texture, &dsvDesc, &dsv);
+ if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ SafeRelease(texture);
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create render target depth stencil view, result: 0x%X.",
+ result);
+ }
+
+ *outRT = new TextureRenderTarget11(dsv, texture, srv, format, formatInfo, width, height,
+ 1, supportedSamples);
+
+ SafeRelease(dsv);
+ }
+ 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;
+
+ ID3D11RenderTargetView *rtv = NULL;
+ result = mDevice->CreateRenderTargetView(texture, &rtvDesc, &rtv);
+ if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ SafeRelease(texture);
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create render target render target view, result: 0x%X.",
+ result);
+ }
+
+ if (formatInfo.dataInitializerFunction != NULL)
+ {
+ const float clearValues[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ mDeviceContext->ClearRenderTargetView(rtv, clearValues);
+ }
+
+ *outRT = new TextureRenderTarget11(rtv, texture, srv, blitSRV, format, formatInfo,
+ width, height, 1, supportedSamples);
+
+ SafeRelease(rtv);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ SafeRelease(texture);
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ }
+ else
+ {
+ *outRT = new TextureRenderTarget11(
+ static_cast<ID3D11RenderTargetView *>(nullptr), nullptr, nullptr, nullptr, format,
+ d3d11::Format::Get(GL_NONE, mRenderer11DeviceCaps), width, height, 1, supportedSamples);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT)
+{
+ ASSERT(source != nullptr);
+
+ RenderTargetD3D *newRT = nullptr;
+ ANGLE_TRY(createRenderTarget(source->getWidth(), source->getHeight(),
+ source->getInternalFormat(), source->getSamples(), &newRT));
+
+ RenderTarget11 *source11 = GetAs<RenderTarget11>(source);
+ RenderTarget11 *dest11 = GetAs<RenderTarget11>(newRT);
+
+ mDeviceContext->CopySubresourceRegion(dest11->getTexture(), dest11->getSubresourceIndex(), 0, 0,
+ 0, source11->getTexture(),
+ source11->getSubresourceIndex(), nullptr);
+ *outRT = newRT;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::loadExecutable(const void *function,
+ size_t length,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable)
+{
+ switch (type)
+ {
+ case SHADER_VERTEX:
+ {
+ ID3D11VertexShader *vertexShader = NULL;
+ ID3D11GeometryShader *streamOutShader = NULL;
+
+ HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.",
+ result);
+ }
+
+ if (!streamOutVaryings.empty())
+ {
+ std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration;
+ soDeclaration.reserve(streamOutVaryings.size());
+
+ for (const auto &streamOutVarying : streamOutVaryings)
+ {
+ D3D11_SO_DECLARATION_ENTRY entry = {0};
+ 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);
+ }
+
+ result = mDevice->CreateGeometryShaderWithStreamOutput(
+ function, static_cast<unsigned int>(length), soDeclaration.data(),
+ static_cast<unsigned int>(soDeclaration.size()), NULL, 0, 0, NULL,
+ &streamOutShader);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create steam output shader, result: 0x%X.", result);
+ }
+ }
+
+ *outExecutable =
+ new ShaderExecutable11(function, length, vertexShader, streamOutShader);
+ }
+ break;
+ case SHADER_PIXEL:
+ {
+ ID3D11PixelShader *pixelShader = NULL;
+
+ HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader, result: 0x%X.",
+ result);
+ }
+
+ *outExecutable = new ShaderExecutable11(function, length, pixelShader);
+ }
+ break;
+ case SHADER_GEOMETRY:
+ {
+ ID3D11GeometryShader *geometryShader = NULL;
+
+ HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create geometry shader, result: 0x%X.", result);
+ }
+
+ *outExecutable = new ShaderExecutable11(function, length, geometryShader);
+ }
+ break;
+ default:
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const D3DCompilerWorkarounds &workarounds,
+ ShaderExecutableD3D **outExectuable)
+{
+ const char *profileType = NULL;
+ switch (type)
+ {
+ case SHADER_VERTEX:
+ profileType = "vs";
+ break;
+ case SHADER_PIXEL:
+ profileType = "ps";
+ break;
+ case SHADER_GEOMETRY:
+ profileType = "gs";
+ break;
+ default:
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+ }
+
+ std::string profile = FormatString("%s_%d_%d%s", profileType, getMajorShaderModel(),
+ getMinorShaderModel(), getShaderModelSuffix().c_str());
+
+ UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;
+
+ if (gl::DebugAnnotationsActive())
+ {
+#ifndef NDEBUG
+ flags = D3DCOMPILE_SKIP_OPTIMIZATION;
+#endif
+
+ flags |= D3DCOMPILE_DEBUG;
+ }
+
+ 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}};
+
+ ID3DBlob *binary = NULL;
+ std::string debugInfo;
+ ANGLE_TRY(mCompiler.compileToBinary(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 = NULL;
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ gl::Error error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
+ streamOutVaryings, separatedOutputBuffers, outExectuable);
+
+ SafeRelease(binary);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!debugInfo.empty())
+ {
+ (*outExectuable)->appendDebugInfo(debugInfo);
+ }
+
+ return gl::NoError();
+}
+
+UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize)
+{
+ return new UniformStorage11(this, storageSize);
+}
+
+VertexBuffer *Renderer11::createVertexBuffer()
+{
+ return new VertexBuffer11(this);
+}
+
+IndexBuffer *Renderer11::createIndexBuffer()
+{
+ return new IndexBuffer11(this);
+}
+
+StreamProducerImpl *Renderer11::createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs)
+{
+ return new StreamProducerNV12(this);
+}
+
+bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
+{
+ ASSERT(getNativeExtensions().pixelBufferObject);
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(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;
+}
+
+gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea)
+{
+ ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
+ return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat,
+ sourcePixelsType, destArea);
+}
+
+ImageD3D *Renderer11::createImage()
+{
+ return new Image11(this);
+}
+
+gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src)
+{
+ Image11 *dest11 = GetAs<Image11>(dest);
+ Image11 *src11 = GetAs<Image11>(src);
+ return Image11::generateMipmap(dest11, src11, mRenderer11DeviceCaps);
+}
+
+gl::Error Renderer11::generateMipmapUsingD3D(TextureStorage *storage,
+ const gl::TextureState &textureState)
+{
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
+
+ ASSERT(storage11->isRenderTarget());
+ ASSERT(storage11->supportsNativeMipmapFunction());
+
+ ID3D11ShaderResourceView *srv;
+ ANGLE_TRY(storage11->getSRVLevels(textureState.getEffectiveBaseLevel(),
+ textureState.getEffectiveMaxLevel(), &srv));
+
+ mDeviceContext->GenerateMips(srv);
+
+ return gl::NoError();
+}
+
+TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain)
+{
+ SwapChain11 *swapChain11 = GetAs<SwapChain11>(swapChain);
+ return new TextureStorage11_2D(this, swapChain11);
+}
+
+TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D)
+{
+ return new TextureStorage11_EGLImage(this, eglImage, GetAs<RenderTarget11>(renderTargetD3D));
+}
+
+TextureStorage *Renderer11::createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
+{
+ return new TextureStorage11_External(this, stream, desc);
+}
+
+TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ bool hintLevelZeroOnly)
+{
+ return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels,
+ hintLevelZeroOnly);
+}
+
+TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat,
+ bool renderTarget,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly)
+{
+ return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels,
+ hintLevelZeroOnly);
+}
+
+TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels)
+{
+ return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth,
+ levels);
+}
+
+TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels)
+{
+ return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth,
+ levels);
+}
+
+gl::Error Renderer11::readFromAttachment(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);
+
+ RenderTargetD3D *renderTarget = nullptr;
+ ANGLE_TRY(srcAttachment.getRenderTarget(&renderTarget));
+
+ RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget);
+ ASSERT(rt11->getTexture());
+
+ TextureHelper11 textureHelper =
+ TextureHelper11::MakeAndReference(rt11->getTexture(), rt11->getFormatSet());
+ unsigned int sourceSubResource = rt11->getSubresourceIndex();
+
+ const gl::Extents &texSize = textureHelper.getExtents();
+
+ gl::Rectangle actualArea = sourceArea;
+ if (invertTexture)
+ {
+ actualArea.y = texSize.height - actualArea.y - actualArea.height;
+ }
+
+ // 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 gl::NoError();
+ }
+
+ gl::Extents safeSize(safeArea.width, safeArea.height, 1);
+ TextureHelper11 stagingHelper;
+ ANGLE_TRY_RESULT(
+ CreateStagingTexture(textureHelper.getTextureType(), textureHelper.getFormatSet(), safeSize,
+ StagingAccess::READ, mDevice),
+ 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.getTextureType() == GL_TEXTURE_2D && 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;
+
+ ID3D11Texture2D *resolveTex2D = nullptr;
+ HRESULT result = mDevice->CreateTexture2D(&resolveDesc, nullptr, &resolveTex2D);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Renderer11::readTextureData failed to create internal resolve "
+ "texture for ReadPixels, HRESULT: 0x%X.",
+ result);
+ }
+
+ mDeviceContext->ResolveSubresource(resolveTex2D, 0, textureHelper.getTexture2D(),
+ sourceSubResource, textureHelper.getFormat());
+ resolvedTextureHelper =
+ TextureHelper11::MakeAndReference(resolveTex2D, textureHelper.getFormatSet());
+
+ 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.getTextureType() == GL_TEXTURE_3D)
+ {
+ srcBox.front = static_cast<UINT>(srcAttachment.layer());
+ }
+ srcBox.back = srcBox.front + 1;
+
+ mDeviceContext->CopySubresourceRegion(stagingHelper.getResource(), 0, 0, 0, 0,
+ srcTexture->getResource(), sourceSubResource, &srcBox);
+
+ if (!invertTexture)
+ {
+ PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0);
+ return packPixels(stagingHelper, packParams, pixelsOut);
+ }
+
+ gl::PixelPackState invertTexturePack;
+
+ // Create a new PixelPackState with reversed row order. Note that we can't just assign
+ // 'invertTexturePack' to be 'pack' (or memcpy) since that breaks the ref counting/object
+ // tracking in the 'pixelBuffer' members, causing leaks. Instead we must use
+ // pixelBuffer.set() twice, which performs the addRef/release correctly
+ invertTexturePack.alignment = pack.alignment;
+ invertTexturePack.pixelBuffer.set(pack.pixelBuffer.get());
+ invertTexturePack.reverseRowOrder = !pack.reverseRowOrder;
+
+ PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, 0);
+ gl::Error error = packPixels(stagingHelper, packParams, pixelsOut);
+ invertTexturePack.pixelBuffer.set(nullptr);
+ ANGLE_TRY(error);
+ return gl::NoError();
+}
+
+gl::Error Renderer11::packPixels(const TextureHelper11 &textureHelper,
+ const PackPixelsParams &params,
+ uint8_t *pixelsOut)
+{
+ ID3D11Resource *readResource = textureHelper.getResource();
+
+ D3D11_MAPPED_SUBRESOURCE mapping;
+ HRESULT hr = mDeviceContext->Map(readResource, 0, D3D11_MAP_READ, 0, &mapping);
+ if (FAILED(hr))
+ {
+ ASSERT(hr == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to map internal texture for reading, result: 0x%X.", hr);
+ }
+
+ 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 gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
+ const gl::Rectangle &drawRectIn,
+ 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);
+ if (!drawRenderTarget11)
+ {
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Failed to retrieve the internal draw render target from the draw framebuffer.");
+ }
+
+ TextureHelper11 drawTexture = TextureHelper11::MakeAndReference(
+ drawRenderTarget11->getTexture(), drawRenderTarget11->getFormatSet());
+ unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
+ ID3D11RenderTargetView *drawRTV = drawRenderTarget11->getRenderTargetView();
+ ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView();
+
+ RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
+ if (!readRenderTarget11)
+ {
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Failed to retrieve the internal read render target from the read framebuffer.");
+ }
+
+ TextureHelper11 readTexture;
+ unsigned int readSubresource = 0;
+ ID3D11ShaderResourceView *readSRV = nullptr;
+
+ if (readRenderTarget->getSamples() > 1)
+ {
+ auto readRT11 = GetAs<RenderTarget11>(readRenderTarget);
+ ANGLE_TRY_RESULT(resolveMultisampledTexture(readRT11, depthBlit, stencilBlit), readTexture);
+
+ if (!stencilBlit)
+ {
+ 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;
+
+ HRESULT hresult =
+ mDevice->CreateShaderResourceView(readTexture.getResource(), &viewDesc, &readSRV);
+ if (FAILED(hresult))
+ {
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Renderer11::blitRenderbufferRect: Failed to create temporary SRV.");
+ }
+ }
+ }
+ else
+ {
+ ASSERT(readRenderTarget11);
+ readTexture = TextureHelper11::MakeAndReference(readRenderTarget11->getTexture(),
+ readRenderTarget11->getFormatSet());
+ readSubresource = readRenderTarget11->getSubresourceIndex();
+ readSRV = readRenderTarget11->getBlitShaderResourceView();
+ if (readSRV == nullptr)
+ {
+ ASSERT(depthBlit || stencilBlit);
+ readSRV = readRenderTarget11->getShaderResourceView();
+ }
+ ASSERT(readSRV);
+ readSRV->AddRef();
+ }
+
+ // Stencil blits don't use shaders.
+ ASSERT(readSRV || stencilBlit);
+
+ 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.
+ gl::Rectangle readRect = readRectIn;
+ gl::Rectangle drawRect = drawRectIn;
+ auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset) {
+ double readToDrawScale =
+ static_cast<double>(drawRectIn.width) / static_cast<double>(readRectIn.width);
+ return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
+ };
+ if (readRect.x < 0)
+ {
+ int readOffset = -readRect.x;
+ readRect.x += readOffset;
+ readRect.width -= readOffset;
+
+ int drawOffset = readToDrawX(readOffset);
+ drawRect.x += drawOffset;
+ drawRect.width -= drawOffset;
+ }
+
+ auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) {
+ double readToDrawScale =
+ static_cast<double>(drawRectIn.height) / static_cast<double>(readRectIn.height);
+ return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
+ };
+ if (readRect.y < 0)
+ {
+ int readOffset = -readRect.y;
+ readRect.y += readOffset;
+ readRect.height -= readOffset;
+
+ int drawOffset = readToDrawY(readOffset);
+ drawRect.y += drawOffset;
+ drawRect.height -= drawOffset;
+ }
+
+ if (readRect.x1() < 0)
+ {
+ int readOffset = -readRect.x1();
+ readRect.width += readOffset;
+
+ int drawOffset = readToDrawX(readOffset);
+ drawRect.width += drawOffset;
+ }
+
+ if (readRect.y1() < 0)
+ {
+ int readOffset = -readRect.y1();
+ readRect.height += readOffset;
+
+ int drawOffset = readToDrawY(readOffset);
+ drawRect.height += drawOffset;
+ }
+
+ bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, nullptr);
+
+ const auto &destFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat());
+ const auto &srcFormatInfo = gl::GetInternalFormatInfo(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;
+
+ bool flipRequired =
+ readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0;
+
+ 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);
+
+ if (readRenderTarget11->getFormatSet().formatID ==
+ drawRenderTarget11->getFormatSet().formatID &&
+ !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
+ !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy))
+ {
+ UINT dstX = drawRect.x;
+ UINT dstY = drawRect.y;
+
+ 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 = 0;
+ readBox.back = 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 ? nullptr : &readBox;
+
+ mDeviceContext->CopySubresourceRegion(drawTexture.getResource(), drawSubresource, dstX,
+ dstY, 0, readTexture.getResource(), 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(readTexture, readSubresource, readArea, readSize,
+ drawTexture, drawSubresource, drawArea, drawSize,
+ scissor));
+ }
+ else if (depthBlit)
+ {
+ ASSERT(readSRV);
+ ANGLE_TRY(mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize,
+ scissor));
+ }
+ else if (stencilBlit)
+ {
+ ANGLE_TRY(mBlit->copyStencil(readTexture, readSubresource, readArea, readSize,
+ drawTexture, drawSubresource, drawArea, drawSize,
+ scissor));
+ }
+ else
+ {
+ // We don't currently support masking off any other channel than alpha
+ bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha;
+ ASSERT(readSRV);
+ ANGLE_TRY(mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize,
+ scissor, destFormatInfo.format, filter, maskOffAlpha,
+ false, false));
+ }
+ }
+
+ SafeRelease(readSRV);
+
+ return gl::NoError();
+}
+
+bool Renderer11::isES3Capable() const
+{
+ return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel) > 2);
+};
+
+void Renderer11::onSwap()
+{
+ // Send histogram updates every half hour
+ const double kHistogramUpdateInterval = 30 * 60;
+
+ const double currentTime = ANGLEPlatformCurrent()->monotonicallyIncreasingTime();
+ 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 (auto &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);
+}
+
+gl::ErrorOrResult<TextureHelper11>
+Renderer11::resolveMultisampledTexture(RenderTarget11 *renderTarget, bool depth, bool stencil)
+{
+ if (depth && !stencil)
+ {
+ return mBlit->resolveDepth(renderTarget);
+ }
+
+ if (stencil)
+ {
+ return mBlit->resolveStencil(renderTarget, depth);
+ }
+
+ const auto &formatSet = renderTarget->getFormatSet();
+
+ ASSERT(renderTarget->getSamples() > 1);
+
+ 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;
+
+ ID3D11Texture2D *resolveTexture = nullptr;
+ HRESULT result = mDevice->CreateTexture2D(&resolveDesc, nullptr, &resolveTexture);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create a multisample resolve texture, HRESULT: 0x%X.", result);
+ }
+
+ mDeviceContext->ResolveSubresource(resolveTexture, 0, renderTarget->getTexture(),
+ renderTarget->getSubresourceIndex(), formatSet.texFormat);
+ return TextureHelper11::MakeAndPossess2D(resolveTexture, renderTarget->getFormatSet());
+}
+
+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(
+ gl::VertexFormatType vertexFormatType) const
+{
+ return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel)
+ .conversionType;
+}
+
+GLenum Renderer11::getVertexComponentType(gl::VertexFormatType vertexFormatType) const
+{
+ const auto &format =
+ d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel);
+ return d3d11::GetComponentType(format.nativeFormat);
+}
+
+gl::ErrorOrResult<unsigned int> Renderer11::getVertexSpaceRequired(
+ const gl::VertexAttribute &attrib,
+ GLsizei count,
+ GLsizei instances) const
+{
+ if (!attrib.enabled)
+ {
+ return 16u;
+ }
+
+ unsigned int elementCount = 0;
+ if (instances == 0 || attrib.divisor == 0)
+ {
+ elementCount = count;
+ }
+ else
+ {
+ // Round up to divisor, if possible
+ elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
+ }
+
+ gl::VertexFormatType formatType = gl::GetVertexFormatType(attrib);
+ const D3D_FEATURE_LEVEL featureLevel = mRenderer11DeviceCaps.featureLevel;
+ const d3d11::VertexFormat &vertexFormatInfo =
+ d3d11::GetVertexFormatInfo(formatType, featureLevel);
+ const d3d11::DXGIFormatSize &dxgiFormatInfo =
+ d3d11::GetDXGIFormatSizeInfo(vertexFormatInfo.nativeFormat);
+ unsigned int elementSize = dxgiFormatInfo.pixelBytes;
+ if (elementSize > std::numeric_limits<unsigned int>::max() / elementCount)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
+ }
+
+ return elementSize * elementCount;
+}
+
+void Renderer11::generateCaps(gl::Caps *outCaps,
+ gl::TextureCapsMap *outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations *outLimitations) const
+{
+ d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps,
+ outExtensions, outLimitations);
+}
+
+WorkaroundsD3D Renderer11::generateWorkarounds() const
+{
+ return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps, mAdapterDescription);
+}
+
+gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd)
+{
+ return mStateManager.clearTextures(samplerType, rangeStart, rangeEnd);
+}
+
+egl::Error Renderer11::getEGLDevice(DeviceImpl **device)
+{
+ if (mEGLDevice == nullptr)
+ {
+ ASSERT(mDevice != nullptr);
+ mEGLDevice = new DeviceD3D();
+ egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice),
+ EGL_D3D11_DEVICE_ANGLE, EGL_FALSE);
+
+ if (error.isError())
+ {
+ SafeDelete(mEGLDevice);
+ return error;
+ }
+ }
+
+ *device = static_cast<DeviceImpl *>(mEGLDevice);
+ return egl::Error(EGL_SUCCESS);
+}
+
+ContextImpl *Renderer11::createContext(const gl::ContextState &state)
+{
+ return new Context11(state, this);
+}
+
+gl::Error Renderer11::genericDrawElements(Context11 *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange)
+{
+ const auto &data = context->getContextState();
+ const auto &glState = data.getState();
+ gl::Program *program = glState.getProgram();
+ ASSERT(program != nullptr);
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ bool usesPointSize = programD3D->usesPointSize();
+
+ programD3D->updateSamplerMapping();
+
+ ANGLE_TRY(generateSwizzles(data));
+
+ if (!applyPrimitiveType(mode, count, usesPointSize))
+ {
+ return gl::NoError();
+ }
+
+ ANGLE_TRY(updateState(data, mode));
+
+ TranslatedIndexData indexInfo;
+ indexInfo.indexRange = indexRange;
+
+ ANGLE_TRY(applyIndexBuffer(data, indices, count, mode, type, &indexInfo));
+
+ applyTransformFeedbackBuffers(data);
+ // Transform feedback is not allowed for DrawElements, this error should have been caught at the
+ // API validation layer.
+ ASSERT(!glState.isTransformFeedbackActiveUnpaused());
+
+ size_t vertexCount = indexInfo.indexRange.vertexCount();
+ ANGLE_TRY(applyVertexBuffer(glState, mode, static_cast<GLsizei>(indexInfo.indexRange.start),
+ static_cast<GLsizei>(vertexCount), instances, &indexInfo));
+ ANGLE_TRY(applyTextures(context, data));
+ ANGLE_TRY(applyShaders(data, mode));
+ ANGLE_TRY(programD3D->applyUniformBuffers(data));
+
+ if (!skipDraw(data, mode))
+ {
+ ANGLE_TRY(drawElementsImpl(data, indexInfo, mode, count, type, indices, instances));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::genericDrawArrays(Context11 *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances)
+{
+ const auto &data = context->getContextState();
+ const auto &glState = data.getState();
+ gl::Program *program = glState.getProgram();
+ ASSERT(program != nullptr);
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ bool usesPointSize = programD3D->usesPointSize();
+
+ programD3D->updateSamplerMapping();
+
+ ANGLE_TRY(generateSwizzles(data));
+ if (!applyPrimitiveType(mode, count, usesPointSize))
+ {
+ return gl::NoError();
+ }
+
+ ANGLE_TRY(updateState(data, mode));
+ ANGLE_TRY(applyTransformFeedbackBuffers(data));
+ ANGLE_TRY(applyVertexBuffer(glState, mode, first, count, instances, nullptr));
+ ANGLE_TRY(applyTextures(context, data));
+ ANGLE_TRY(applyShaders(data, mode));
+ ANGLE_TRY(programD3D->applyUniformBuffers(data));
+
+ if (!skipDraw(data, mode))
+ {
+ ANGLE_TRY(drawArraysImpl(data, mode, first, count, instances));
+
+ if (glState.isTransformFeedbackActiveUnpaused())
+ {
+ ANGLE_TRY(markTransformFeedbackUsage(data));
+ }
+ }
+
+ return gl::NoError();
+}
+
+FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+ return new Framebuffer11(state, this);
+}
+
+gl::Error Renderer11::getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut)
+{
+ if (mScratchMemoryBuffer.size() == requestedSize)
+ {
+ mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime;
+ *bufferOut = &mScratchMemoryBuffer;
+ return gl::NoError();
+ }
+
+ if (mScratchMemoryBuffer.size() > requestedSize)
+ {
+ mScratchMemoryBufferResetCounter--;
+ }
+
+ if (mScratchMemoryBufferResetCounter <= 0 || mScratchMemoryBuffer.size() < requestedSize)
+ {
+ mScratchMemoryBuffer.resize(0);
+ if (!mScratchMemoryBuffer.resize(requestedSize))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer.");
+ }
+ mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime;
+ }
+
+ ASSERT(mScratchMemoryBuffer.size() >= requestedSize);
+
+ *bufferOut = &mScratchMemoryBuffer;
+ return gl::NoError();
+}
+
+gl::Version Renderer11::getMaxSupportedESVersion() const
+{
+ return gl::Version(d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel), 0);
+}
+
+gl::DebugAnnotator *Renderer11::getAnnotator()
+{
+ return mAnnotator;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
new file mode 100755
index 000000000..576fe3215
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -0,0 +1,580 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h"
+#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
+#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+struct ImageIndex;
+}
+
+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
+{
+ 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
+ UINT B5G6R5support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G6R5_UNORM
+ UINT B4G4R4A4support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B4G4R4A4_UNORM
+ UINT B5G5R5A1support; // Bitfield of D3D11_FORMAT_SUPPORT values for 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
+};
+
+// 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
+};
+
+class Renderer11 : public RendererD3D
+{
+ public:
+ explicit Renderer11(egl::Display *display);
+ virtual ~Renderer11();
+
+ egl::Error initialize() override;
+ bool resetDevice() override;
+
+ egl::ConfigSet generateConfigs() override;
+ void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override;
+
+ ContextImpl *createContext(const gl::ContextState &state) override;
+
+ gl::Error flush();
+ gl::Error finish();
+
+ 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) override;
+ egl::Error getD3DTextureInfo(IUnknown *d3dTexture,
+ EGLint *width,
+ EGLint *height,
+ GLenum *fboFormat) const override;
+ egl::Error validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const override;
+
+ gl::Error setSamplerState(gl::SamplerType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &sampler) override;
+ gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) override;
+
+ gl::Error setUniformBuffers(const gl::ContextState &data,
+ const std::vector<GLint> &vertexUniformBuffers,
+ const std::vector<GLint> &fragmentUniformBuffers) override;
+
+ gl::Error updateState(const gl::ContextState &data, GLenum drawMode);
+
+ bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize);
+ gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer);
+ gl::Error applyUniforms(const ProgramD3D &programD3D,
+ GLenum drawMode,
+ const std::vector<D3DUniform *> &uniformArray) override;
+ gl::Error applyVertexBuffer(const gl::State &state,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances,
+ TranslatedIndexData *indexInfo);
+ gl::Error applyIndexBuffer(const gl::ContextState &data,
+ const GLvoid *indices,
+ GLsizei count,
+ GLenum mode,
+ GLenum type,
+ TranslatedIndexData *indexInfo);
+ gl::Error applyTransformFeedbackBuffers(const gl::ContextState &data);
+
+ // lost device
+ bool testDeviceLost() override;
+ bool testDeviceResettable() override;
+
+ SIZE_T getMaxResourceSize() const;
+ std::string getRendererDescription() const;
+ DeviceIdentifier getAdapterIdentifier() const override;
+
+ unsigned int getReservedVertexUniformVectors() const;
+ unsigned int getReservedFragmentUniformVectors() const;
+ unsigned int getReservedVertexUniformBuffers() const override;
+ unsigned int getReservedFragmentUniformBuffers() const override;
+
+ bool getShareHandleSupport() const;
+
+ bool getNV12TextureSupport() const;
+
+ int getMajorShaderModel() const override;
+ int getMinorShaderModel() const override;
+ std::string getShaderModelSuffix() const override;
+
+ // Pixel operations
+ gl::Error copyImage2D(const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+ gl::Error copyImageCube(const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum target,
+ GLint level) override;
+ gl::Error copyImage3D(const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+ gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+
+ gl::Error copyTexture(const gl::Texture *source,
+ GLint sourceLevel,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) override;
+ gl::Error copyCompressedTexture(const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel) override;
+
+ // RenderTarget creation
+ gl::Error createRenderTarget(int width,
+ int height,
+ GLenum format,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+ gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override;
+
+ // Shader operations
+ gl::Error loadExecutable(const void *function,
+ size_t length,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable) override;
+ gl::Error compileToExecutable(gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const D3DCompilerWorkarounds &workarounds,
+ ShaderExecutableD3D **outExectuable) override;
+ UniformStorageD3D *createUniformStorage(size_t storageSize) override;
+
+ // Image operations
+ ImageD3D *createImage() override;
+ gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
+ gl::Error generateMipmapUsingD3D(TextureStorage *storage,
+ const gl::TextureState &textureState) override;
+ TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) override;
+ TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D) override;
+ TextureStorage *createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+ TextureStorage *createTextureStorage2D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ bool hintLevelZeroOnly) override;
+ TextureStorage *createTextureStorageCube(GLenum internalformat,
+ bool renderTarget,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly) override;
+ TextureStorage *createTextureStorage3D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels) override;
+ TextureStorage *createTextureStorage2DArray(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels) override;
+
+ VertexBuffer *createVertexBuffer() override;
+ IndexBuffer *createIndexBuffer() override;
+
+ // Stream Creation
+ StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) override;
+
+ // D3D11-renderer specific methods
+ ID3D11Device *getDevice() { return mDevice; }
+ void *getD3DDevice() override;
+ ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
+ ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; };
+ IDXGIFactory *getDxgiFactory() { return mDxgiFactory; };
+
+ RenderStateCache &getStateCache() { return mStateCache; }
+
+ Blit11 *getBlitter() { return mBlit; }
+ Clear11 *getClearer() { return mClear; }
+ gl::DebugAnnotator *getAnnotator();
+
+ // Buffer-to-texture and Texture-to-buffer copies
+ bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override;
+ gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea) override;
+
+ void markAllStateDirty();
+ gl::Error packPixels(const TextureHelper11 &textureHelper,
+ const PackPixelsParams &params,
+ uint8_t *pixelsOut);
+
+ bool getLUID(LUID *adapterLuid) const override;
+ VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const override;
+ GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override;
+ gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(const gl::VertexAttribute &attrib,
+ GLsizei count,
+ GLsizei instances) const override;
+
+ gl::Error readFromAttachment(const gl::FramebufferAttachment &srcAttachment,
+ const gl::Rectangle &sourceArea,
+ GLenum format,
+ GLenum type,
+ GLuint outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixels);
+
+ gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, 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 { return RENDERER_D3D11; }
+ InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; }
+ StateManager11 *getStateManager() { return &mStateManager; }
+
+ void onSwap();
+ void onBufferCreate(const Buffer11 *created);
+ void onBufferDelete(const Buffer11 *deleted);
+
+ egl::Error getEGLDevice(DeviceImpl **device) override;
+
+ gl::Error genericDrawArrays(Context11 *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances);
+
+ gl::Error genericDrawElements(Context11 *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange);
+
+ // Necessary hack for default framebuffers in D3D.
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+ gl::Error getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut);
+
+ gl::Version getMaxSupportedESVersion() const override;
+
+ protected:
+ gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override;
+
+ private:
+ gl::Error drawArraysImpl(const gl::ContextState &data,
+ GLenum mode,
+ GLint startVertex,
+ GLsizei count,
+ GLsizei instances);
+ gl::Error drawElementsImpl(const gl::ContextState &data,
+ const TranslatedIndexData &indexInfo,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances);
+
+ void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations *outLimitations) const override;
+
+ WorkaroundsD3D generateWorkarounds() const override;
+
+ gl::Error drawLineLoop(const gl::ContextState &data,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const TranslatedIndexData *indexInfo,
+ int instances);
+ gl::Error drawTriangleFan(const gl::ContextState &data,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ int minIndex,
+ int instances);
+
+ gl::Error applyShaders(const gl::ContextState &data, GLenum drawMode);
+ gl::Error generateSwizzle(gl::Texture *texture);
+ gl::Error generateSwizzles(const gl::ContextState &data, gl::SamplerType type);
+ gl::Error generateSwizzles(const gl::ContextState &data);
+
+ gl::ErrorOrResult<TextureHelper11> resolveMultisampledTexture(RenderTarget11 *renderTarget,
+ bool depth,
+ bool stencil);
+
+ void populateRenderer11DeviceCaps();
+
+ void updateHistograms();
+
+ class SamplerMetadataD3D11 final : angle::NonCopyable
+ {
+ public:
+ SamplerMetadataD3D11();
+ ~SamplerMetadataD3D11();
+
+ struct dx_SamplerMetadata
+ {
+ int baseLevel;
+ int internalFormatBits;
+ int wrapModes;
+ int padding; // This just pads the struct to 16 bytes
+ };
+ static_assert(sizeof(dx_SamplerMetadata) == 16u,
+ "Sampler metadata struct must be one 4-vec / 16 bytes.");
+
+ void initData(unsigned int samplerCount);
+ void update(unsigned int samplerIndex, const gl::Texture &texture);
+
+ const dx_SamplerMetadata *getData() const;
+ size_t sizeBytes() const;
+ bool isDirty() const { return mDirty; }
+ void markClean() { mDirty = false; }
+
+ private:
+ std::vector<dx_SamplerMetadata> mSamplerMetadata;
+ bool mDirty;
+ };
+
+ template <class TShaderConstants>
+ void applyDriverConstantsIfNeeded(TShaderConstants *appliedConstants,
+ const TShaderConstants &constants,
+ SamplerMetadataD3D11 *samplerMetadata,
+ size_t samplerMetadataReferencedBytes,
+ ID3D11Buffer *driverConstantBuffer);
+
+ gl::Error copyImageInternal(const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ RenderTargetD3D *destRenderTarget);
+
+ HMODULE mD3d11Module;
+ HMODULE mDxgiModule;
+ HMODULE mDCompModule;
+ std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
+ D3D_DRIVER_TYPE mRequestedDriverType;
+ bool mCreatedWithDeviceEXT;
+ DeviceD3D *mEGLDevice;
+
+ HLSLCompiler mCompiler;
+
+ egl::Error initializeD3DDevice();
+ void initializeDevice();
+ void releaseDeviceResources();
+ void release();
+
+ d3d11::ANGLED3D11DeviceType getDeviceType() const;
+
+ RenderStateCache mStateCache;
+
+ // Currently applied sampler states
+ std::vector<bool> mForceSetVertexSamplerStates;
+ std::vector<gl::SamplerState> mCurVertexSamplerStates;
+
+ std::vector<bool> mForceSetPixelSamplerStates;
+ std::vector<gl::SamplerState> mCurPixelSamplerStates;
+
+ StateManager11 mStateManager;
+
+ // Currently applied primitive topology
+ D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology;
+
+ // Currently applied index buffer
+ ID3D11Buffer *mAppliedIB;
+ DXGI_FORMAT mAppliedIBFormat;
+ unsigned int mAppliedIBOffset;
+ bool mAppliedIBChanged;
+
+ // Currently applied transform feedback buffers
+ uintptr_t mAppliedTFObject;
+
+ // Currently applied shaders
+ uintptr_t mAppliedVertexShader;
+ uintptr_t mAppliedGeometryShader;
+ uintptr_t mAppliedPixelShader;
+
+ dx_VertexConstants11 mAppliedVertexConstants;
+ ID3D11Buffer *mDriverConstantBufferVS;
+ SamplerMetadataD3D11 mSamplerMetadataVS;
+ ID3D11Buffer *mCurrentVertexConstantBuffer;
+ unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
+ GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
+ GLsizeiptr mCurrentConstantBufferVSSize[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
+
+ dx_PixelConstants11 mAppliedPixelConstants;
+ ID3D11Buffer *mDriverConstantBufferPS;
+ SamplerMetadataD3D11 mSamplerMetadataPS;
+ ID3D11Buffer *mCurrentPixelConstantBuffer;
+ unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
+ GLintptr mCurrentConstantBufferPSOffset[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
+ GLsizeiptr mCurrentConstantBufferPSSize[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
+
+ ID3D11Buffer *mCurrentGeometryConstantBuffer;
+
+ // Vertex, index and input layouts
+ VertexDataManager *mVertexDataManager;
+ IndexDataManager *mIndexDataManager;
+ InputLayoutCache mInputLayoutCache;
+
+ 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
+ ID3D11Query *mSyncQuery;
+
+ // Created objects state tracking
+ std::set<const Buffer11*> mAliveBuffers;
+
+ double mLastHistogramUpdateTime;
+
+ ID3D11Device *mDevice;
+ Renderer11DeviceCaps mRenderer11DeviceCaps;
+ ID3D11DeviceContext *mDeviceContext;
+ ID3D11DeviceContext1 *mDeviceContext1;
+ IDXGIAdapter *mDxgiAdapter;
+ DXGI_ADAPTER_DESC mAdapterDescription;
+ char mDescription[128];
+ IDXGIFactory *mDxgiFactory;
+ ID3D11Debug *mDebug;
+
+ std::vector<GLuint> mScratchIndexDataBuffer;
+
+ MemoryBuffer mScratchMemoryBuffer;
+ unsigned int mScratchMemoryBufferResetCounter;
+
+ gl::DebugAnnotator *mAnnotator;
+
+ mutable Optional<bool> mSupportsShareHandles;
+};
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp
new file mode 100755
index 000000000..e20b161ef
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp
@@ -0,0 +1,97 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader
+// executable implementation details.
+
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable)
+ : ShaderExecutableD3D(function, length)
+{
+ mPixelExecutable = executable;
+ mVertexExecutable = NULL;
+ mGeometryExecutable = NULL;
+ mStreamOutExecutable = NULL;
+}
+
+ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut)
+ : ShaderExecutableD3D(function, length)
+{
+ mVertexExecutable = executable;
+ mPixelExecutable = NULL;
+ mGeometryExecutable = NULL;
+ mStreamOutExecutable = streamOut;
+}
+
+ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable)
+ : ShaderExecutableD3D(function, length)
+{
+ mGeometryExecutable = executable;
+ mVertexExecutable = NULL;
+ mPixelExecutable = NULL;
+ mStreamOutExecutable = NULL;
+}
+
+ShaderExecutable11::~ShaderExecutable11()
+{
+ SafeRelease(mVertexExecutable);
+ SafeRelease(mPixelExecutable);
+ SafeRelease(mGeometryExecutable);
+ SafeRelease(mStreamOutExecutable);
+}
+
+ID3D11VertexShader *ShaderExecutable11::getVertexShader() const
+{
+ return mVertexExecutable;
+}
+
+ID3D11PixelShader *ShaderExecutable11::getPixelShader() const
+{
+ return mPixelExecutable;
+}
+
+ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const
+{
+ return mGeometryExecutable;
+}
+
+ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const
+{
+ return mStreamOutExecutable;
+}
+
+UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize)
+ : UniformStorageD3D(initialSize),
+ mConstantBuffer(NULL)
+{
+ ID3D11Device *d3d11Device = renderer->getDevice();
+
+ if (initialSize > 0)
+ {
+ D3D11_BUFFER_DESC constantBufferDescription = {0};
+ constantBufferDescription.ByteWidth = static_cast<unsigned int>(initialSize);
+ constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC;
+ constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ constantBufferDescription.MiscFlags = 0;
+ constantBufferDescription.StructureByteStride = 0;
+
+ HRESULT result = d3d11Device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer);
+ ASSERT(SUCCEEDED(result));
+ }
+}
+
+UniformStorage11::~UniformStorage11()
+{
+ SafeRelease(mConstantBuffer);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h
new file mode 100755
index 000000000..379f39fe5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h
@@ -0,0 +1,55 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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"
+
+namespace rx
+{
+class Renderer11;
+class UniformStorage11;
+
+class ShaderExecutable11 : public ShaderExecutableD3D
+{
+ public:
+ ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable);
+ ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut);
+ ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable);
+
+ virtual ~ShaderExecutable11();
+
+ ID3D11PixelShader *getPixelShader() const;
+ ID3D11VertexShader *getVertexShader() const;
+ ID3D11GeometryShader *getGeometryShader() const;
+ ID3D11GeometryShader *getStreamOutShader() const;
+
+ private:
+ ID3D11PixelShader *mPixelExecutable;
+ ID3D11VertexShader *mVertexExecutable;
+ ID3D11GeometryShader *mGeometryExecutable;
+ ID3D11GeometryShader *mStreamOutExecutable;
+};
+
+class UniformStorage11 : public UniformStorageD3D
+{
+ public:
+ UniformStorage11(Renderer11 *renderer, size_t initialSize);
+ virtual ~UniformStorage11();
+
+ ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; }
+
+ private:
+ ID3D11Buffer *mConstantBuffer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
new file mode 100755
index 000000000..0e28c8c18
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -0,0 +1,1120 @@
+//
+// Copyright (c) 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/BitSetIterator.h"
+#include "common/utilities.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+
+namespace rx
+{
+
+namespace
+{
+bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
+{
+ unsigned mipLevel = index.mipIndex;
+ GLint layerIndex = index.layerIndex;
+ GLenum type = index.type;
+
+ 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.mipIndex;
+ unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex;
+
+ return type == GL_TEXTURE_2D &&
+ gl::RangeUI(mipMin, mipMax)
+ .intersects(gl::RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip));
+ }
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+ {
+ 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 (type == GL_TEXTURE_2D_ARRAY || gl::IsCubeMapTextureTarget(type)) &&
+ 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 gl::IsCubeMapTextureTarget(type) &&
+ 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 type == GL_TEXTURE_3D && desc.Texture3D.MostDetailedMip <= mipLevel &&
+ mipLevel < maxSrvMip;
+ }
+ default:
+ // We only handle the cases corresponding to valid image indexes
+ UNIMPLEMENTED();
+ }
+
+ return false;
+}
+
+// Does *not* increment the resource ref count!!
+ID3D11Resource *GetViewResource(ID3D11View *view)
+{
+ ID3D11Resource *resource = NULL;
+ ASSERT(view);
+ view->GetResource(&resource);
+ resource->Release();
+ return resource;
+}
+
+} // anonymous namespace
+
+void StateManager11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv)
+{
+ ASSERT(resourceIndex < mCurrentSRVs.size());
+ SRVRecord *record = &mCurrentSRVs[resourceIndex];
+
+ record->srv = reinterpret_cast<uintptr_t>(srv);
+ if (srv)
+ {
+ record->resource = reinterpret_cast<uintptr_t>(GetViewResource(srv));
+ srv->GetDesc(&record->desc);
+ mHighestUsedSRV = std::max(resourceIndex + 1, mHighestUsedSRV);
+ }
+ else
+ {
+ record->resource = 0;
+
+ if (resourceIndex + 1 == mHighestUsedSRV)
+ {
+ do
+ {
+ --mHighestUsedSRV;
+ } while (mHighestUsedSRV > 0 && mCurrentSRVs[mHighestUsedSRV].srv == 0);
+ }
+ }
+}
+
+void StateManager11::SRVCache::clear()
+{
+ if (mCurrentSRVs.empty())
+ {
+ return;
+ }
+
+ memset(&mCurrentSRVs[0], 0, sizeof(SRVRecord) * mCurrentSRVs.size());
+ mHighestUsedSRV = 0;
+}
+
+static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
+ GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED_EXT,
+ GL_COMMANDS_COMPLETED_CHROMIUM};
+
+StateManager11::StateManager11(Renderer11 *renderer)
+ : mRenderer(renderer),
+ mBlendStateIsDirty(false),
+ mCurBlendColor(0, 0, 0, 0),
+ mCurSampleMask(0),
+ mDepthStencilStateIsDirty(false),
+ mCurStencilRef(0),
+ mCurStencilBackRef(0),
+ mCurStencilSize(0),
+ mRasterizerStateIsDirty(false),
+ mScissorStateIsDirty(false),
+ mCurScissorEnabled(false),
+ mCurScissorRect(),
+ mViewportStateIsDirty(false),
+ mCurViewport(),
+ mCurNear(0.0f),
+ mCurFar(0.0f),
+ mViewportBounds(),
+ mRenderTargetIsDirty(false),
+ mDirtyCurrentValueAttribs(),
+ mCurrentValueAttribs()
+{
+ mCurBlendState.blend = false;
+ mCurBlendState.sourceBlendRGB = GL_ONE;
+ mCurBlendState.destBlendRGB = GL_ZERO;
+ mCurBlendState.sourceBlendAlpha = GL_ONE;
+ mCurBlendState.destBlendAlpha = GL_ZERO;
+ mCurBlendState.blendEquationRGB = GL_FUNC_ADD;
+ mCurBlendState.blendEquationAlpha = GL_FUNC_ADD;
+ mCurBlendState.colorMaskRed = true;
+ mCurBlendState.colorMaskBlue = true;
+ mCurBlendState.colorMaskGreen = true;
+ mCurBlendState.colorMaskAlpha = true;
+ mCurBlendState.sampleAlphaToCoverage = false;
+ mCurBlendState.dither = false;
+
+ 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_BACK;
+ mCurRasterState.frontFace = GL_CCW;
+ mCurRasterState.polygonOffsetFill = false;
+ mCurRasterState.polygonOffsetFactor = 0.0f;
+ mCurRasterState.polygonOffsetUnits = 0.0f;
+ mCurRasterState.pointDrawMode = false;
+ mCurRasterState.multiSample = false;
+
+ // Initially all current value attributes must be updated on first use.
+ mDirtyCurrentValueAttribs.flip();
+}
+
+StateManager11::~StateManager11()
+{
+}
+
+void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
+ unsigned int stencilSize)
+{
+ if (!depthStencilInitialized || stencilSize != mCurStencilSize)
+ {
+ mCurStencilSize = stencilSize;
+ mDepthStencilStateIsDirty = true;
+ }
+}
+
+void StateManager11::setViewportBounds(const int width, const int height)
+{
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 &&
+ (mViewportBounds.width != width || mViewportBounds.height != height))
+ {
+ mViewportBounds = gl::Extents(width, height, 1);
+ mViewportStateIsDirty = true;
+ }
+}
+
+void StateManager11::updatePresentPath(bool presentPathFastActive,
+ const gl::FramebufferAttachment *framebufferAttachment)
+{
+ const int colorBufferHeight =
+ framebufferAttachment ? framebufferAttachment->getSize().height : 0;
+
+ if ((mCurPresentPathFastEnabled != presentPathFastActive) ||
+ (presentPathFastActive && (colorBufferHeight != mCurPresentPathFastColorBufferHeight)))
+ {
+ mCurPresentPathFastEnabled = presentPathFastActive;
+ mCurPresentPathFastColorBufferHeight = colorBufferHeight;
+ mViewportStateIsDirty = true; // Viewport may need to be vertically inverted
+ mScissorStateIsDirty = true; // Scissor rect may need to be vertically inverted
+ mRasterizerStateIsDirty = true; // Cull Mode may need to be inverted
+ }
+}
+
+void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
+{
+ if (!dirtyBits.any())
+ {
+ return;
+ }
+
+ for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
+ {
+ switch (dirtyBit)
+ {
+ case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
+ {
+ const gl::BlendState &blendState = state.getBlendState();
+ if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB ||
+ blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha)
+ {
+ mBlendStateIsDirty = true;
+ }
+ 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)
+ {
+ mBlendStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_BLEND_ENABLED:
+ if (state.getBlendState().blend != mCurBlendState.blend)
+ {
+ mBlendStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
+ if (state.getBlendState().sampleAlphaToCoverage !=
+ mCurBlendState.sampleAlphaToCoverage)
+ {
+ mBlendStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_DITHER_ENABLED:
+ if (state.getBlendState().dither != mCurBlendState.dither)
+ {
+ mBlendStateIsDirty = true;
+ }
+ 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)
+ {
+ mBlendStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_BLEND_COLOR:
+ if (state.getBlendColor() != mCurBlendColor)
+ {
+ mBlendStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_MASK:
+ if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
+ if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_FUNC:
+ if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
+ if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
+ {
+ const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
+ if (depthStencil.stencilFunc != mCurDepthStencilState.stencilFunc ||
+ depthStencil.stencilMask != mCurDepthStencilState.stencilMask ||
+ state.getStencilRef() != mCurStencilRef)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
+ {
+ const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
+ if (depthStencil.stencilBackFunc != mCurDepthStencilState.stencilBackFunc ||
+ depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask ||
+ state.getStencilBackRef() != mCurStencilBackRef)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+ if (state.getDepthStencilState().stencilWritemask !=
+ mCurDepthStencilState.stencilWritemask)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+ if (state.getDepthStencilState().stencilBackWritemask !=
+ mCurDepthStencilState.stencilBackWritemask)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
+ {
+ const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
+ if (depthStencil.stencilFail != mCurDepthStencilState.stencilFail ||
+ depthStencil.stencilPassDepthFail !=
+ mCurDepthStencilState.stencilPassDepthFail ||
+ depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
+ {
+ const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
+ if (depthStencil.stencilBackFail != mCurDepthStencilState.stencilBackFail ||
+ depthStencil.stencilBackPassDepthFail !=
+ mCurDepthStencilState.stencilBackPassDepthFail ||
+ depthStencil.stencilBackPassDepthPass !=
+ mCurDepthStencilState.stencilBackPassDepthPass)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
+ if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
+ {
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_CULL_FACE:
+ if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
+ {
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_FRONT_FACE:
+ if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
+ {
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
+ if (state.getRasterizerState().polygonOffsetFill !=
+ mCurRasterState.polygonOffsetFill)
+ {
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_POLYGON_OFFSET:
+ {
+ const gl::RasterizerState &rasterState = state.getRasterizerState();
+ if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
+ rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
+ {
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
+ if (state.getRasterizerState().rasterizerDiscard !=
+ mCurRasterState.rasterizerDiscard)
+ {
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_SCISSOR:
+ if (state.getScissor() != mCurScissorRect)
+ {
+ mScissorStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
+ if (state.isScissorTestEnabled() != mCurScissorEnabled)
+ {
+ mScissorStateIsDirty = true;
+ // Rasterizer state update needs mCurScissorsEnabled and updates when it changes
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_RANGE:
+ if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar)
+ {
+ mViewportStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_VIEWPORT:
+ if (state.getViewport() != mCurViewport)
+ {
+ mViewportStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
+ mRenderTargetIsDirty = true;
+ break;
+ default:
+ if (dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 &&
+ dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX)
+ {
+ size_t attribIndex =
+ static_cast<size_t>(dirtyBit - gl::State::DIRTY_BIT_CURRENT_VALUE_0);
+ mDirtyCurrentValueAttribs.set(attribIndex);
+ }
+ break;
+ }
+ }
+}
+
+gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer,
+ const gl::BlendState &blendState,
+ const gl::ColorF &blendColor,
+ unsigned int sampleMask)
+{
+ if (!mBlendStateIsDirty && sampleMask == mCurSampleMask)
+ {
+ return gl::NoError();
+ }
+
+ ID3D11BlendState *dxBlendState = nullptr;
+ ANGLE_TRY(mRenderer->getStateCache().getBlendState(framebuffer, blendState, &dxBlendState));
+
+ ASSERT(dxBlendState != nullptr);
+
+ float blendColors[4] = {0.0f};
+ 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)
+ {
+ blendColors[0] = blendColor.red;
+ blendColors[1] = blendColor.green;
+ blendColors[2] = blendColor.blue;
+ blendColors[3] = blendColor.alpha;
+ }
+ else
+ {
+ blendColors[0] = blendColor.alpha;
+ blendColors[1] = blendColor.alpha;
+ blendColors[2] = blendColor.alpha;
+ blendColors[3] = blendColor.alpha;
+ }
+
+ mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState, blendColors, sampleMask);
+
+ mCurBlendState = blendState;
+ mCurBlendColor = blendColor;
+ mCurSampleMask = sampleMask;
+
+ mBlendStateIsDirty = false;
+
+ return gl::NoError();
+}
+
+gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
+{
+ const auto &fbo = *glState.getDrawFramebuffer();
+
+ // 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());
+
+ // CurDisableDepth/Stencil are reset automatically after we call forceSetDepthStencilState.
+ if (!mDepthStencilStateIsDirty && mCurDisableDepth.valid() &&
+ disableDepth == mCurDisableDepth.value() && mCurDisableStencil.valid() &&
+ disableStencil == mCurDisableStencil.value())
+ {
+ return gl::NoError();
+ }
+
+ const auto &depthStencilState = glState.getDepthStencilState();
+ int stencilRef = glState.getStencilRef();
+ int stencilBackRef = glState.getStencilBackRef();
+
+ // get the maximum size of the stencil ref
+ unsigned int maxStencil = 0;
+ if (depthStencilState.stencilTest && mCurStencilSize > 0)
+ {
+ maxStencil = (1 << mCurStencilSize) - 1;
+ }
+ ASSERT((depthStencilState.stencilWritemask & maxStencil) ==
+ (depthStencilState.stencilBackWritemask & maxStencil));
+ ASSERT(stencilRef == stencilBackRef);
+ ASSERT((depthStencilState.stencilMask & maxStencil) ==
+ (depthStencilState.stencilBackMask & maxStencil));
+
+ ID3D11DepthStencilState *dxDepthStencilState = NULL;
+ ANGLE_TRY(mRenderer->getStateCache().getDepthStencilState(
+ depthStencilState, disableDepth, disableStencil, &dxDepthStencilState));
+
+ ASSERT(dxDepthStencilState);
+
+ // 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 = std::min<UINT>(stencilRef, 0xFFu);
+
+ mRenderer->getDeviceContext()->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
+
+ mCurDepthStencilState = depthStencilState;
+ mCurStencilRef = stencilRef;
+ mCurStencilBackRef = stencilBackRef;
+ mCurDisableDepth = disableDepth;
+ mCurDisableStencil = disableStencil;
+
+ mDepthStencilStateIsDirty = false;
+
+ return gl::NoError();
+}
+
+gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterState)
+{
+ // TODO: Remove pointDrawMode and multiSample from gl::RasterizerState.
+ if (!mRasterizerStateIsDirty && rasterState.pointDrawMode == mCurRasterState.pointDrawMode &&
+ rasterState.multiSample == mCurRasterState.multiSample)
+ {
+ return gl::NoError();
+ }
+
+ 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->getStateCache().getRasterizerState(
+ modifiedRasterState, mCurScissorEnabled, &dxRasterState));
+ }
+ else
+ {
+ ANGLE_TRY(mRenderer->getStateCache().getRasterizerState(rasterState, mCurScissorEnabled,
+ &dxRasterState));
+ }
+
+ mRenderer->getDeviceContext()->RSSetState(dxRasterState);
+
+ mCurRasterState = rasterState;
+ mRasterizerStateIsDirty = false;
+
+ return gl::NoError();
+}
+
+void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
+{
+ if (!mScissorStateIsDirty)
+ return;
+
+ int modifiedScissorY = scissor.y;
+ if (mCurPresentPathFastEnabled)
+ {
+ modifiedScissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y;
+ }
+
+ if (enabled)
+ {
+ D3D11_RECT rect;
+ rect.left = std::max(0, scissor.x);
+ rect.top = std::max(0, modifiedScissorY);
+ rect.right = scissor.x + std::max(0, scissor.width);
+ rect.bottom = modifiedScissorY + std::max(0, scissor.height);
+
+ mRenderer->getDeviceContext()->RSSetScissorRects(1, &rect);
+ }
+
+ mCurScissorRect = scissor;
+ mCurScissorEnabled = enabled;
+ mScissorStateIsDirty = false;
+}
+
+void StateManager11::setViewport(const gl::Caps *caps,
+ const gl::Rectangle &viewport,
+ float zNear,
+ float zFar)
+{
+ if (!mViewportStateIsDirty)
+ return;
+
+ float actualZNear = gl::clamp01(zNear);
+ float actualZFar = gl::clamp01(zFar);
+
+ int dxMaxViewportBoundsX = static_cast<int>(caps->maxViewportWidth);
+ int dxMaxViewportBoundsY = static_cast<int>(caps->maxViewportHeight);
+ int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
+ int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
+
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_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;
+ }
+
+ int dxViewportTopLeftX = gl::clamp(viewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
+ int dxViewportTopLeftY = gl::clamp(viewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
+ int dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
+ int dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
+
+ D3D11_VIEWPORT dxViewport;
+ dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
+
+ if (mCurPresentPathFastEnabled)
+ {
+ // 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);
+ }
+
+ 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;
+
+ // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
+ // using viewAdjust (like the D3D9 renderer).
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ mVertexConstants.viewAdjust[0] = static_cast<float>((viewport.width - dxViewportWidth) +
+ 2 * (viewport.x - dxViewportTopLeftX)) /
+ dxViewport.Width;
+ mVertexConstants.viewAdjust[1] = static_cast<float>((viewport.height - dxViewportHeight) +
+ 2 * (viewport.y - dxViewportTopLeftY)) /
+ dxViewport.Height;
+ mVertexConstants.viewAdjust[2] = static_cast<float>(viewport.width) / dxViewport.Width;
+ mVertexConstants.viewAdjust[3] = static_cast<float>(viewport.height) / dxViewport.Height;
+ }
+
+ mPixelConstants.viewCoords[0] = viewport.width * 0.5f;
+ mPixelConstants.viewCoords[1] = viewport.height * 0.5f;
+ mPixelConstants.viewCoords[2] = viewport.x + (viewport.width * 0.5f);
+ mPixelConstants.viewCoords[3] = viewport.y + (viewport.height * 0.5f);
+
+ // Instanced pointsprite emulation requires ViewCoords to be defined in the
+ // the vertex shader.
+ mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0];
+ mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1];
+ mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2];
+ mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3];
+
+ mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
+ mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
+
+ mVertexConstants.depthRange[0] = actualZNear;
+ mVertexConstants.depthRange[1] = actualZFar;
+ mVertexConstants.depthRange[2] = actualZFar - actualZNear;
+
+ mPixelConstants.depthRange[0] = actualZNear;
+ mPixelConstants.depthRange[1] = actualZFar;
+ mPixelConstants.depthRange[2] = actualZFar - actualZNear;
+
+ mPixelConstants.viewScale[0] = 1.0f;
+ mPixelConstants.viewScale[1] = mCurPresentPathFastEnabled ? 1.0f : -1.0f;
+ mPixelConstants.viewScale[2] = 1.0f;
+ mPixelConstants.viewScale[3] = 1.0f;
+
+ mVertexConstants.viewScale[0] = mPixelConstants.viewScale[0];
+ mVertexConstants.viewScale[1] = mPixelConstants.viewScale[1];
+ mVertexConstants.viewScale[2] = mPixelConstants.viewScale[2];
+ mVertexConstants.viewScale[3] = mPixelConstants.viewScale[3];
+
+ mViewportStateIsDirty = false;
+}
+
+void StateManager11::invalidateRenderTarget()
+{
+ mRenderTargetIsDirty = true;
+}
+
+void StateManager11::invalidateBoundViews()
+{
+ mCurVertexSRVs.clear();
+ mCurPixelSRVs.clear();
+
+ invalidateRenderTarget();
+}
+
+void StateManager11::invalidateEverything()
+{
+ mBlendStateIsDirty = true;
+ mDepthStencilStateIsDirty = true;
+ mRasterizerStateIsDirty = true;
+ mScissorStateIsDirty = true;
+ mViewportStateIsDirty = true;
+
+ // We reset the current SRV data because it might not be in sync with D3D's state
+ // anymore. For example when a currently used SRV is used as an RTV, D3D silently
+ // remove it from its state.
+ invalidateBoundViews();
+}
+
+void StateManager11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTarget,
+ ID3D11DepthStencilView *depthStencil)
+{
+ mRenderer->getDeviceContext()->OMSetRenderTargets(1, &renderTarget, depthStencil);
+ mRenderTargetIsDirty = true;
+}
+
+void StateManager11::setOneTimeRenderTargets(
+ const std::vector<ID3D11RenderTargetView *> &renderTargets,
+ ID3D11DepthStencilView *depthStencil)
+{
+ UINT count = static_cast<UINT>(renderTargets.size());
+ auto renderTargetPointer = (!renderTargets.empty() ? renderTargets.data() : nullptr);
+
+ mRenderer->getDeviceContext()->OMSetRenderTargets(count, renderTargetPointer, depthStencil);
+ mRenderTargetIsDirty = true;
+}
+
+void StateManager11::onBeginQuery(Query11 *query)
+{
+ mCurrentQueries.insert(query);
+}
+
+void StateManager11::onDeleteQueryObject(Query11 *query)
+{
+ mCurrentQueries.erase(query);
+}
+
+gl::Error StateManager11::onMakeCurrent(const gl::ContextState &data)
+{
+ const gl::State &state = data.getState();
+
+ for (Query11 *query : mCurrentQueries)
+ {
+ query->pause();
+ }
+ mCurrentQueries.clear();
+
+ for (GLenum queryType : QueryTypes)
+ {
+ gl::Query *query = state.getActiveQuery(queryType);
+ if (query != nullptr)
+ {
+ Query11 *query11 = GetImplAs<Query11>(query);
+ query11->resume();
+ mCurrentQueries.insert(query11);
+ }
+ }
+
+ return gl::NoError();
+}
+
+void StateManager11::setShaderResource(gl::SamplerType shaderType,
+ UINT resourceSlot,
+ ID3D11ShaderResourceView *srv)
+{
+ auto &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+
+ ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size());
+ const SRVRecord &record = currentSRVs[resourceSlot];
+
+ if (record.srv != reinterpret_cast<uintptr_t>(srv))
+ {
+ auto deviceContext = mRenderer->getDeviceContext();
+ if (shaderType == gl::SAMPLER_VERTEX)
+ {
+ deviceContext->VSSetShaderResources(resourceSlot, 1, &srv);
+ }
+ else
+ {
+ deviceContext->PSSetShaderResources(resourceSlot, 1, &srv);
+ }
+
+ currentSRVs.update(resourceSlot, srv);
+ }
+}
+
+gl::Error StateManager11::clearTextures(gl::SamplerType samplerType,
+ size_t rangeStart,
+ size_t rangeEnd)
+{
+ if (rangeStart == rangeEnd)
+ {
+ return gl::NoError();
+ }
+
+ auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+
+ gl::Range<size_t> clearRange(rangeStart, rangeStart);
+ clearRange.extend(std::min(rangeEnd, currentSRVs.highestUsed()));
+
+ if (clearRange.empty())
+ {
+ return gl::NoError();
+ }
+
+ auto deviceContext = mRenderer->getDeviceContext();
+ if (samplerType == gl::SAMPLER_VERTEX)
+ {
+ deviceContext->VSSetShaderResources(static_cast<unsigned int>(rangeStart),
+ static_cast<unsigned int>(rangeEnd - rangeStart),
+ &mNullSRVs[0]);
+ }
+ else
+ {
+ deviceContext->PSSetShaderResources(static_cast<unsigned int>(rangeStart),
+ static_cast<unsigned int>(rangeEnd - rangeStart),
+ &mNullSRVs[0]);
+ }
+
+ for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; ++samplerIndex)
+ {
+ currentSRVs.update(samplerIndex, nullptr);
+ }
+
+ return gl::NoError();
+}
+
+void StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType,
+ uintptr_t resource,
+ const gl::ImageIndex &index)
+{
+ auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+
+ for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex)
+ {
+ auto &record = currentSRVs[resourceIndex];
+
+ if (record.srv && record.resource == resource &&
+ ImageIndexConflictsWithSRV(index, record.desc))
+ {
+ setShaderResource(samplerType, static_cast<UINT>(resourceIndex), NULL);
+ }
+ }
+}
+
+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::SAMPLER_VERTEX, resourcePtr, index);
+ unsetConflictingSRVs(gl::SAMPLER_PIXEL, resourcePtr, index);
+ }
+}
+
+void StateManager11::initialize(const gl::Caps &caps)
+{
+ mCurVertexSRVs.initialize(caps.maxVertexTextureImageUnits);
+ mCurPixelSRVs.initialize(caps.maxTextureImageUnits);
+
+ // Initialize cached NULL SRV block
+ mNullSRVs.resize(caps.maxTextureImageUnits, nullptr);
+
+ mCurrentValueAttribs.resize(caps.maxVertexAttributes);
+}
+
+void StateManager11::deinitialize()
+{
+ mCurrentValueAttribs.clear();
+}
+
+gl::Error StateManager11::syncFramebuffer(gl::Framebuffer *framebuffer)
+{
+ Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
+ ANGLE_TRY(framebuffer11->markAttachmentsDirty());
+
+ if (framebuffer11->hasAnyInternalDirtyBit())
+ {
+ ASSERT(framebuffer->id() != 0);
+ framebuffer11->syncInternalState();
+ }
+
+ if (!mRenderTargetIsDirty)
+ {
+ return gl::NoError();
+ }
+
+ mRenderTargetIsDirty = false;
+
+ // 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 (framebuffer->id() == 0)
+ {
+ ASSERT(!framebuffer11->hasAnyInternalDirtyBit());
+ const gl::Extents &size = framebuffer->getFirstColorbuffer()->getSize();
+ if (size.width == 0 || size.height == 0)
+ {
+ return gl::NoError();
+ }
+ }
+
+ // Get the color render buffer and serial
+ // Also extract the render target dimensions and view
+ unsigned int renderTargetWidth = 0;
+ unsigned int renderTargetHeight = 0;
+ RTVArray framebufferRTVs;
+ bool missingColorRenderTarget = true;
+
+ framebufferRTVs.fill(nullptr);
+
+ const auto &colorRTs = framebuffer11->getCachedColorRenderTargets();
+
+ size_t appliedRTIndex = 0;
+ bool skipInactiveRTs = mRenderer->getWorkarounds().mrtPerfWorkaround;
+ const auto &drawStates = framebuffer->getDrawBufferStates();
+
+ 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))
+ {
+ continue;
+ }
+
+ if (renderTarget)
+ {
+ framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView();
+ ASSERT(framebufferRTVs[appliedRTIndex]);
+
+ if (missingColorRenderTarget)
+ {
+ renderTargetWidth = renderTarget->getWidth();
+ renderTargetHeight = renderTarget->getHeight();
+ missingColorRenderTarget = false;
+ }
+ }
+
+ // Unset conflicting texture SRVs
+ const auto *attachment = framebuffer->getColorbuffer(rtIndex);
+ ASSERT(attachment);
+ unsetConflictingAttachmentResources(attachment, renderTarget->getTexture());
+
+ appliedRTIndex++;
+ }
+
+ // Get the depth stencil buffers
+ ID3D11DepthStencilView *framebufferDSV = nullptr;
+ const auto *depthStencilRenderTarget = framebuffer11->getCachedDepthStencilRenderTarget();
+ if (depthStencilRenderTarget)
+ {
+ framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
+ ASSERT(framebufferDSV);
+
+ // If there is no render buffer, the width, height and format values come from
+ // the depth stencil
+ if (missingColorRenderTarget)
+ {
+ renderTargetWidth = depthStencilRenderTarget->getWidth();
+ renderTargetHeight = depthStencilRenderTarget->getHeight();
+ }
+
+ // Unset conflicting texture SRVs
+ const auto *attachment = framebuffer->getDepthOrStencilbuffer();
+ ASSERT(attachment);
+ unsetConflictingAttachmentResources(attachment, depthStencilRenderTarget->getTexture());
+ }
+
+ // TODO(jmadill): Use context caps?
+ UINT drawBuffers = mRenderer->getNativeCaps().maxDrawBuffers;
+
+ // Apply the render target and depth stencil
+ mRenderer->getDeviceContext()->OMSetRenderTargets(drawBuffers, framebufferRTVs.data(),
+ framebufferDSV);
+
+ // The D3D11 blend state is heavily dependent on the current render target.
+ mBlendStateIsDirty = true;
+
+ setViewportBounds(renderTargetWidth, renderTargetHeight);
+
+ return gl::NoError();
+}
+
+gl::Error StateManager11::updateCurrentValueAttribs(const gl::State &state,
+ VertexDataManager *vertexDataManager)
+{
+ const auto &activeAttribsMask = state.getProgram()->getActiveAttribLocationsMask();
+ const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);
+ const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
+
+ for (auto attribIndex : angle::IterateBitSet(dirtyActiveAttribs))
+ {
+ if (vertexAttributes[attribIndex].enabled)
+ continue;
+
+ mDirtyCurrentValueAttribs.reset(attribIndex);
+
+ const auto &currentValue =
+ state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
+ auto currentValueAttrib = &mCurrentValueAttribs[attribIndex];
+ currentValueAttrib->currentValueType = currentValue.Type;
+ currentValueAttrib->attribute = &vertexAttributes[attribIndex];
+
+ ANGLE_TRY(vertexDataManager->storeCurrentValue(currentValue, currentValueAttrib,
+ static_cast<size_t>(attribIndex)));
+ }
+
+ return gl::NoError();
+}
+
+const std::vector<TranslatedAttribute> &StateManager11::getCurrentValueAttribs() const
+{
+ return mCurrentValueAttribs;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
new file mode 100755
index 000000000..771eb439f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
@@ -0,0 +1,202 @@
+//
+// Copyright (c) 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/angletypes.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/State.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/Query11.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+
+struct RenderTargetDesc;
+struct Renderer11DeviceCaps;
+
+struct dx_VertexConstants11
+{
+ float depthRange[4];
+ float viewAdjust[4];
+ float viewCoords[4];
+ float viewScale[4];
+};
+
+struct dx_PixelConstants11
+{
+ float depthRange[4];
+ float viewCoords[4];
+ float depthFront[4];
+ float viewScale[4];
+};
+
+class StateManager11 final : angle::NonCopyable
+{
+ public:
+ StateManager11(Renderer11 *renderer);
+ ~StateManager11();
+
+ void initialize(const gl::Caps &caps);
+ void deinitialize();
+ void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
+
+ gl::Error setBlendState(const gl::Framebuffer *framebuffer,
+ const gl::BlendState &blendState,
+ const gl::ColorF &blendColor,
+ unsigned int sampleMask);
+
+ gl::Error setDepthStencilState(const gl::State &glState);
+
+ gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
+
+ void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+
+ void setViewport(const gl::Caps *caps, const gl::Rectangle &viewport, float zNear, float zFar);
+
+ void updatePresentPath(bool presentPathFastActive,
+ const gl::FramebufferAttachment *framebufferAttachment);
+
+ const dx_VertexConstants11 &getVertexConstants() const { return mVertexConstants; }
+ const dx_PixelConstants11 &getPixelConstants() const { return mPixelConstants; }
+
+ void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
+
+ void setShaderResource(gl::SamplerType shaderType,
+ UINT resourceSlot,
+ ID3D11ShaderResourceView *srv);
+ gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd);
+
+ gl::Error syncFramebuffer(gl::Framebuffer *framebuffer);
+
+ void invalidateRenderTarget();
+ void invalidateBoundViews();
+ void invalidateEverything();
+
+ void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTarget,
+ ID3D11DepthStencilView *depthStencil);
+ void setOneTimeRenderTargets(const std::vector<ID3D11RenderTargetView *> &renderTargets,
+ ID3D11DepthStencilView *depthStencil);
+
+ void onBeginQuery(Query11 *query);
+ void onDeleteQueryObject(Query11 *query);
+ gl::Error onMakeCurrent(const gl::ContextState &data);
+
+ gl::Error updateCurrentValueAttribs(const gl::State &state,
+ VertexDataManager *vertexDataManager);
+
+ const std::vector<TranslatedAttribute> &getCurrentValueAttribs() const;
+
+ private:
+ void setViewportBounds(const int width, const int height);
+ void unsetConflictingSRVs(gl::SamplerType shaderType,
+ uintptr_t resource,
+ const gl::ImageIndex &index);
+ void unsetConflictingAttachmentResources(const gl::FramebufferAttachment *attachment,
+ ID3D11Resource *resource);
+
+ Renderer11 *mRenderer;
+
+ // Blend State
+ bool mBlendStateIsDirty;
+ // TODO(dianx) temporary representation of a dirty bit. once we move enough states in,
+ // try experimenting with dirty bit instead of a bool
+ gl::BlendState mCurBlendState;
+ gl::ColorF mCurBlendColor;
+ unsigned int mCurSampleMask;
+
+ // Currently applied depth stencil state
+ bool mDepthStencilStateIsDirty;
+ gl::DepthStencilState mCurDepthStencilState;
+ int mCurStencilRef;
+ int mCurStencilBackRef;
+ unsigned int mCurStencilSize;
+ Optional<bool> mCurDisableDepth;
+ Optional<bool> mCurDisableStencil;
+
+ // Currently applied rasterizer state
+ bool mRasterizerStateIsDirty;
+ gl::RasterizerState mCurRasterState;
+
+ // Currently applied scissor rectangle state
+ bool mScissorStateIsDirty;
+ bool mCurScissorEnabled;
+ gl::Rectangle mCurScissorRect;
+
+ // Currently applied viewport state
+ bool mViewportStateIsDirty;
+ gl::Rectangle mCurViewport;
+ float mCurNear;
+ float mCurFar;
+
+ // Things needed in viewport state
+ dx_VertexConstants11 mVertexConstants;
+ dx_PixelConstants11 mPixelConstants;
+
+ // Render target variables
+ gl::Extents mViewportBounds;
+
+ // EGL_ANGLE_experimental_present_path variables
+ bool mCurPresentPathFastEnabled;
+ int mCurPresentPathFastColorBufferHeight;
+
+ // Current RenderTarget state
+ bool mRenderTargetIsDirty;
+
+ // Queries that are currently active in this state
+ std::set<Query11 *> mCurrentQueries;
+
+ // Currently applied textures
+ struct SRVRecord
+ {
+ uintptr_t srv;
+ uintptr_t resource;
+ D3D11_SHADER_RESOURCE_VIEW_DESC desc;
+ };
+
+ // A cache of current SRVs that also tracks the highest 'used' (non-NULL) SRV
+ // We might want to investigate a more robust approach that is also fast when there's
+ // a large gap between used SRVs (e.g. if SRV 0 and 7 are non-NULL, this approach will
+ // waste time on SRVs 1-6.)
+ class SRVCache : angle::NonCopyable
+ {
+ public:
+ SRVCache() : mHighestUsedSRV(0) {}
+
+ void initialize(size_t size) { mCurrentSRVs.resize(size); }
+
+ size_t size() const { return mCurrentSRVs.size(); }
+ size_t highestUsed() const { return mHighestUsedSRV; }
+
+ const SRVRecord &operator[](size_t index) const { return mCurrentSRVs[index]; }
+ void clear();
+ void update(size_t resourceIndex, ID3D11ShaderResourceView *srv);
+
+ private:
+ std::vector<SRVRecord> mCurrentSRVs;
+ size_t mHighestUsedSRV;
+ };
+
+ SRVCache mCurVertexSRVs;
+ SRVCache mCurPixelSRVs;
+
+ // A block of NULL pointers, cached so we don't re-allocate every draw call
+ std::vector<ID3D11ShaderResourceView *> mNullSRVs;
+
+ // Current translations of "Current-Value" data - owned by Context, not VertexArray.
+ gl::AttributesMask mDirtyCurrentValueAttribs;
+ std::vector<TranslatedAttribute> mCurrentValueAttribs;
+};
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp
new file mode 100755
index 000000000..fbbdf552a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp
@@ -0,0 +1,102 @@
+//
+// Copyright (c) 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.
+//
+
+// StreamProducerNV12.cpp: Implements the stream producer for NV12 textures
+
+#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
+
+#include "common/utilities.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+StreamProducerNV12::StreamProducerNV12(Renderer11 *renderer)
+ : mRenderer(renderer), mTexture(nullptr), mArraySlice(0), mTextureWidth(0), mTextureHeight(0)
+{
+}
+
+StreamProducerNV12::~StreamProducerNV12()
+{
+ SafeRelease(mTexture);
+}
+
+egl::Error StreamProducerNV12::validateD3DNV12Texture(void *pointer) const
+{
+ ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer);
+
+ // Check that the texture originated from our device
+ ID3D11Device *device;
+ textureD3D->GetDevice(&device);
+ if (device != mRenderer->getDevice())
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "Texture not created on ANGLE D3D device");
+ }
+
+ // Get the description and validate it
+ D3D11_TEXTURE2D_DESC desc;
+ textureD3D->GetDesc(&desc);
+ if (desc.Format != DXGI_FORMAT_NV12)
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "Texture format not DXGI_FORMAT_NV12");
+ }
+ if (desc.Width < 1 || desc.Height < 1)
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "Texture is of size 0");
+ }
+ if ((desc.Width % 2) != 0 || (desc.Height % 2) != 0)
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "Texture dimensions are not even");
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+void StreamProducerNV12::postD3DNV12Texture(void *pointer, const egl::AttributeMap &attributes)
+{
+ ASSERT(pointer != nullptr);
+ ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer);
+
+ // Check that the texture originated from our device
+ ID3D11Device *device;
+ textureD3D->GetDevice(&device);
+
+ // Get the description
+ D3D11_TEXTURE2D_DESC desc;
+ textureD3D->GetDesc(&desc);
+
+ // Release the previous texture if there is one
+ SafeRelease(mTexture);
+
+ mTexture = textureD3D;
+ mTexture->AddRef();
+ mTextureWidth = desc.Width;
+ mTextureHeight = desc.Height;
+ mArraySlice = static_cast<UINT>(attributes.get(EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0));
+}
+
+egl::Stream::GLTextureDescription StreamProducerNV12::getGLFrameDescription(int planeIndex)
+{
+ // The UV plane of NV12 textures has half the width/height of the Y plane
+ egl::Stream::GLTextureDescription desc;
+ desc.width = (planeIndex == 0) ? mTextureWidth : (mTextureWidth / 2);
+ desc.height = (planeIndex == 0) ? mTextureHeight : (mTextureHeight / 2);
+ desc.internalFormat = (planeIndex == 0) ? GL_R8 : GL_RG8;
+ desc.mipLevels = 0;
+ return desc;
+}
+
+ID3D11Texture2D *StreamProducerNV12::getD3DTexture()
+{
+ return mTexture;
+}
+
+UINT StreamProducerNV12::getArraySlice()
+{
+ return mArraySlice;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h
new file mode 100755
index 000000000..304c9dfe5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 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.
+//
+
+// StreamProducerNV12.h: Interface for a NV12 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 StreamProducerNV12 : public StreamProducerImpl
+{
+ public:
+ StreamProducerNV12(Renderer11 *renderer);
+ ~StreamProducerNV12() override;
+
+ egl::Error validateD3DNV12Texture(void *pointer) const override;
+ void postD3DNV12Texture(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 mTextureWidth;
+ UINT mTextureHeight;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
new file mode 100755
index 000000000..a410c425d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
@@ -0,0 +1,867 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "third_party/trace_event/trace_event.h"
+
+// Precompiled shaders
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.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
+{
+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)
+ : 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(nullptr),
+ mBackBufferRTView(nullptr),
+ mBackBufferSRView(nullptr),
+ mNeedsOffscreenTexture(NeedsOffscreenTexture(renderer, nativeWindow, orientation)),
+ mOffscreenTexture(nullptr),
+ mOffscreenRTView(nullptr),
+ mOffscreenSRView(nullptr),
+ mDepthStencilTexture(nullptr),
+ mDepthStencilDSView(nullptr),
+ mDepthStencilSRView(nullptr),
+ mQuadVB(nullptr),
+ mPassThroughSampler(nullptr),
+ mPassThroughIL(nullptr),
+ mPassThroughVS(nullptr),
+ mPassThroughPS(nullptr),
+ mPassThroughRS(nullptr),
+ mColorRenderTarget(this, renderer, false),
+ mDepthStencilRenderTarget(this, renderer, true)
+{
+ // Sanity check that if present path fast is active then we're using the default orientation
+ ASSERT(!mRenderer->presentPathFastEnabled() || orientation == 0);
+}
+
+SwapChain11::~SwapChain11()
+{
+ release();
+}
+
+void SwapChain11::release()
+{
+ SafeRelease(mSwapChain1);
+ SafeRelease(mSwapChain);
+ SafeRelease(mKeyedMutex);
+ SafeRelease(mBackBufferTexture);
+ SafeRelease(mBackBufferRTView);
+ SafeRelease(mBackBufferSRView);
+ SafeRelease(mOffscreenTexture);
+ SafeRelease(mOffscreenRTView);
+ SafeRelease(mOffscreenSRView);
+ SafeRelease(mDepthStencilTexture);
+ SafeRelease(mDepthStencilDSView);
+ SafeRelease(mDepthStencilSRView);
+ SafeRelease(mQuadVB);
+ SafeRelease(mPassThroughSampler);
+ SafeRelease(mPassThroughIL);
+ SafeRelease(mPassThroughVS);
+ SafeRelease(mPassThroughPS);
+ SafeRelease(mPassThroughRS);
+
+ if (!mAppCreatedShareHandle)
+ {
+ mShareHandle = NULL;
+ }
+}
+
+void SwapChain11::releaseOffscreenColorBuffer()
+{
+ SafeRelease(mOffscreenTexture);
+ SafeRelease(mOffscreenRTView);
+ SafeRelease(mOffscreenSRView);
+}
+
+void SwapChain11::releaseOffscreenDepthBuffer()
+{
+ SafeRelease(mDepthStencilTexture);
+ SafeRelease(mDepthStencilDSView);
+ SafeRelease(mDepthStencilSRView);
+}
+
+EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHeight)
+{
+ if (mNeedsOffscreenTexture)
+ {
+ EGLint result = resetOffscreenColorBuffer(backbufferWidth, backbufferHeight);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+ }
+
+ EGLint result = resetOffscreenDepthBuffer(backbufferWidth, backbufferHeight);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight)
+{
+ ASSERT(mNeedsOffscreenTexture);
+
+ TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture");
+ ID3D11Device *device = mRenderer->getDevice();
+
+ ASSERT(device != NULL);
+
+ // D3D11 does not allow zero size textures
+ ASSERT(backbufferWidth >= 1);
+ ASSERT(backbufferHeight >= 1);
+
+ // Preserve the render target content
+ ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
+ if (previousOffscreenTexture)
+ {
+ previousOffscreenTexture->AddRef();
+ }
+ const int previousWidth = mWidth;
+ const int previousHeight = mHeight;
+
+ releaseOffscreenColorBuffer();
+
+ const d3d11::Format &backbufferFormatInfo =
+ d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
+
+ // 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);
+ ASSERT(SUCCEEDED(result));
+
+ mOffscreenTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11);
+ SafeRelease(tempResource11);
+ }
+ else if (mD3DTexture != nullptr)
+ {
+ mOffscreenTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(mD3DTexture);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ ASSERT(mOffscreenTexture != nullptr);
+ }
+ else
+ {
+ const bool useSharedResource =
+ !mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport();
+
+ D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
+ offscreenTextureDesc.Width = backbufferWidth;
+ offscreenTextureDesc.Height = backbufferHeight;
+ offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
+ offscreenTextureDesc.MipLevels = 1;
+ offscreenTextureDesc.ArraySize = 1;
+ offscreenTextureDesc.SampleDesc.Count = 1;
+ 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;
+
+ HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
+
+ if (FAILED(result))
+ {
+ ERR("Could not create offscreen texture: %08lX", result);
+ release();
+
+ if (d3d11::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ d3d11::SetDebugName(mOffscreenTexture, "Offscreen back buffer texture");
+
+ // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
+ if (useSharedResource)
+ {
+ IDXGIResource *offscreenTextureResource = NULL;
+ result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
+
+ // Fall back to no share handle on failure
+ if (FAILED(result))
+ {
+ ERR("Could not query offscreen texture resource: %08lX", result);
+ }
+ else
+ {
+ result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
+ SafeRelease(offscreenTextureResource);
+
+ if (FAILED(result))
+ {
+ mShareHandle = NULL;
+ ERR("Could not get offscreen texture shared handle: %08lX", result);
+ }
+ }
+ }
+ }
+
+ // This may return null if the original texture was created without a keyed mutex.
+ mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture);
+
+ D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc;
+ offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat;
+ offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ offscreenRTVDesc.Texture2D.MipSlice = 0;
+
+ HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target");
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc;
+ offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat;
+ offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ offscreenSRVDesc.Texture2D.MostDetailedMip = 0;
+ offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);
+
+ result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource");
+
+ if (previousOffscreenTexture != nullptr)
+ {
+ D3D11_BOX sourceBox = {0};
+ 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, 0, 0, yoffset, 0,
+ previousOffscreenTexture, 0, &sourceBox);
+
+ SafeRelease(previousOffscreenTexture);
+
+ if (mSwapChain)
+ {
+ swapRect(0, 0, backbufferWidth, backbufferHeight);
+ }
+ }
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resetOffscreenDepthBuffer(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 = 1;
+ depthStencilTextureDesc.SampleDesc.Quality = 0;
+ depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT;
+ depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+
+ if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ depthStencilTextureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
+ }
+
+ depthStencilTextureDesc.CPUAccessFlags = 0;
+ depthStencilTextureDesc.MiscFlags = 0;
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result =
+ device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture);
+ if (FAILED(result))
+ {
+ ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
+ release();
+
+ if (d3d11::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+ d3d11::SetDebugName(mDepthStencilTexture, "Offscreen depth stencil texture");
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc;
+ depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat;
+ depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ depthStencilDesc.Flags = 0;
+ depthStencilDesc.Texture2D.MipSlice = 0;
+
+ result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view");
+
+ if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc;
+ depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat;
+ depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ depthStencilSRVDesc.Texture2D.MostDetailedMip = 0;
+ depthStencilSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);
+
+ result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource");
+ }
+ }
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
+{
+ TRACE_EVENT0("gpu.angle", "SwapChain11::resize");
+ ID3D11Device *device = mRenderer->getDevice();
+
+ if (device == NULL)
+ {
+ 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 && mBackBufferRTView && mBackBufferSRView);
+
+ SafeRelease(mBackBufferTexture);
+ SafeRelease(mBackBufferRTView);
+ SafeRelease(mBackBufferSRView);
+
+ // Resize swap chain
+ DXGI_SWAP_CHAIN_DESC desc;
+ HRESULT result = mSwapChain->GetDesc(&desc);
+ if (FAILED(result))
+ {
+ ERR("Error reading swap chain description: 0x%08X", result);
+ release();
+ return EGL_BAD_ALLOC;
+ }
+
+ result = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight, getSwapChainNativeFormat(), 0);
+
+ if (FAILED(result))
+ {
+ ERR("Error resizing swap chain buffers: 0x%08X", result);
+ release();
+
+ if (d3d11::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
+ ASSERT(SUCCEEDED(result));
+ if (SUCCEEDED(result))
+ {
+ d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
+ result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
+ ASSERT(SUCCEEDED(result));
+ if (SUCCEEDED(result))
+ {
+ d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
+ }
+
+ result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView);
+ ASSERT(SUCCEEDED(result));
+ if (SUCCEEDED(result))
+ {
+ d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource");
+ }
+ }
+
+ mFirstSwap = true;
+
+ return resetOffscreenBuffers(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
+ return (mOffscreenRenderTargetFormat == GL_BGRA8_EXT) ? DXGI_FORMAT_B8G8R8A8_UNORM : DXGI_FORMAT_R8G8B8A8_UNORM;
+}
+
+EGLint SwapChain11::reset(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(backbufferWidth, backbufferHeight);
+ }
+
+ TRACE_EVENT0("gpu.angle", "SwapChain11::reset");
+ ID3D11Device *device = mRenderer->getDevice();
+
+ if (device == NULL)
+ {
+ 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);
+ SafeRelease(mBackBufferTexture);
+ SafeRelease(mBackBufferRTView);
+
+ // 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 result = mNativeWindow->createSwapChain(device, mRenderer->getDxgiFactory(),
+ getSwapChainNativeFormat(), backbufferWidth,
+ backbufferHeight, &mSwapChain);
+
+ if (FAILED(result))
+ {
+ ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
+ release();
+
+ if (d3d11::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2)
+ {
+ mSwapChain1 = d3d11::DynamicCastComObject<IDXGISwapChain1>(mSwapChain);
+ }
+
+ result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
+
+ result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
+
+ result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view");
+ }
+
+ mFirstSwap = true;
+
+ return resetOffscreenBuffers(backbufferWidth, backbufferHeight);
+}
+
+void SwapChain11::initPassThroughResources()
+{
+ if (mPassThroughResourcesInit)
+ {
+ return;
+ }
+
+ TRACE_EVENT0("gpu.angle", "SwapChain11::initPassThroughResources");
+ ID3D11Device *device = mRenderer->getDevice();
+
+ ASSERT(device != NULL);
+
+ // Make sure our resources are all not allocated, when we create
+ ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
+ ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
+
+ 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;
+
+ HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
+
+ 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;
+
+ result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
+
+ 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 },
+ };
+
+ result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
+
+ result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
+
+ result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
+
+ // 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;
+ result = device->CreateRasterizerState(&rasterizerDesc, &mPassThroughRS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mPassThroughRS, "Swap chain pass through rasterizer state");
+
+ mPassThroughResourcesInit = true;
+}
+
+// parameters should be validated/clamped by caller
+EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ if (mNeedsOffscreenTexture)
+ {
+ EGLint result = copyOffscreenToBackbuffer(x, y, width, height);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+ }
+
+ EGLint result = present(x, y, width, height);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+
+ mRenderer->onSwap();
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ if (!mSwapChain)
+ {
+ return EGL_SUCCESS;
+ }
+
+ initPassThroughResources();
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ // Set vertices
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = deviceContext->Map(mQuadVB, 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, 0);
+
+ static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
+ static UINT startIdx = 0;
+ deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
+
+ // Apply state
+ deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
+
+ static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
+
+ deviceContext->RSSetState(mPassThroughRS);
+
+ // Apply shaders
+ deviceContext->IASetInputLayout(mPassThroughIL);
+ deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+ deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
+ deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
+ deviceContext->GSSetShader(NULL, NULL, 0);
+
+ auto stateManager = mRenderer->getStateManager();
+
+ // Apply render targets
+ stateManager->setOneTimeRenderTarget(mBackBufferRTView, nullptr);
+
+ // Set the viewport
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = static_cast<FLOAT>(mWidth);
+ viewport.Height = static_cast<FLOAT>(mHeight);
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ deviceContext->RSSetViewports(1, &viewport);
+
+ // Apply textures
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView);
+ deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
+
+ // Draw
+ deviceContext->Draw(4, 0);
+
+ // Rendering to the swapchain is now complete. Now we can call Present().
+ // Before that, we perform any cleanup on the D3D device. We do this before Present() to make sure the
+ // cleanup is caught under the current eglSwapBuffers() PIX/Graphics Diagnostics call rather than the next one.
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
+
+ mRenderer->markAllStateDirty();
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::present(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.
+ if (mSwapChain1 != nullptr)
+ {
+ 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.
+ mRenderer->getStateManager()->invalidateRenderTarget();
+
+ if (result == DXGI_ERROR_DEVICE_REMOVED)
+ {
+ ERR("Present failed: the D3D11 device was removed: 0x%08X",
+ 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 error code 0x%08X", result);
+ }
+
+ mNativeWindow->commitChange();
+
+ return EGL_SUCCESS;
+}
+
+ID3D11Texture2D *SwapChain11::getOffscreenTexture()
+{
+ return mNeedsOffscreenTexture ? mOffscreenTexture : mBackBufferTexture;
+}
+
+ID3D11RenderTargetView *SwapChain11::getRenderTarget()
+{
+ return mNeedsOffscreenTexture ? mOffscreenRTView : mBackBufferRTView;
+}
+
+ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
+{
+ return mNeedsOffscreenTexture ? mOffscreenSRView : mBackBufferSRView;
+}
+
+ID3D11DepthStencilView *SwapChain11::getDepthStencil()
+{
+ return mDepthStencilDSView;
+}
+
+ID3D11ShaderResourceView * SwapChain11::getDepthStencilShaderResource()
+{
+ return mDepthStencilSRView;
+}
+
+ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
+{
+ return mDepthStencilTexture;
+}
+
+void SwapChain11::recreate()
+{
+ // possibly should use this method instead of reset
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
new file mode 100755
index 000000000..1d7e57b7c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
@@ -0,0 +1,108 @@
+//
+// Copyright (c) 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);
+ virtual ~SwapChain11();
+
+ EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
+ EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) override;
+ EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ void recreate() override;
+
+ RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; }
+ RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; }
+
+ ID3D11Texture2D *getOffscreenTexture();
+ ID3D11RenderTargetView *getRenderTarget();
+ ID3D11ShaderResourceView *getRenderTargetShaderResource();
+
+ ID3D11Texture2D *getDepthStencilTexture();
+ ID3D11DepthStencilView *getDepthStencil();
+ ID3D11ShaderResourceView *getDepthStencilShaderResource();
+
+ EGLint getWidth() const { return mWidth; }
+ EGLint getHeight() const { return mHeight; }
+ void *getKeyedMutex() override { return mKeyedMutex; }
+
+ private:
+ void release();
+ void initPassThroughResources();
+
+ void releaseOffscreenColorBuffer();
+ void releaseOffscreenDepthBuffer();
+ EGLint resetOffscreenBuffers(int backbufferWidth, int backbufferHeight);
+ EGLint resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight);
+ EGLint resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight);
+
+ DXGI_FORMAT getSwapChainNativeFormat() const;
+
+ EGLint copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height);
+ EGLint present(EGLint x, EGLint y, EGLint width, EGLint height);
+
+ 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;
+
+ ID3D11Texture2D *mBackBufferTexture;
+ ID3D11RenderTargetView *mBackBufferRTView;
+ ID3D11ShaderResourceView *mBackBufferSRView;
+
+ const bool mNeedsOffscreenTexture;
+ ID3D11Texture2D *mOffscreenTexture;
+ ID3D11RenderTargetView *mOffscreenRTView;
+ ID3D11ShaderResourceView *mOffscreenSRView;
+
+ ID3D11Texture2D *mDepthStencilTexture;
+ ID3D11DepthStencilView *mDepthStencilDSView;
+ ID3D11ShaderResourceView *mDepthStencilSRView;
+
+ ID3D11Buffer *mQuadVB;
+ ID3D11SamplerState *mPassThroughSampler;
+ ID3D11InputLayout *mPassThroughIL;
+ ID3D11VertexShader *mPassThroughVS;
+ ID3D11PixelShader *mPassThroughPS;
+ ID3D11RasterizerState *mPassThroughRS;
+
+ SurfaceRenderTarget11 mColorRenderTarget;
+ SurfaceRenderTarget11 mDepthStencilRenderTarget;
+};
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
new file mode 100755
index 000000000..36c888dd3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -0,0 +1,3390 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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/formatutils.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Image11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+
+namespace rx
+{
+
+TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil)
+ : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle), dropStencil(dropStencil)
+{
+}
+
+bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const
+{
+ return std::tie(baseLevel, mipLevels, swizzle, dropStencil) <
+ std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle, rhs.dropStencil);
+}
+
+TextureStorage11::TextureStorage11(Renderer11 *renderer,
+ UINT bindFlags,
+ UINT miscFlags,
+ GLenum internalFormat)
+ : mRenderer(renderer),
+ mTopLevel(0),
+ mMipLevels(0),
+ mFormatInfo(d3d11::Format::Get(internalFormat, mRenderer->getRenderer11DeviceCaps())),
+ mTextureWidth(0),
+ mTextureHeight(0),
+ mTextureDepth(0),
+ mDropStencilTexture(nullptr),
+ mBindFlags(bindFlags),
+ mMiscFlags(miscFlags)
+{
+ mLevelSRVs.fill(nullptr);
+ mLevelBlitSRVs.fill(nullptr);
+}
+
+TextureStorage11::~TextureStorage11()
+{
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ SafeRelease(mLevelSRVs[level]);
+ SafeRelease(mLevelBlitSRVs[level]);
+ }
+
+ for (SRVCache::iterator i = mSrvCache.begin(); i != mSrvCache.end(); i++)
+ {
+ SafeRelease(i->second);
+ }
+ mSrvCache.clear();
+ SafeRelease(mDropStencilTexture);
+}
+
+DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ bool renderTarget)
+{
+ 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.dsvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ bindFlags |= D3D11_BIND_DEPTH_STENCIL;
+ }
+ if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && renderTarget)
+ {
+ bindFlags |= D3D11_BIND_RENDER_TARGET;
+ }
+
+ return bindFlags;
+}
+
+DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ bool renderTarget,
+ int levels)
+{
+ UINT miscFlags = 0;
+
+ const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
+ if (renderTarget && levels > 1)
+ {
+ 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);
+}
+
+UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const
+{
+ UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel);
+ UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+ UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
+ ASSERT(subresource != std::numeric_limits<UINT>::max());
+ return subresource;
+}
+
+gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState,
+ ID3D11ShaderResourceView **outSRV)
+{
+ // Make sure to add the level offset for our tiny compressed texture workaround
+ const GLuint effectiveBaseLevel = textureState.getEffectiveBaseLevel();
+ bool swizzleRequired = textureState.swizzleRequired();
+ bool mipmapping = gl::IsMipmapFiltered(textureState.getSamplerState());
+ 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->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ // We must ensure that the level zero texture is in sync with mipped texture.
+ ANGLE_TRY(useLevelZeroWorkaroundTexture(mipLevels == 1));
+ }
+
+ if (swizzleRequired)
+ {
+ verifySwizzleExists(textureState.getSwizzleState());
+ }
+
+ // We drop the stencil when sampling from the SRV if three conditions hold:
+ // 1. the drop stencil workaround is enabled.
+ bool workaround = mRenderer->getWorkarounds().emulateTinyStencilTextures;
+ // 2. this is a stencil texture.
+ bool hasStencil = (mFormatInfo.format().stencilBits > 0);
+ // 3. the texture has a 1x1 or 2x2 mip.
+ bool hasSmallMips = (getLevelWidth(mMipLevels - 1) <= 2 || getLevelHeight(mMipLevels - 1) <= 2);
+
+ bool useDropStencil = (workaround && hasStencil && hasSmallMips);
+ if (useDropStencil)
+ {
+ // Ensure drop texture gets re-created, if SRV is cached.
+ ANGLE_TRY(createDropStencilTexture());
+ }
+
+ SRVKey key(effectiveBaseLevel, mipLevels, swizzleRequired, useDropStencil);
+ ANGLE_TRY(getCachedOrCreateSRV(key, outSRV));
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11::getCachedOrCreateSRV(const SRVKey &key,
+ ID3D11ShaderResourceView **outSRV)
+{
+ auto iter = mSrvCache.find(key);
+ if (iter != mSrvCache.end())
+ {
+ *outSRV = iter->second;
+ return gl::NoError();
+ }
+
+ ID3D11Resource *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(&texture));
+ format = swizzleFormat.srvFormat;
+ }
+ else if (key.dropStencil)
+ {
+ ASSERT(mDropStencilTexture);
+ texture = mDropStencilTexture;
+ format = DXGI_FORMAT_R32_FLOAT;
+ }
+ else
+ {
+ ANGLE_TRY(getResource(&texture));
+ format = mFormatInfo.srvFormat;
+ }
+
+ ID3D11ShaderResourceView *srv = nullptr;
+
+ ANGLE_TRY(createSRV(key.baseLevel, key.mipLevels, format, texture, &srv));
+
+ mSrvCache.insert(std::make_pair(key, srv));
+ *outSRV = srv;
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11::getSRVLevel(int mipLevel,
+ bool blitSRV,
+ ID3D11ShaderResourceView **outSRV)
+{
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+ auto &levelSRVs = (blitSRV) ? mLevelBlitSRVs : mLevelSRVs;
+ auto &otherLevelSRVs = (blitSRV) ? mLevelSRVs : mLevelBlitSRVs;
+
+ if (!levelSRVs[mipLevel])
+ {
+ // Only create a different SRV for blit if blit format is different from regular srv format
+ if (otherLevelSRVs[mipLevel] && mFormatInfo.srvFormat == mFormatInfo.blitSRVFormat)
+ {
+ levelSRVs[mipLevel] = otherLevelSRVs[mipLevel];
+ levelSRVs[mipLevel]->AddRef();
+ }
+ else
+ {
+ ID3D11Resource *resource = nullptr;
+ ANGLE_TRY(getResource(&resource));
+
+ DXGI_FORMAT resourceFormat =
+ blitSRV ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat;
+ ANGLE_TRY(createSRV(mipLevel, 1, resourceFormat, resource, &levelSRVs[mipLevel]));
+ }
+ }
+
+ *outSRV = levelSRVs[mipLevel];
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11::getSRVLevels(GLint baseLevel,
+ GLint maxLevel,
+ ID3D11ShaderResourceView **outSRV)
+{
+ 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->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ // We must ensure that the level zero texture is in sync with mipped texture.
+ ANGLE_TRY(useLevelZeroWorkaroundTexture(mipLevels == 1));
+ }
+
+ // TODO(jmadill): Assert we don't need to drop stencil.
+
+ SRVKey key(baseLevel, mipLevels, false, false);
+ ANGLE_TRY(getCachedOrCreateSRV(key, outSRV));
+
+ return gl::NoError();
+}
+
+const d3d11::Format &TextureStorage11::getFormatSet() const
+{
+ return mFormatInfo;
+}
+
+gl::Error TextureStorage11::generateSwizzles(const gl::SwizzleState &swizzleTarget)
+{
+ 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
+ ID3D11ShaderResourceView *sourceSRV = nullptr;
+ ANGLE_TRY(getSRVLevel(level, true, &sourceSRV));
+
+ ID3D11RenderTargetView *destRTV = nullptr;
+ ANGLE_TRY(getSwizzleRenderTarget(level, &destRTV));
+
+ gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
+
+ Blit11 *blitter = mRenderer->getBlitter();
+
+ ANGLE_TRY(blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleTarget));
+
+ mSwizzleCache[level] = swizzleTarget;
+ }
+ }
+
+ return gl::NoError();
+}
+
+void TextureStorage11::markLevelDirty(int mipLevel)
+{
+ if (mipLevel >= 0 && static_cast<unsigned int>(mipLevel) < ArraySize(mSwizzleCache))
+ {
+ // The default constructor of SwizzleState has GL_INVALID_INDEX for all channels which is
+ // not a valid swizzle combination
+ mSwizzleCache[mipLevel] = gl::SwizzleState();
+ }
+
+ SafeRelease(mDropStencilTexture);
+}
+
+void TextureStorage11::markDirty()
+{
+ for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++)
+ {
+ markLevelDirty(mipLevel);
+ }
+}
+
+gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture,
+ unsigned int sourceSubresource,
+ const gl::ImageIndex &index,
+ const gl::Box &copyArea)
+{
+ ASSERT(srcTexture);
+
+ const GLint level = index.mipIndex;
+
+ markLevelDirty(level);
+
+ gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
+
+ bool fullCopy = copyArea.x == 0 && copyArea.y == 0 && copyArea.z == 0 &&
+ copyArea.width == texSize.width && copyArea.height == texSize.height &&
+ copyArea.depth == texSize.depth;
+
+ ID3D11Resource *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 (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ ANGLE_TRY(getMippedResource(&dstTexture));
+ }
+ else
+ {
+ ANGLE_TRY(getResource(&dstTexture));
+ }
+
+ unsigned int dstSubresource = getSubresourceIndex(index);
+
+ ASSERT(dstTexture);
+
+ 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();
+ TextureHelper11 source = TextureHelper11::MakeAndReference(srcTexture, getFormatSet());
+ TextureHelper11 dest = TextureHelper11::MakeAndReference(dstTexture, getFormatSet());
+ return blitter->copyDepthStencil(source, sourceSubresource, copyArea, texSize, dest,
+ 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 *context = mRenderer->getDeviceContext();
+
+ context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z,
+ srcTexture, sourceSubresource, fullCopy ? nullptr : &srcBox);
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource *dstTexture,
+ unsigned int dstSubresource,
+ const gl::ImageIndex &index,
+ const gl::Box &region)
+{
+ ASSERT(dstTexture);
+
+ ID3D11Resource *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.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ ANGLE_TRY(getMippedResource(&srcTexture));
+ }
+ else
+ {
+ ANGLE_TRY(getResource(&srcTexture));
+ }
+
+ ASSERT(srcTexture);
+
+ unsigned int srcSubresource = getSubresourceIndex(index);
+
+ ID3D11DeviceContext *context = 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)
+ {
+ // 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;
+ }
+
+ context->CopySubresourceRegion(dstTexture, dstSubresource, region.x, region.y, region.z,
+ srcTexture, srcSubresource, pSrcBox);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex)
+{
+ ASSERT(sourceIndex.layerIndex == destIndex.layerIndex);
+
+ markLevelDirty(destIndex.mipIndex);
+
+ RenderTargetD3D *source = nullptr;
+ ANGLE_TRY(getRenderTarget(sourceIndex, &source));
+
+ RenderTargetD3D *dest = nullptr;
+ ANGLE_TRY(getRenderTarget(destIndex, &dest));
+
+ ID3D11ShaderResourceView *sourceSRV =
+ GetAs<RenderTarget11>(source)->getBlitShaderResourceView();
+ ID3D11RenderTargetView *destRTV = GetAs<RenderTarget11>(dest)->getRenderTargetView();
+
+ 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();
+ return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize,
+ nullptr,
+ gl::GetInternalFormatInfo(source->getInternalFormat()).format,
+ 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();
+
+ auto iter = mSrvCache.begin();
+ while (iter != mSrvCache.end())
+ {
+ if (!iter->first.swizzle)
+ {
+ SafeRelease(iter->second);
+ iter = mSrvCache.erase(iter);
+ }
+ else
+ {
+ iter++;
+ }
+ }
+
+ for (size_t level = 0; level < mLevelSRVs.size(); level++)
+ {
+ SafeRelease(mLevelSRVs[level]);
+ SafeRelease(mLevelBlitSRVs[level]);
+ }
+}
+
+gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+
+ ID3D11Resource *sourceResouce = nullptr;
+ ANGLE_TRY(getResource(&sourceResouce));
+
+ TextureStorage11 *dest11 = GetAs<TextureStorage11>(destStorage);
+ ID3D11Resource *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(&destResource));
+
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+ immediateContext->CopyResource(destResource, sourceResouce);
+
+ dest11->markDirty();
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11::setData(const gl::ImageIndex &index,
+ ImageD3D *image,
+ const gl::Box *destBox,
+ GLenum inputType,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixelData)
+{
+ ASSERT(!image->isDirty());
+
+ markLevelDirty(index.mipIndex);
+
+ ID3D11Resource *resource = nullptr;
+ ANGLE_TRY(getResource(&resource));
+ ASSERT(resource);
+
+ UINT destSubresource = getSubresourceIndex(index);
+
+ const auto sizedInputFormat = image->getSizedInputFormat(inputType);
+ const gl::InternalFormat &inputFormat = gl::GetInternalFormatInfo(sizedInputFormat);
+
+ gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex),
+ getLevelDepth(index.mipIndex));
+ bool fullUpdate = (destBox == nullptr || *destBox == levelBox);
+ ASSERT(inputFormat.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(!inputFormat.compressed);
+
+ 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_TRY_RESULT(
+ inputFormat.computeRowPitch(width, unpack.alignment, unpack.rowLength),
+ srcRowPitch);
+ GLuint srcDepthPitch = 0;
+ ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(height, unpack.imageHeight, srcRowPitch),
+ srcDepthPitch);
+ GLuint srcSkipBytes = 0;
+ ANGLE_TRY_RESULT(
+ inputFormat.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.is3D()),
+ 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;
+ MemoryBuffer *conversionBuffer = nullptr;
+ const uint8_t *data = nullptr;
+
+ LoadImageFunctionInfo loadFunctionInfo = d3d11Format.getLoadFunctions()(inputType);
+ if (loadFunctionInfo.requiresConversion)
+ {
+ ANGLE_TRY(mRenderer->getScratchMemoryBuffer(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, destSubresource, &destD3DBox, data,
+ bufferRowPitch, bufferDepthPitch);
+ }
+ else
+ {
+ immediateContext->UpdateSubresource(resource, destSubresource, nullptr, data,
+ bufferRowPitch, bufferDepthPitch);
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11::createDropStencilTexture()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION, "Drop stencil texture not implemented.");
+}
+
+TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain)
+ : TextureStorage11(renderer,
+ D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
+ 0,
+ swapchain->getRenderTargetInternalFormat()),
+ mTexture(swapchain->getOffscreenTexture()),
+ mLevelZeroTexture(nullptr),
+ mLevelZeroRenderTarget(nullptr),
+ mUseLevelZeroTexture(false),
+ mSwizzleTexture(nullptr)
+{
+ mTexture->AddRef();
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mAssociatedImages[i] = nullptr;
+ mRenderTarget[i] = nullptr;
+ mSwizzleRenderTargets[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,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ bool hintLevelZeroOnly)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ renderTarget,
+ levels),
+ internalformat),
+ mTexture(nullptr),
+ mHasKeyedMutex(false),
+ mLevelZeroTexture(nullptr),
+ mLevelZeroRenderTarget(nullptr),
+ mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
+ mSwizzleTexture(nullptr)
+{
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mAssociatedImages[i] = nullptr;
+ mRenderTarget[i] = nullptr;
+ mSwizzleRenderTargets[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->getWorkarounds().zeroMaxLodWorkaround);
+}
+
+TextureStorage11_2D::~TextureStorage11_2D()
+{
+ for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ if (mAssociatedImages[i] != nullptr)
+ {
+ bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this);
+ ASSERT(imageAssociationCorrect);
+
+ if (imageAssociationCorrect)
+ {
+ // We must let the Images recover their data before we delete it from the
+ // TextureStorage.
+ gl::Error error = mAssociatedImages[i]->recoverFromAssociatedStorage();
+ if (error.isError())
+ {
+ // TODO: Find a way to report this back to the context
+ ERR("Error initialization texture storage: %x", error.getCode());
+ }
+ }
+ }
+ }
+
+ SafeRelease(mTexture);
+ SafeRelease(mSwizzleTexture);
+
+ SafeRelease(mLevelZeroTexture);
+ SafeDelete(mLevelZeroRenderTarget);
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ SafeDelete(mRenderTarget[i]);
+ SafeRelease(mSwizzleRenderTargets[i]);
+ }
+
+ if (mHasKeyedMutex)
+ {
+ // If the keyed mutex is released that will unbind it and cause the state cache to become
+ // desynchronized.
+ mRenderer->getStateManager()->invalidateBoundViews();
+ }
+}
+
+gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+
+ TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage);
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
+ // corresponding textures in destStorage.
+ if (mTexture)
+ {
+ ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(false));
+
+ ID3D11Resource *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(&destResource));
+
+ immediateContext->CopyResource(destResource, mTexture);
+ }
+
+ if (mLevelZeroTexture)
+ {
+ ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(true));
+
+ ID3D11Resource *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(&destResource));
+
+ immediateContext->CopyResource(destResource, mLevelZeroTexture);
+ }
+
+ return gl::NoError();
+ }
+
+ ID3D11Resource *sourceResouce = nullptr;
+ ANGLE_TRY(getResource(&sourceResouce));
+
+ ID3D11Resource *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(&destResource));
+
+ immediateContext->CopyResource(destResource, sourceResouce);
+ dest11->markDirty();
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture)
+{
+ bool lastSetting = mUseLevelZeroTexture;
+
+ if (useLevelZeroTexture && mMipLevels > 1)
+ {
+ if (!mUseLevelZeroTexture && mTexture)
+ {
+ ANGLE_TRY(ensureTextureExists(1));
+
+ // Pull data back from the mipped texture if necessary.
+ ASSERT(mLevelZeroTexture);
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ context->CopySubresourceRegion(mLevelZeroTexture, 0, 0, 0, 0, mTexture, 0, nullptr);
+ }
+
+ mUseLevelZeroTexture = true;
+ }
+ else
+ {
+ if (mUseLevelZeroTexture && mLevelZeroTexture)
+ {
+ ANGLE_TRY(ensureTextureExists(mMipLevels));
+
+ // Pull data back from the level zero texture if necessary.
+ ASSERT(mTexture);
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ context->CopySubresourceRegion(mTexture, 0, 0, 0, 0, mLevelZeroTexture, 0, nullptr);
+ }
+
+ mUseLevelZeroTexture = false;
+ }
+
+ if (lastSetting != mUseLevelZeroTexture)
+ {
+ // Mark everything as dirty to be conservative.
+ if (mLevelZeroRenderTarget)
+ {
+ mLevelZeroRenderTarget->signalDirty();
+ }
+ for (auto *renderTarget : mRenderTarget)
+ {
+ if (renderTarget)
+ {
+ renderTarget->signalDirty();
+ }
+ }
+ }
+
+ return gl::NoError();
+}
+
+void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+ const GLint level = index.mipIndex;
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ mAssociatedImages[level] = image;
+ }
+}
+
+bool TextureStorage11_2D::isAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ const GLint level = index.mipIndex;
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ // This validation check should never return false. It means the Image/TextureStorage
+ // association is broken.
+ bool retValue = (mAssociatedImages[level] == expectedImage);
+ ASSERT(retValue);
+ return retValue;
+ }
+
+ return false;
+}
+
+// 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.mipIndex;
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ ASSERT(mAssociatedImages[level] == expectedImage);
+
+ if (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.
+gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ const GLint level = index.mipIndex;
+
+ 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. This should be
+ // true.
+ bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this);
+ ASSERT(imageAssociationCorrect);
+
+ if (imageAssociationCorrect)
+ {
+ // 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());
+ }
+ }
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource)
+{
+ if (mUseLevelZeroTexture && mMipLevels > 1)
+ {
+ ANGLE_TRY(ensureTextureExists(1));
+
+ *outResource = mLevelZeroTexture;
+ return gl::NoError();
+ }
+
+ ANGLE_TRY(ensureTextureExists(mMipLevels));
+
+ *outResource = mTexture;
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource)
+{
+ // This shouldn't be called unless the zero max LOD workaround is active.
+ ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
+
+ ANGLE_TRY(ensureTextureExists(mMipLevels));
+
+ *outResource = mTexture;
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels)
+{
+ // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
+ bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround
+ ? (mipLevels == 1) && (mMipLevels > 1)
+ : false;
+ ID3D11Texture2D **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 == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
+ {
+ ASSERT(mipLevels > 0);
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth; // Compressed texture size constraints?
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mipLevels;
+ desc.ArraySize = 1;
+ desc.Format = mFormatInfo.texFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = getMiscFlags();
+
+ HRESULT result = device->CreateTexture2D(&desc, nullptr, outputTexture);
+
+ // this can happen from windows TDR
+ if (d3d11::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.",
+ result);
+ }
+ else if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.",
+ result);
+ }
+
+ d3d11::SetDebugName(*outputTexture, "TexStorage2D.Texture");
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+ ASSERT(!index.hasLayer());
+
+ const int level = index.mipIndex;
+ ASSERT(level >= 0 && level < getLevelCount());
+
+ // 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];
+ return gl::NoError();
+ }
+
+ ID3D11Resource *texture = nullptr;
+ ANGLE_TRY(getResource(&texture));
+
+ ID3D11ShaderResourceView *srv = nullptr;
+ ANGLE_TRY(getSRVLevel(level, false, &srv));
+
+ ID3D11ShaderResourceView *blitSRV = nullptr;
+ ANGLE_TRY(getSRVLevel(level, true, &blitSRV));
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ 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;
+
+ ID3D11RenderTargetView *rtv;
+ HRESULT result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal render target view for texture "
+ "storage, result: 0x%X.",
+ result);
+ }
+ ASSERT(SUCCEEDED(result));
+
+ mLevelZeroRenderTarget = new TextureRenderTarget11(
+ rtv, mLevelZeroTexture, nullptr, nullptr, mFormatInfo.internalFormat,
+ getFormatSet(), getLevelWidth(level), getLevelHeight(level), 1, 0);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ }
+
+ *outRT = mLevelZeroRenderTarget;
+ return gl::NoError();
+ }
+
+ 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;
+
+ ID3D11RenderTargetView *rtv;
+ HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Failed to create internal render target view for texture storage, result: 0x%X.",
+ result);
+ }
+
+ mRenderTarget[level] = new TextureRenderTarget11(
+ rtv, texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, 0);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+
+ *outRT = mRenderTarget[level];
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ 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;
+
+ ID3D11DepthStencilView *dsv;
+ HRESULT result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Failed to create internal depth stencil view for texture storage, result: 0x%X.",
+ result);
+ }
+
+ mRenderTarget[level] =
+ new TextureRenderTarget11(dsv, texture, srv, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, 0);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(dsv);
+
+ *outRT = mRenderTarget[level];
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::createSRV(int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const
+{
+ 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;
+
+ ID3D11Resource *srvTexture = texture;
+
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ 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.
+ ASSERT(mLevelZeroTexture != nullptr && texture == mLevelZeroTexture);
+ srvTexture = mLevelZeroTexture;
+ }
+ else
+ {
+ ASSERT(mipLevels == static_cast<int>(mMipLevels));
+ ASSERT(mTexture != nullptr && texture == mTexture);
+ srvTexture = mTexture;
+ }
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal texture storage SRV, result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(*outSRV, "TexStorage2D.SRV");
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_2D::getSwizzleTexture(ID3D11Resource **outTexture)
+{
+ ASSERT(outTexture);
+
+ if (!mSwizzleTexture)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = 1;
+ desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).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;
+
+ HRESULT result = device->CreateTexture2D(&desc, nullptr, &mSwizzleTexture);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal swizzle texture, result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(mSwizzleTexture, "TexStorage2D.SwizzleTexture");
+ }
+
+ *outTexture = mSwizzleTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV)
+{
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+ ASSERT(outRTV);
+
+ if (!mSwizzleRenderTargets[mipLevel])
+ {
+ ID3D11Resource *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
+
+ HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc,
+ &mSwizzleRenderTargets[mipLevel]);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal swizzle render target view, result: 0x%X.",
+ result);
+ }
+ }
+
+ *outRTV = mSwizzleRenderTargets[mipLevel];
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2D::createDropStencilTexture()
+{
+ if (mDropStencilTexture)
+ {
+ return gl::NoError();
+ }
+
+ 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;
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ HRESULT hr = device->CreateTexture2D(&dropDesc, nullptr, &mDropStencilTexture);
+ if (FAILED(hr))
+ {
+ return gl::Error(GL_INVALID_OPERATION, "Error creating drop stencil texture.");
+ }
+ d3d11::SetDebugName(mDropStencilTexture, "TexStorage2D.DropStencil");
+
+ ANGLE_TRY(initDropStencilTexture(gl::ImageIndexIterator::Make2D(0, mMipLevels)));
+
+ return gl::NoError();
+}
+
+TextureStorage11_External::TextureStorage11_External(
+ Renderer11 *renderer,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &glDesc)
+ : TextureStorage11(renderer, D3D11_BIND_SHADER_RESOURCE, 0, glDesc.internalFormat)
+{
+ ASSERT(stream->getProducerType() == egl::Stream::ProducerType::D3D11TextureNV12);
+ StreamProducerNV12 *producer = static_cast<StreamProducerNV12 *>(stream->getImplementation());
+ mTexture = producer->getD3DTexture();
+ mSubresourceIndex = producer->getArraySlice();
+ mTexture->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;
+}
+
+TextureStorage11_External::~TextureStorage11_External()
+{
+ SafeRelease(mTexture);
+ if (mHasKeyedMutex)
+ {
+ // If the keyed mutex is released that will unbind it and cause the state cache to become
+ // desynchronized.
+ mRenderer->getStateManager()->invalidateBoundViews();
+ }
+}
+
+gl::Error TextureStorage11_External::copyToStorage(TextureStorage *destStorage)
+{
+ UNIMPLEMENTED();
+ return gl::NoError();
+}
+
+void TextureStorage11_External::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+ ASSERT(index.mipIndex == 0);
+ mAssociatedImage = image;
+}
+
+bool TextureStorage11_External::isAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ return (index.mipIndex == 0 && mAssociatedImage == expectedImage);
+}
+
+void TextureStorage11_External::disassociateImage(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ ASSERT(index.mipIndex == 0);
+ ASSERT(mAssociatedImage == expectedImage);
+ mAssociatedImage = nullptr;
+}
+
+gl::Error TextureStorage11_External::releaseAssociatedImage(const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ ASSERT(index.mipIndex == 0);
+
+ if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage)
+ {
+ bool imageAssociationCorrect = mAssociatedImage->isAssociatedStorageValid(this);
+ ASSERT(imageAssociationCorrect);
+
+ if (imageAssociationCorrect)
+ {
+ ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage());
+ }
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_External::getResource(ID3D11Resource **outResource)
+{
+ *outResource = mTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_External::getMippedResource(ID3D11Resource **outResource)
+{
+ *outResource = mTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_External::getRenderTarget(const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
+{
+ // Render targets are not supported for external textures
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureStorage11_External::createSRV(int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const
+{
+ // 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;
+
+ ID3D11Resource *srvTexture = texture;
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal texture storage SRV, result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(*outSRV, "TexStorage2D.SRV");
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_External::getSwizzleTexture(ID3D11Resource **outTexture)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureStorage11_External::getSwizzleRenderTarget(int mipLevel,
+ ID3D11RenderTargetView **outRTV)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer,
+ EGLImageD3D *eglImage,
+ RenderTarget11 *renderTarget11)
+ : TextureStorage11(renderer,
+ D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
+ 0,
+ renderTarget11->getInternalFormat()),
+ mImage(eglImage),
+ mCurrentRenderTarget(0),
+ mSwizzleTexture(nullptr),
+ mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS, nullptr)
+{
+ mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
+
+ mMipLevels = 1;
+ mTextureWidth = renderTarget11->getWidth();
+ mTextureHeight = renderTarget11->getHeight();
+ mTextureDepth = 1;
+}
+
+TextureStorage11_EGLImage::~TextureStorage11_EGLImage()
+{
+ SafeRelease(mSwizzleTexture);
+ for (size_t i = 0; i < mSwizzleRenderTargets.size(); i++)
+ {
+ SafeRelease(mSwizzleRenderTargets[i]);
+ }
+}
+
+gl::Error TextureStorage11_EGLImage::getResource(ID3D11Resource **outResource)
+{
+ ANGLE_TRY(checkForUpdatedRenderTarget());
+
+ RenderTarget11 *renderTarget11 = nullptr;
+ ANGLE_TRY(getImageRenderTarget(&renderTarget11));
+ *outResource = renderTarget11->getTexture();
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_EGLImage::getSRV(const gl::TextureState &textureState,
+ ID3D11ShaderResourceView **outSRV)
+{
+ ANGLE_TRY(checkForUpdatedRenderTarget());
+ return TextureStorage11::getSRV(textureState, outSRV);
+}
+
+gl::Error TextureStorage11_EGLImage::getMippedResource(ID3D11Resource **)
+{
+ // This shouldn't be called unless the zero max LOD workaround is active.
+ // EGL images are unavailable in this configuration.
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(!index.hasLayer());
+ ASSERT(index.mipIndex == 0);
+
+ ANGLE_TRY(checkForUpdatedRenderTarget());
+
+ return mImage->getRenderTarget(outRT);
+}
+
+gl::Error TextureStorage11_EGLImage::copyToStorage(TextureStorage *destStorage)
+{
+ ID3D11Resource *sourceResouce = nullptr;
+ ANGLE_TRY(getResource(&sourceResouce));
+
+ ASSERT(destStorage);
+ TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage);
+ ID3D11Resource *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(&destResource));
+
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+ immediateContext->CopyResource(destResource, sourceResouce);
+
+ dest11->markDirty();
+
+ return gl::NoError();
+}
+
+void TextureStorage11_EGLImage::associateImage(Image11 *, const gl::ImageIndex &)
+{
+}
+
+void TextureStorage11_EGLImage::disassociateImage(const gl::ImageIndex &, Image11 *)
+{
+}
+
+bool TextureStorage11_EGLImage::isAssociatedImageValid(const gl::ImageIndex &, Image11 *)
+{
+ return false;
+}
+
+gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::ImageIndex &, Image11 *)
+{
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(bool)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureStorage11_EGLImage::getSwizzleTexture(ID3D11Resource **outTexture)
+{
+ ASSERT(outTexture);
+
+ if (!mSwizzleTexture)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = 1;
+ desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).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;
+
+ HRESULT result = device->CreateTexture2D(&desc, nullptr, &mSwizzleTexture);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal swizzle texture, result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(mSwizzleTexture, "TexStorageEGLImage.SwizzleTexture");
+ }
+
+ *outTexture = mSwizzleTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_EGLImage::getSwizzleRenderTarget(int mipLevel,
+ ID3D11RenderTargetView **outRTV)
+{
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+ ASSERT(outRTV);
+
+ if (!mSwizzleRenderTargets[mipLevel])
+ {
+ ID3D11Resource *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
+
+ HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc,
+ &mSwizzleRenderTargets[mipLevel]);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal swizzle render target view, result: 0x%X.",
+ result);
+ }
+ }
+
+ *outRTV = mSwizzleRenderTargets[mipLevel];
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget()
+{
+ RenderTarget11 *renderTarget11 = nullptr;
+ ANGLE_TRY(getImageRenderTarget(&renderTarget11));
+
+ if (mCurrentRenderTarget != reinterpret_cast<uintptr_t>(renderTarget11))
+ {
+ clearSRVCache();
+ mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_EGLImage::createSRV(int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const
+{
+ 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;
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal texture storage SRV, result: 0x%X.",
+ result);
+ }
+
+ d3d11::SetDebugName(*outSRV, "TexStorageEGLImage.SRV");
+ }
+ else
+ {
+ RenderTarget11 *renderTarget = nullptr;
+ ANGLE_TRY(getImageRenderTarget(&renderTarget));
+
+ ASSERT(texture == renderTarget->getTexture());
+
+ *outSRV = renderTarget->getShaderResourceView();
+ (*outSRV)->AddRef();
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_EGLImage::getImageRenderTarget(RenderTarget11 **outRT) const
+{
+ RenderTargetD3D *renderTargetD3D = nullptr;
+ ANGLE_TRY(mImage->getRenderTarget(&renderTargetD3D));
+ *outRT = GetAs<RenderTarget11>(renderTargetD3D);
+ return gl::NoError();
+}
+
+TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer,
+ GLenum internalformat,
+ bool renderTarget,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ renderTarget,
+ levels),
+ internalformat),
+ mTexture(nullptr),
+ mLevelZeroTexture(nullptr),
+ mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
+ mSwizzleTexture(nullptr)
+{
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ mSwizzleRenderTargets[level] = nullptr;
+ for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+ {
+ mAssociatedImages[face][level] = nullptr;
+ mRenderTarget[face][level] = nullptr;
+ }
+ }
+
+ for (unsigned int face = 0; face < CUBE_FACE_COUNT; 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->getWorkarounds().zeroMaxLodWorkaround);
+}
+
+TextureStorage11_Cube::~TextureStorage11_Cube()
+{
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+ {
+ if (mAssociatedImages[face][level] != nullptr)
+ {
+ bool imageAssociationCorrect =
+ mAssociatedImages[face][level]->isAssociatedStorageValid(this);
+ ASSERT(imageAssociationCorrect);
+
+ if (imageAssociationCorrect)
+ {
+ // We must let the Images recover their data before we delete it from the
+ // TextureStorage.
+ mAssociatedImages[face][level]->recoverFromAssociatedStorage();
+ }
+ }
+ }
+ }
+
+ SafeRelease(mTexture);
+ SafeRelease(mSwizzleTexture);
+ SafeRelease(mLevelZeroTexture);
+
+ for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+ {
+ SafeDelete(mLevelZeroRenderTarget[face]);
+ }
+
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ SafeRelease(mSwizzleRenderTargets[level]);
+ for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+ {
+ SafeDelete(mRenderTarget[face][level]);
+ }
+ }
+}
+
+UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const
+{
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture &&
+ index.mipIndex == 0)
+ {
+ UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+ UINT subresource = D3D11CalcSubresource(0, arraySlice, 1);
+ ASSERT(subresource != std::numeric_limits<UINT>::max());
+ return subresource;
+ }
+ else
+ {
+ UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel);
+ UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+ UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
+ ASSERT(subresource != std::numeric_limits<UINT>::max());
+ return subresource;
+ }
+}
+
+gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+
+ TextureStorage11_Cube *dest11 = GetAs<TextureStorage11_Cube>(destStorage);
+
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+
+ // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
+ // corresponding textures in destStorage.
+ if (mTexture)
+ {
+ ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(false));
+
+ ID3D11Resource *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(&destResource));
+
+ immediateContext->CopyResource(destResource, mTexture);
+ }
+
+ if (mLevelZeroTexture)
+ {
+ ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(true));
+
+ ID3D11Resource *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(&destResource));
+
+ immediateContext->CopyResource(destResource, mLevelZeroTexture);
+ }
+ }
+ else
+ {
+ ID3D11Resource *sourceResouce = nullptr;
+ ANGLE_TRY(getResource(&sourceResouce));
+
+ ID3D11Resource *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(&destResource));
+
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+ immediateContext->CopyResource(destResource, sourceResouce);
+ }
+
+ dest11->markDirty();
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture)
+{
+ if (useLevelZeroTexture && mMipLevels > 1)
+ {
+ if (!mUseLevelZeroTexture && mTexture)
+ {
+ ANGLE_TRY(ensureTextureExists(1));
+
+ // Pull data back from the mipped texture if necessary.
+ ASSERT(mLevelZeroTexture);
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ for (int face = 0; face < 6; face++)
+ {
+ context->CopySubresourceRegion(mLevelZeroTexture, D3D11CalcSubresource(0, face, 1),
+ 0, 0, 0, mTexture, face * mMipLevels, nullptr);
+ }
+ }
+
+ mUseLevelZeroTexture = true;
+ }
+ else
+ {
+ if (mUseLevelZeroTexture && mLevelZeroTexture)
+ {
+ ANGLE_TRY(ensureTextureExists(mMipLevels));
+
+ // Pull data back from the level zero texture if necessary.
+ ASSERT(mTexture);
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ for (int face = 0; face < 6; face++)
+ {
+ context->CopySubresourceRegion(mTexture, D3D11CalcSubresource(0, face, mMipLevels),
+ 0, 0, 0, mLevelZeroTexture, face, nullptr);
+ }
+ }
+
+ mUseLevelZeroTexture = false;
+ }
+
+ return gl::NoError();
+}
+
+void TextureStorage11_Cube::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT));
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ if (0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT))
+ {
+ mAssociatedImages[layerTarget][level] = image;
+ }
+ }
+}
+
+bool TextureStorage11_Cube::isAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ if (0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT))
+ {
+ // This validation check should never return false. It means the Image/TextureStorage
+ // association is broken.
+ bool retValue = (mAssociatedImages[layerTarget][level] == expectedImage);
+ ASSERT(retValue);
+ return retValue;
+ }
+ }
+
+ return false;
+}
+
+// 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.mipIndex;
+ const GLint layerTarget = index.layerIndex;
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT));
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ if (0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT))
+ {
+ ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
+
+ if (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.
+gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT));
+
+ if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
+ {
+ if (0 <= layerTarget && layerTarget < static_cast<GLint>(CUBE_FACE_COUNT))
+ {
+ // 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. This should
+ // be true.
+ bool imageAssociationCorrect =
+ mAssociatedImages[layerTarget][level]->isAssociatedStorageValid(this);
+ ASSERT(imageAssociationCorrect);
+
+ if (imageAssociationCorrect)
+ {
+ // 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());
+ }
+ }
+ }
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource)
+{
+ if (mUseLevelZeroTexture && mMipLevels > 1)
+ {
+ ANGLE_TRY(ensureTextureExists(1));
+ *outResource = mLevelZeroTexture;
+ return gl::NoError();
+ }
+ else
+ {
+ ANGLE_TRY(ensureTextureExists(mMipLevels));
+ *outResource = mTexture;
+ return gl::NoError();
+ }
+}
+
+gl::Error TextureStorage11_Cube::getMippedResource(ID3D11Resource **outResource)
+{
+ // This shouldn't be called unless the zero max LOD workaround is active.
+ ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
+
+ ANGLE_TRY(ensureTextureExists(mMipLevels));
+ *outResource = mTexture;
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::ensureTextureExists(int mipLevels)
+{
+ // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
+ bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround
+ ? (mipLevels == 1) && (mMipLevels > 1)
+ : false;
+ ID3D11Texture2D **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 == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
+ {
+ ASSERT(mMipLevels > 0);
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mipLevels;
+ desc.ArraySize = CUBE_FACE_COUNT;
+ desc.Format = 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();
+
+ HRESULT result = device->CreateTexture2D(&desc, nullptr, outputTexture);
+
+ // this can happen from windows TDR
+ if (d3d11::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create cube texture storage, result: 0x%X.", result);
+ }
+ else if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create cube texture storage, result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(*outputTexture, "TexStorageCube.Texture");
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::createRenderTargetSRV(ID3D11Resource *texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ ID3D11ShaderResourceView **srv) const
+{
+ ID3D11Device *device = mRenderer->getDevice();
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = resourceFormat;
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex;
+ srvDesc.Texture2DArray.ArraySize = 1;
+
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ }
+ else
+ {
+ // Will be used with Texture2D sampler, not TextureCube
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ }
+
+ HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, srv);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Failed to create internal shader resource view for texture storage, result: 0x%X.",
+ result);
+ }
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
+{
+ const int faceIndex = index.layerIndex;
+ const int level = index.mipIndex;
+
+ ASSERT(level >= 0 && level < getLevelCount());
+ ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(CUBE_FACE_COUNT));
+
+ if (!mRenderTarget[faceIndex][level])
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result;
+
+ ID3D11Resource *texture = nullptr;
+ ANGLE_TRY(getResource(&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;
+
+ ID3D11RenderTargetView *rtv;
+ result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal render target view for texture "
+ "storage, result: 0x%X.",
+ result);
+ }
+ ASSERT(SUCCEEDED(result));
+
+ mLevelZeroRenderTarget[faceIndex] = new TextureRenderTarget11(
+ rtv, mLevelZeroTexture, nullptr, nullptr, mFormatInfo.internalFormat,
+ getFormatSet(), getLevelWidth(level), getLevelHeight(level), 1, 0);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ }
+
+ ASSERT(outRT);
+ *outRT = mLevelZeroRenderTarget[faceIndex];
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ ID3D11ShaderResourceView *srv = nullptr;
+ ANGLE_TRY(createRenderTargetSRV(texture, index, mFormatInfo.srvFormat, &srv));
+ ID3D11ShaderResourceView *blitSRV = nullptr;
+ if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
+ {
+ gl::Error error =
+ createRenderTargetSRV(texture, index, mFormatInfo.blitSRVFormat, &blitSRV);
+ if (error.isError())
+ {
+ SafeRelease(srv);
+ return error;
+ }
+ }
+ else
+ {
+ blitSRV = srv;
+ blitSRV->AddRef();
+ }
+
+ d3d11::SetDebugName(srv, "TexStorageCube.RenderTargetSRV");
+
+ 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;
+
+ ID3D11RenderTargetView *rtv;
+ result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal render target view for texture "
+ "storage, result: 0x%X.",
+ result);
+ }
+
+ d3d11::SetDebugName(rtv, "TexStorageCube.RenderTargetRTV");
+
+ mRenderTarget[faceIndex][level] = new TextureRenderTarget11(
+ rtv, texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, 0);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ }
+ 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;
+
+ ID3D11DepthStencilView *dsv;
+ result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal depth stencil view for texture "
+ "storage, result: 0x%X.",
+ result);
+ }
+
+ d3d11::SetDebugName(dsv, "TexStorageCube.RenderTargetDSV");
+
+ mRenderTarget[faceIndex][level] = new TextureRenderTarget11(
+ dsv, texture, srv, mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
+ getLevelHeight(level), 1, 0);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(dsv);
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+
+ ASSERT(outRT);
+ *outRT = mRenderTarget[faceIndex][level];
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_Cube::createSRV(int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const
+{
+ 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 = CUBE_FACE_COUNT;
+ }
+ else
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ srvDesc.TextureCube.MipLevels = mipLevels;
+ srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
+ }
+
+ ID3D11Resource *srvTexture = texture;
+
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ 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.
+ ASSERT(mLevelZeroTexture != nullptr && texture == mLevelZeroTexture);
+ srvTexture = mLevelZeroTexture;
+ }
+ else
+ {
+ ASSERT(mipLevels == static_cast<int>(mMipLevels));
+ ASSERT(mTexture != nullptr && texture == mTexture);
+ srvTexture = mTexture;
+ }
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal texture storage SRV, result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(*outSRV, "TexStorageCube.SRV");
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_Cube::getSwizzleTexture(ID3D11Resource **outTexture)
+{
+ ASSERT(outTexture);
+
+ if (!mSwizzleTexture)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = CUBE_FACE_COUNT;
+ desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).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;
+
+ HRESULT result = device->CreateTexture2D(&desc, nullptr, &mSwizzleTexture);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal swizzle texture, result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(*outTexture, "TexStorageCube.SwizzleTexture");
+ }
+
+ *outTexture = mSwizzleTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel,
+ ID3D11RenderTargetView **outRTV)
+{
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+ ASSERT(outRTV);
+
+ if (!mSwizzleRenderTargets[mipLevel])
+ {
+ ID3D11Resource *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ 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 = CUBE_FACE_COUNT;
+
+ HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc,
+ &mSwizzleRenderTargets[mipLevel]);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal swizzle render target view, result: 0x%X.",
+ result);
+ }
+ }
+
+ *outRTV = mSwizzleRenderTargets[mipLevel];
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11::initDropStencilTexture(const gl::ImageIndexIterator &it)
+{
+ ID3D11Resource *resource = nullptr;
+ ANGLE_TRY(getResource(&resource));
+ TextureHelper11 sourceTexture = TextureHelper11::MakeAndReference(resource, mFormatInfo);
+ TextureHelper11 destTexture = TextureHelper11::MakeAndReference(
+ mDropStencilTexture,
+ d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps()));
+
+ gl::ImageIndexIterator itCopy = it;
+
+ while (itCopy.hasNext())
+ {
+ gl::ImageIndex index = itCopy.next();
+ gl::Box wholeArea(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex),
+ 1);
+ gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1);
+ UINT subresource = getSubresourceIndex(index);
+ ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil(sourceTexture, subresource, wholeArea,
+ wholeSize, destTexture, subresource,
+ wholeArea, wholeSize, nullptr));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::createDropStencilTexture()
+{
+ if (mDropStencilTexture)
+ {
+ return gl::NoError();
+ }
+
+ 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;
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ HRESULT hr = device->CreateTexture2D(&dropDesc, nullptr, &mDropStencilTexture);
+ if (FAILED(hr))
+ {
+ return gl::Error(GL_INVALID_OPERATION, "Error creating drop stencil texture.");
+ }
+ d3d11::SetDebugName(mDropStencilTexture, "TexStorageCube.DropStencil");
+
+ ANGLE_TRY(initDropStencilTexture(gl::ImageIndexIterator::MakeCube(0, mMipLevels)));
+
+ return gl::NoError();
+}
+
+TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer,
+ GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ renderTarget,
+ levels),
+ internalformat)
+{
+ mTexture = nullptr;
+ mSwizzleTexture = nullptr;
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mAssociatedImages[i] = nullptr;
+ mLevelRenderTargets[i] = nullptr;
+ mSwizzleRenderTargets[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;
+}
+
+TextureStorage11_3D::~TextureStorage11_3D()
+{
+ for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ if (mAssociatedImages[i] != nullptr)
+ {
+ bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this);
+ ASSERT(imageAssociationCorrect);
+
+ if (imageAssociationCorrect)
+ {
+ // We must let the Images recover their data before we delete it from the
+ // TextureStorage.
+ mAssociatedImages[i]->recoverFromAssociatedStorage();
+ }
+ }
+ }
+
+ SafeRelease(mTexture);
+ SafeRelease(mSwizzleTexture);
+
+ for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin();
+ i != mLevelLayerRenderTargets.end(); i++)
+ {
+ SafeDelete(i->second);
+ }
+ mLevelLayerRenderTargets.clear();
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ SafeDelete(mLevelRenderTargets[i]);
+ SafeRelease(mSwizzleRenderTargets[i]);
+ }
+}
+
+void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+ const GLint level = index.mipIndex;
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ mAssociatedImages[level] = image;
+ }
+}
+
+bool TextureStorage11_3D::isAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ const GLint level = index.mipIndex;
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ // This validation check should never return false. It means the Image/TextureStorage
+ // association is broken.
+ bool retValue = (mAssociatedImages[level] == expectedImage);
+ ASSERT(retValue);
+ return retValue;
+ }
+
+ return false;
+}
+
+// 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.mipIndex;
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ ASSERT(mAssociatedImages[level] == expectedImage);
+
+ if (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.
+gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ const GLint level = index.mipIndex;
+
+ 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. This should be
+ // true.
+ bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this);
+ ASSERT(imageAssociationCorrect);
+
+ if (imageAssociationCorrect)
+ {
+ // 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());
+ }
+ }
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_3D::getResource(ID3D11Resource **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 == nullptr && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
+ {
+ ASSERT(mMipLevels > 0);
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE3D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.Depth = mTextureDepth;
+ desc.MipLevels = mMipLevels;
+ desc.Format = mFormatInfo.texFormat;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = getMiscFlags();
+
+ HRESULT result = device->CreateTexture3D(&desc, nullptr, &mTexture);
+
+ // this can happen from windows TDR
+ if (d3d11::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.",
+ result);
+ }
+ else if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.",
+ result);
+ }
+
+ d3d11::SetDebugName(mTexture, "TexStorage3D.Texture");
+ }
+
+ *outResource = mTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_3D::createSRV(int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const
+{
+ 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;
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal texture storage SRV, result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(*outSRV, "TexStorage3D.SRV");
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+ const int mipLevel = index.mipIndex;
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+ ASSERT(mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
+
+ if (!index.hasLayer())
+ {
+ if (!mLevelRenderTargets[mipLevel])
+ {
+ ID3D11Resource *texture = nullptr;
+ ANGLE_TRY(getResource(&texture));
+
+ ID3D11ShaderResourceView *srv = nullptr;
+ ANGLE_TRY(getSRVLevel(mipLevel, false, &srv));
+
+ ID3D11ShaderResourceView *blitSRV = nullptr;
+ ANGLE_TRY(getSRVLevel(mipLevel, true, &blitSRV));
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ 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);
+
+ ID3D11RenderTargetView *rtv;
+ HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal render target view for texture "
+ "storage, result: 0x%X.",
+ result);
+ }
+
+ d3d11::SetDebugName(rtv, "TexStorage3D.RTV");
+
+ mLevelRenderTargets[mipLevel] = new TextureRenderTarget11(
+ rtv, texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel), 0);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ }
+
+ ASSERT(outRT);
+ *outRT = mLevelRenderTargets[mipLevel];
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ const int layer = index.layerIndex;
+
+ LevelLayerKey key(mipLevel, layer);
+ if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result;
+
+ ID3D11Resource *texture = nullptr;
+ ANGLE_TRY(getResource(&texture));
+
+ // TODO, what kind of SRV is expected here?
+ ID3D11ShaderResourceView *srv = nullptr;
+ ID3D11ShaderResourceView *blitSRV = nullptr;
+
+ 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;
+
+ ID3D11RenderTargetView *rtv;
+ result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal render target view for texture "
+ "storage, result: 0x%X.",
+ result);
+ }
+ ASSERT(SUCCEEDED(result));
+
+ d3d11::SetDebugName(rtv, "TexStorage3D.LayerRTV");
+
+ mLevelLayerRenderTargets[key] = new TextureRenderTarget11(
+ rtv, texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ }
+
+ ASSERT(outRT);
+ *outRT = mLevelLayerRenderTargets[key];
+ return gl::NoError();
+ }
+}
+
+gl::Error TextureStorage11_3D::getSwizzleTexture(ID3D11Resource **outTexture)
+{
+ ASSERT(outTexture);
+
+ if (!mSwizzleTexture)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE3D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.Depth = mTextureDepth;
+ desc.MipLevels = mMipLevels;
+ desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).texFormat;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ HRESULT result = device->CreateTexture3D(&desc, nullptr, &mSwizzleTexture);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal swizzle texture, result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(mSwizzleTexture, "TexStorage3D.SwizzleTexture");
+ }
+
+ *outTexture = mSwizzleTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV)
+{
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+ ASSERT(outRTV);
+
+ if (!mSwizzleRenderTargets[mipLevel])
+ {
+ ID3D11Resource *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ 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);
+
+ HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc,
+ &mSwizzleRenderTargets[mipLevel]);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal swizzle render target view, result: 0x%X.",
+ result);
+ }
+
+ d3d11::SetDebugName(mSwizzleTexture, "TexStorage3D.SwizzleRTV");
+ }
+
+ *outRTV = mSwizzleRenderTargets[mipLevel];
+ return gl::Error(GL_NO_ERROR);
+}
+
+TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer,
+ GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ renderTarget,
+ levels),
+ internalformat)
+{
+ mTexture = nullptr;
+ mSwizzleTexture = nullptr;
+
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ mSwizzleRenderTargets[level] = 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;
+}
+
+TextureStorage11_2DArray::~TextureStorage11_2DArray()
+{
+ for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++)
+ {
+ if (i->second)
+ {
+ bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this);
+ ASSERT(imageAssociationCorrect);
+
+ if (imageAssociationCorrect)
+ {
+ // We must let the Images recover their data before we delete it from the
+ // TextureStorage.
+ i->second->recoverFromAssociatedStorage();
+ }
+ }
+ }
+ mAssociatedImages.clear();
+
+ SafeRelease(mTexture);
+ SafeRelease(mSwizzleTexture);
+
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ SafeRelease(mSwizzleRenderTargets[level]);
+ }
+
+ for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++)
+ {
+ SafeDelete(i->second);
+ }
+ mRenderTargets.clear();
+}
+
+void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
+
+ ASSERT(0 <= level && level < getLevelCount());
+
+ if (0 <= level && level < getLevelCount())
+ {
+ LevelLayerKey key(level, layerTarget);
+ mAssociatedImages[key] = image;
+ }
+}
+
+bool TextureStorage11_2DArray::isAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
+
+ LevelLayerKey key(level, layerTarget);
+
+ // 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);
+ return 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.mipIndex;
+ const GLint layerTarget = index.layerIndex;
+
+ LevelLayerKey key(level, layerTarget);
+
+ bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
+ (mAssociatedImages[key] == expectedImage));
+ ASSERT(imageAssociationCorrect);
+
+ if (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.
+gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
+
+ LevelLayerKey key(level, layerTarget);
+
+ if (mAssociatedImages.find(key) != mAssociatedImages.end())
+ {
+ if (mAssociatedImages[key] != nullptr && mAssociatedImages[key] != incomingImage)
+ {
+ // Ensure that the Image is still associated with this TextureStorage. This should be
+ // true.
+ bool imageAssociationCorrect = mAssociatedImages[key]->isAssociatedStorageValid(this);
+ ASSERT(imageAssociationCorrect);
+
+ if (imageAssociationCorrect)
+ {
+ // 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());
+ }
+ }
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **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 == nullptr && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
+ {
+ ASSERT(mMipLevels > 0);
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = mTextureDepth;
+ desc.Format = mFormatInfo.texFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = getMiscFlags();
+
+ HRESULT result = device->CreateTexture2D(&desc, nullptr, &mTexture);
+
+ // this can happen from windows TDR
+ if (d3d11::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create 2D array texture storage, result: 0x%X.", result);
+ }
+ else if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create 2D array texture storage, result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(mTexture, "TexStorage2DArray.Texture");
+ }
+
+ *outResource = mTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_2DArray::createSRV(int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const
+{
+ 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;
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal texture storage SRV, result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(*outSRV, "TexStorage2DArray.SRV");
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_2DArray::createRenderTargetSRV(ID3D11Resource *texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ ID3D11ShaderResourceView **srv) const
+{
+ ID3D11Device *device = mRenderer->getDevice();
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = resourceFormat;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex;
+ srvDesc.Texture2DArray.ArraySize = 1;
+
+ HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, srv);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Failed to create internal shader resource view for texture storage, result: 0x%X.",
+ result);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(index.hasLayer());
+
+ const int mipLevel = index.mipIndex;
+ const int layer = index.layerIndex;
+
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+ LevelLayerKey key(mipLevel, layer);
+ if (mRenderTargets.find(key) == mRenderTargets.end())
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result;
+
+ ID3D11Resource *texture = nullptr;
+ ANGLE_TRY(getResource(&texture));
+ ID3D11ShaderResourceView *srv;
+ ANGLE_TRY(createRenderTargetSRV(texture, index, mFormatInfo.srvFormat, &srv));
+ ID3D11ShaderResourceView *blitSRV;
+ if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
+ {
+ gl::Error error =
+ createRenderTargetSRV(texture, index, mFormatInfo.blitSRVFormat, &blitSRV);
+ if (error.isError())
+ {
+ SafeRelease(srv);
+ return error;
+ }
+ }
+ else
+ {
+ blitSRV = srv;
+ blitSRV->AddRef();
+ }
+
+ d3d11::SetDebugName(srv, "TexStorage2DArray.RenderTargetSRV");
+
+ 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 = 1;
+
+ ID3D11RenderTargetView *rtv;
+ result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal render target view for texture "
+ "storage, result: 0x%X.",
+ result);
+ }
+
+ d3d11::SetDebugName(rtv, "TexStorage2DArray.RenderTargetRTV");
+
+ mRenderTargets[key] = new TextureRenderTarget11(
+ rtv, texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ }
+ 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 = 1;
+ dsvDesc.Flags = 0;
+
+ ID3D11DepthStencilView *dsv;
+ result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create TexStorage2DArray DSV. Result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(dsv, "TexStorage2DArray.RenderTargetDSV");
+
+ mRenderTargets[key] = new TextureRenderTarget11(
+ dsv, texture, srv, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(dsv);
+ SafeRelease(srv);
+ SafeRelease(blitSRV);
+ }
+ }
+
+ ASSERT(outRT);
+ *outRT = mRenderTargets[key];
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture)
+{
+ if (!mSwizzleTexture)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = mTextureDepth;
+ desc.Format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).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;
+
+ HRESULT result = device->CreateTexture2D(&desc, nullptr, &mSwizzleTexture);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal swizzle texture, result: 0x%X.", result);
+ }
+
+ d3d11::SetDebugName(*outTexture, "TexStorage2DArray.SwizzleTexture");
+ }
+
+ *outTexture = mSwizzleTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel,
+ ID3D11RenderTargetView **outRTV)
+{
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+ ASSERT(outRTV);
+
+ if (!mSwizzleRenderTargets[mipLevel])
+ {
+ ID3D11Resource *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ 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;
+
+ HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc,
+ &mSwizzleRenderTargets[mipLevel]);
+
+ ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal swizzle render target view, result: 0x%X.",
+ result);
+ }
+ }
+
+ *outRTV = mSwizzleRenderTargets[mipLevel];
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DArray::createDropStencilTexture()
+{
+ if (mDropStencilTexture)
+ {
+ return gl::NoError();
+ }
+
+ 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;
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ HRESULT hr = device->CreateTexture2D(&dropDesc, nullptr, &mDropStencilTexture);
+ if (FAILED(hr))
+ {
+ return gl::Error(GL_INVALID_OPERATION, "Error creating drop stencil texture.");
+ }
+ d3d11::SetDebugName(mDropStencilTexture, "TexStorage2DArray.DropStencil");
+
+ std::vector<GLsizei> layerCounts(mMipLevels, mTextureDepth);
+
+ ANGLE_TRY(initDropStencilTexture(
+ gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data())));
+
+ return gl::NoError();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
new file mode 100755
index 000000000..46eb8458b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
@@ -0,0 +1,425 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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/Texture.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+#include <array>
+#include <map>
+
+namespace gl
+{
+struct ImageIndex;
+}
+
+namespace rx
+{
+class EGLImageD3D;
+class RenderTargetD3D;
+class RenderTarget11;
+class Renderer11;
+class SwapChain11;
+class Image11;
+struct Renderer11DeviceCaps;
+
+class TextureStorage11 : public TextureStorage
+{
+ public:
+ virtual ~TextureStorage11();
+
+ static DWORD GetTextureBindFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget);
+ static DWORD GetTextureMiscFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget, int levels);
+
+ UINT getBindFlags() const;
+ UINT getMiscFlags() const;
+
+ virtual gl::Error getResource(ID3D11Resource **outResource) = 0;
+ virtual gl::Error getSRV(const gl::TextureState &textureState,
+ ID3D11ShaderResourceView **outSRV);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
+
+ virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
+
+ virtual int getTopLevel() const;
+ virtual bool isRenderTarget() const;
+ virtual bool isManaged() const;
+ bool supportsNativeMipmapFunction() const override;
+ virtual int getLevelCount() const;
+ virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
+
+ gl::Error generateSwizzles(const gl::SwizzleState &swizzleTarget);
+ void markLevelDirty(int mipLevel);
+ void markDirty();
+
+ gl::Error updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource,
+ const gl::ImageIndex &index, const gl::Box &copyArea);
+
+ gl::Error copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource,
+ const gl::ImageIndex &index, const gl::Box &region);
+
+ virtual void associateImage(Image11* image, const gl::ImageIndex &index) = 0;
+ virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) = 0;
+ virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) = 0;
+ virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0;
+
+ virtual gl::Error copyToStorage(TextureStorage *destStorage);
+ virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixelData);
+
+ gl::Error getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11ShaderResourceView **outSRV);
+
+ const d3d11::Format &getFormatSet() const;
+
+ protected:
+ TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags, GLenum internalFormat);
+ 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 gl::Error getMippedResource(ID3D11Resource **outResource) { return getResource(outResource); }
+
+ virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0;
+ virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0;
+ gl::Error getSRVLevel(int mipLevel, bool blitSRV, ID3D11ShaderResourceView **outSRV);
+
+ // Get a version of a depth texture with only depth information, not stencil.
+ virtual gl::Error createDropStencilTexture();
+ gl::Error initDropStencilTexture(const gl::ImageIndexIterator &it);
+
+ // The baseLevel parameter should *not* have mTopLevel applied.
+ virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const = 0;
+
+ void verifySwizzleExists(const gl::SwizzleState &swizzleState);
+
+ // Clear all cached non-swizzle SRVs and invalidate the swizzle cache.
+ void clearSRVCache();
+
+ Renderer11 *mRenderer;
+ int mTopLevel;
+ unsigned int mMipLevels;
+
+ const d3d11::Format &mFormatInfo;
+ unsigned int mTextureWidth;
+ unsigned int mTextureHeight;
+ unsigned int mTextureDepth;
+
+ gl::SwizzleState mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ ID3D11Texture2D *mDropStencilTexture;
+
+ private:
+ const UINT mBindFlags;
+ const UINT mMiscFlags;
+
+ struct SRVKey
+ {
+ SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil);
+
+ bool operator<(const SRVKey &rhs) const;
+
+ int baseLevel = 0; // Without mTopLevel applied.
+ int mipLevels = 0;
+ bool swizzle = false;
+ bool dropStencil = false;
+ };
+ typedef std::map<SRVKey, ID3D11ShaderResourceView *> SRVCache;
+
+ gl::Error getCachedOrCreateSRV(const SRVKey &key, ID3D11ShaderResourceView **outSRV);
+
+ SRVCache mSrvCache;
+ std::array<ID3D11ShaderResourceView *, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> mLevelSRVs;
+ std::array<ID3D11ShaderResourceView *, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> mLevelBlitSRVs;
+};
+
+class TextureStorage11_2D : public TextureStorage11
+{
+ public:
+ TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain);
+ TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false);
+ ~TextureStorage11_2D() override;
+
+ gl::Error getResource(ID3D11Resource **outResource) override;
+ gl::Error getMippedResource(ID3D11Resource **outResource) override;
+ gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+
+ gl::Error copyToStorage(TextureStorage *destStorage) override;
+
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ bool isAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+
+ gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
+
+ protected:
+ gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
+ gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) override;
+
+ gl::Error createDropStencilTexture() override;
+
+ gl::Error ensureTextureExists(int mipLevels);
+
+ private:
+ gl::Error createSRV(int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const override;
+
+ ID3D11Texture2D *mTexture;
+ RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ 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.
+ ID3D11Texture2D *mLevelZeroTexture;
+ RenderTarget11 *mLevelZeroRenderTarget;
+ bool mUseLevelZeroTexture;
+
+ // Swizzle-related variables
+ ID3D11Texture2D *mSwizzleTexture;
+ ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureStorage11_External : public TextureStorage11
+{
+ public:
+ TextureStorage11_External(Renderer11 *renderer,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &glDesc);
+ ~TextureStorage11_External() override;
+
+ gl::Error getResource(ID3D11Resource **outResource) override;
+ gl::Error getMippedResource(ID3D11Resource **outResource) override;
+ gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+
+ gl::Error copyToStorage(TextureStorage *destStorage) override;
+
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ bool isAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+
+ protected:
+ gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
+ gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) override;
+
+ private:
+ gl::Error createSRV(int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const override;
+
+ ID3D11Texture2D *mTexture;
+ int mSubresourceIndex;
+ bool mHasKeyedMutex;
+
+ Image11 *mAssociatedImage;
+};
+
+class TextureStorage11_EGLImage final : public TextureStorage11
+{
+ public:
+ TextureStorage11_EGLImage(Renderer11 *renderer,
+ EGLImageD3D *eglImage,
+ RenderTarget11 *renderTarget11);
+ ~TextureStorage11_EGLImage() override;
+
+ gl::Error getResource(ID3D11Resource **outResource) override;
+ gl::Error getSRV(const gl::TextureState &textureState,
+ ID3D11ShaderResourceView **outSRV) override;
+ gl::Error getMippedResource(ID3D11Resource **outResource) override;
+ gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+
+ gl::Error copyToStorage(TextureStorage *destStorage) override;
+
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ bool isAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+
+ gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
+
+ protected:
+ gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
+ gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **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.
+ gl::Error checkForUpdatedRenderTarget();
+
+ gl::Error createSRV(int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const override;
+
+ gl::Error getImageRenderTarget(RenderTarget11 **outRT) const;
+
+ EGLImageD3D *mImage;
+ uintptr_t mCurrentRenderTarget;
+
+ // Swizzle-related variables
+ ID3D11Texture2D *mSwizzleTexture;
+ std::vector<ID3D11RenderTargetView *> mSwizzleRenderTargets;
+};
+
+class TextureStorage11_Cube : public TextureStorage11
+{
+ public:
+ TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
+ virtual ~TextureStorage11_Cube();
+
+ virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
+
+ virtual gl::Error getResource(ID3D11Resource **outResource);
+ virtual gl::Error getMippedResource(ID3D11Resource **outResource);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+ virtual gl::Error copyToStorage(TextureStorage *destStorage);
+
+ virtual void associateImage(Image11* image, const gl::ImageIndex &index);
+ virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
+ virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
+ virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
+
+ virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture);
+
+ protected:
+ virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
+ virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
+
+ gl::Error createDropStencilTexture() override;
+
+ gl::Error ensureTextureExists(int mipLevels);
+
+ private:
+ virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const;
+ gl::Error createRenderTargetSRV(ID3D11Resource *texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ ID3D11ShaderResourceView **srv) const;
+
+ static const size_t CUBE_FACE_COUNT = 6;
+
+ ID3D11Texture2D *mTexture;
+ RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ // Level-zero workaround members. See TextureStorage11_2D's workaround members for a description.
+ ID3D11Texture2D *mLevelZeroTexture;
+ RenderTarget11 *mLevelZeroRenderTarget[CUBE_FACE_COUNT];
+ bool mUseLevelZeroTexture;
+
+ ID3D11Texture2D *mSwizzleTexture;
+ ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ Image11 *mAssociatedImages[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureStorage11_3D : public TextureStorage11
+{
+ public:
+ TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
+ GLsizei width, GLsizei height, GLsizei depth, int levels);
+ virtual ~TextureStorage11_3D();
+
+ virtual gl::Error getResource(ID3D11Resource **outResource);
+
+ // Handles both layer and non-layer RTs
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+ virtual void associateImage(Image11* image, const gl::ImageIndex &index);
+ virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
+ virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
+ virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
+
+ protected:
+ virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
+ virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
+
+ private:
+ virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const;
+
+ typedef std::pair<int, int> LevelLayerKey;
+ typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap;
+ RenderTargetMap mLevelLayerRenderTargets;
+
+ RenderTarget11 *mLevelRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ ID3D11Texture3D *mTexture;
+ ID3D11Texture3D *mSwizzleTexture;
+ ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureStorage11_2DArray : public TextureStorage11
+{
+ public:
+ TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
+ GLsizei width, GLsizei height, GLsizei depth, int levels);
+ virtual ~TextureStorage11_2DArray();
+
+ virtual gl::Error getResource(ID3D11Resource **outResource);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+ virtual void associateImage(Image11* image, const gl::ImageIndex &index);
+ virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
+ virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
+ virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
+
+ protected:
+ virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
+ virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
+
+ gl::Error createDropStencilTexture() override;
+
+ private:
+ virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+ ID3D11ShaderResourceView **outSRV) const;
+ gl::Error createRenderTargetSRV(ID3D11Resource *texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ ID3D11ShaderResourceView **srv) const;
+
+ typedef std::pair<int, int> LevelLayerKey;
+ typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap;
+ RenderTargetMap mRenderTargets;
+
+ ID3D11Texture2D *mTexture;
+
+ ID3D11Texture2D *mSwizzleTexture;
+ ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ typedef std::map<LevelLayerKey, Image11*> ImageMap;
+ ImageMap mAssociatedImages;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp
new file mode 100755
index 000000000..39b293f9b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp
@@ -0,0 +1,102 @@
+//
+// 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)
+{
+}
+
+TransformFeedback11::~TransformFeedback11()
+{
+}
+
+void TransformFeedback11::begin(GLenum primitiveMode)
+{
+}
+
+void TransformFeedback11::end()
+{
+ if (mRenderer->getWorkarounds().flushAfterEndingTransformFeedback)
+ {
+ mRenderer->getDeviceContext()->Flush();
+ }
+}
+
+void TransformFeedback11::pause()
+{
+}
+
+void TransformFeedback11::resume()
+{
+}
+
+void TransformFeedback11::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
+{
+}
+
+void TransformFeedback11::bindIndexedBuffer(size_t index,
+ const OffsetBindingPointer<gl::Buffer> &binding)
+{
+ mIsDirty = true;
+ mBufferOffsets[index] = static_cast<UINT>(binding.getOffset());
+}
+
+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());
+}
+
+gl::ErrorOrResult<const std::vector<ID3D11Buffer *> *> TransformFeedback11::getSOBuffers()
+{
+ 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_RESULT(storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK),
+ mBuffers[bindingIdx]);
+ }
+ }
+
+ return &mBuffers;
+}
+
+const std::vector<UINT> &TransformFeedback11::getSOBufferOffsets() const
+{
+ return mBufferOffsets;
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h
new file mode 100755
index 000000000..01879d6f3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h
@@ -0,0 +1,54 @@
+//
+// 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/angletypes.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace rx
+{
+
+class Renderer11;
+
+class TransformFeedback11 : public TransformFeedbackImpl
+{
+ public:
+ TransformFeedback11(const gl::TransformFeedbackState &state, Renderer11 *renderer);
+ ~TransformFeedback11() override;
+
+ void begin(GLenum primitiveMode) override;
+ void end() override;
+ void pause() override;
+ void resume() override;
+
+ void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
+ void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+
+ void onApply();
+
+ bool isDirty() const;
+
+ UINT getNumSOBuffers() const;
+ gl::ErrorOrResult<const std::vector<ID3D11Buffer *> *> getSOBuffers();
+ const std::vector<UINT> &getSOBufferOffsets() const;
+
+ private:
+ Renderer11 *mRenderer;
+
+ bool mIsDirty;
+ std::vector<ID3D11Buffer *> mBuffers;
+ std::vector<UINT> mBufferOffsets;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp
new file mode 100755
index 000000000..29185a9d9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp
@@ -0,0 +1,100 @@
+//
+// Copyright (c) 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_STORE)
+#include <wrl.h>
+#include <wrl/wrappers/corewrappers.h>
+#include <windows.applicationmodel.core.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_STORE)
+ 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_STORE)
+ 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_STORE)
+ 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
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h
new file mode 100755
index 000000000..4741e8160
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h
@@ -0,0 +1,45 @@
+//
+// Copyright (c) 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/angletypes.h"
+#include "libANGLE/Error.h"
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+typedef void* EventRegistrationToken;
+#else
+#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_STORE)
+ EventRegistrationToken mApplicationSuspendedEventToken;
+#endif
+
+ void trim();
+ bool registerForRendererTrimRequest();
+ void unregisterForRendererTrimRequest();
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
new file mode 100755
index 000000000..e06a6b22b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
@@ -0,0 +1,245 @@
+//
+// 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/BitSetIterator.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace
+{
+size_t GetAttribIndex(unsigned long dirtyBit)
+{
+ if (dirtyBit >= gl::VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED &&
+ dirtyBit < gl::VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED)
+ {
+ return dirtyBit - gl::VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED;
+ }
+
+ if (dirtyBit >= gl::VertexArray::DIRTY_BIT_ATTRIB_0_POINTER &&
+ dirtyBit < gl::VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER)
+ {
+ return dirtyBit - gl::VertexArray::DIRTY_BIT_ATTRIB_0_POINTER;
+ }
+
+ ASSERT(dirtyBit >= gl::VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR &&
+ dirtyBit < gl::VertexArray::DIRTY_BIT_ATTRIB_MAX_DIVISOR);
+ return static_cast<size_t>(dirtyBit) - gl::VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR;
+}
+} // anonymous namespace
+
+VertexArray11::VertexArray11(const gl::VertexArrayState &data)
+ : VertexArrayImpl(data),
+ mAttributeStorageTypes(data.getVertexAttributes().size(), VertexStorageType::CURRENT_VALUE),
+ mTranslatedAttribs(data.getVertexAttributes().size()),
+ mCurrentBuffers(data.getVertexAttributes().size())
+{
+ for (size_t attribIndex = 0; attribIndex < mCurrentBuffers.size(); ++attribIndex)
+ {
+ mOnBufferDataDirty.push_back(ChannelBinding(this, static_cast<SignalToken>(attribIndex)));
+ }
+}
+
+VertexArray11::~VertexArray11()
+{
+ for (size_t attribIndex = 0; attribIndex < mCurrentBuffers.size(); ++attribIndex)
+ {
+ if (mCurrentBuffers[attribIndex].get())
+ {
+ mCurrentBuffers[attribIndex].set(nullptr);
+ }
+ }
+}
+
+void VertexArray11::syncState(const gl::VertexArray::DirtyBits &dirtyBits)
+{
+ for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
+ {
+ if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
+ continue;
+
+ size_t attribIndex = GetAttribIndex(dirtyBit);
+ mAttribsToUpdate.set(attribIndex);
+ }
+}
+
+void VertexArray11::updateVertexAttribStorage(size_t attribIndex)
+{
+ const auto &attrib = mData.getVertexAttribute(attribIndex);
+
+ // Note: having an unchanged storage type doesn't mean the attribute is clean.
+ auto oldStorageType = mAttributeStorageTypes[attribIndex];
+ auto newStorageType = ClassifyAttributeStorage(attrib);
+
+ mAttributeStorageTypes[attribIndex] = newStorageType;
+
+ if (newStorageType == VertexStorageType::DYNAMIC)
+ {
+ if (oldStorageType != VertexStorageType::DYNAMIC)
+ {
+ // Sync dynamic attribs in a different set.
+ mAttribsToTranslate.reset(attribIndex);
+ mDynamicAttribsMask.set(attribIndex);
+ }
+ }
+ else
+ {
+ mAttribsToTranslate.set(attribIndex);
+
+ if (oldStorageType == VertexStorageType::DYNAMIC)
+ {
+ ASSERT(mDynamicAttribsMask[attribIndex]);
+ mDynamicAttribsMask.reset(attribIndex);
+ }
+ }
+
+ gl::Buffer *oldBufferGL = mCurrentBuffers[attribIndex].get();
+ gl::Buffer *newBufferGL = attrib.buffer.get();
+ Buffer11 *oldBuffer11 = oldBufferGL ? GetImplAs<Buffer11>(oldBufferGL) : nullptr;
+ Buffer11 *newBuffer11 = newBufferGL ? GetImplAs<Buffer11>(newBufferGL) : nullptr;
+
+ if (oldBuffer11 != newBuffer11 || oldStorageType != newStorageType)
+ {
+ // Note that for static callbacks, promotion to a static buffer from a dynamic buffer means
+ // we need to tag dynamic buffers with static callbacks.
+ BroadcastChannel *newChannel = nullptr;
+ if (newBuffer11 != nullptr)
+ {
+ switch (newStorageType)
+ {
+ case VertexStorageType::DIRECT:
+ newChannel = newBuffer11->getDirectBroadcastChannel();
+ break;
+ case VertexStorageType::STATIC:
+ case VertexStorageType::DYNAMIC:
+ newChannel = newBuffer11->getStaticBroadcastChannel();
+ break;
+ default:
+ break;
+ }
+ }
+ mOnBufferDataDirty[attribIndex].bind(newChannel);
+ mCurrentBuffers[attribIndex] = attrib.buffer;
+ }
+}
+
+gl::Error VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager,
+ const gl::State &state,
+ GLint start,
+ GLsizei count,
+ GLsizei instances)
+{
+ const gl::Program *program = state.getProgram();
+ const auto &activeLocations = program->getActiveAttribLocationsMask();
+
+ if (mAttribsToUpdate.any())
+ {
+ // Skip attrib locations the program doesn't use.
+ const auto &activeToUpdate = (mAttribsToUpdate & activeLocations);
+
+ for (auto toUpdateIndex : angle::IterateBitSet(activeToUpdate))
+ {
+ mAttribsToUpdate.reset(toUpdateIndex);
+ updateVertexAttribStorage(toUpdateIndex);
+ }
+ }
+
+ const auto &attribs = mData.getVertexAttributes();
+
+ if (mAttribsToTranslate.any())
+ {
+ // Skip attrib locations the program doesn't use, saving for the next frame.
+ const auto &dirtyActiveAttribs = (mAttribsToTranslate & activeLocations);
+
+ for (auto dirtyAttribIndex : angle::IterateBitSet(dirtyActiveAttribs))
+ {
+ mAttribsToTranslate.reset(dirtyAttribIndex);
+
+ auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex];
+ const auto &currentValue =
+ state.getVertexAttribCurrentValue(static_cast<unsigned int>(dirtyAttribIndex));
+
+ // Record basic attrib info
+ translatedAttrib->attribute = &attribs[dirtyAttribIndex];
+ translatedAttrib->currentValueType = currentValue.Type;
+ translatedAttrib->divisor = translatedAttrib->attribute->divisor;
+
+ switch (mAttributeStorageTypes[dirtyAttribIndex])
+ {
+ case VertexStorageType::DIRECT:
+ VertexDataManager::StoreDirectAttrib(translatedAttrib);
+ break;
+ case VertexStorageType::STATIC:
+ {
+ ANGLE_TRY(
+ VertexDataManager::StoreStaticAttrib(translatedAttrib, count, instances));
+ break;
+ }
+ case VertexStorageType::CURRENT_VALUE:
+ // Current value attribs are managed by the StateManager11.
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ }
+
+ if (mDynamicAttribsMask.any())
+ {
+ auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
+
+ for (auto dynamicAttribIndex : angle::IterateBitSet(activeDynamicAttribs))
+ {
+ auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex];
+ const auto &currentValue =
+ state.getVertexAttribCurrentValue(static_cast<unsigned int>(dynamicAttribIndex));
+
+ // Record basic attrib info
+ dynamicAttrib->attribute = &attribs[dynamicAttribIndex];
+ dynamicAttrib->currentValueType = currentValue.Type;
+ dynamicAttrib->divisor = dynamicAttrib->attribute->divisor;
+ }
+
+ return vertexDataManager->storeDynamicAttribs(&mTranslatedAttribs, activeDynamicAttribs,
+ start, count, instances);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+const std::vector<TranslatedAttribute> &VertexArray11::getTranslatedAttribs() const
+{
+ return mTranslatedAttribs;
+}
+
+void VertexArray11::signal(SignalToken token)
+{
+ ASSERT(mAttributeStorageTypes[token] != VertexStorageType::CURRENT_VALUE);
+
+ // This can change a buffer's storage, we'll need to re-check.
+ mAttribsToUpdate.set(token);
+}
+
+void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::State &state, GLsizei count)
+{
+ const gl::Program *program = state.getProgram();
+ const auto &activeLocations = program->getActiveAttribLocationsMask();
+ mAttribsToUpdate &= ~activeLocations;
+
+ // Promote to static after we clear the dirty attributes, otherwise we can lose dirtyness.
+ auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
+ VertexDataManager::PromoteDynamicAttribs(mTranslatedAttribs, activeDynamicAttribs, count);
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
new file mode 100755
index 000000000..eb0e0595d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
@@ -0,0 +1,62 @@
+//
+// 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/renderer/VertexArrayImpl.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/signal_utils.h"
+
+namespace rx
+{
+class Renderer11;
+
+class VertexArray11 : public VertexArrayImpl, public angle::SignalReceiver
+{
+ public:
+ VertexArray11(const gl::VertexArrayState &data);
+ ~VertexArray11() override;
+
+ void syncState(const gl::VertexArray::DirtyBits &dirtyBits) override;
+ gl::Error updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager,
+ const gl::State &state,
+ GLint start,
+ GLsizei count,
+ GLsizei instances);
+ void clearDirtyAndPromoteDynamicAttribs(const gl::State &state, GLsizei count);
+
+ const std::vector<TranslatedAttribute> &getTranslatedAttribs() const;
+
+ // SignalReceiver implementation
+ void signal(angle::SignalToken token) override;
+
+ private:
+ void updateVertexAttribStorage(size_t attribIndex);
+
+ std::vector<VertexStorageType> mAttributeStorageTypes;
+ std::vector<TranslatedAttribute> mTranslatedAttribs;
+
+ // The mask of attributes marked as dynamic.
+ gl::AttributesMask mDynamicAttribsMask;
+
+ // A mask of attributes that need to be re-evaluated.
+ gl::AttributesMask mAttribsToUpdate;
+
+ // A set of attributes we know are dirty, and need to be re-translated.
+ gl::AttributesMask mAttribsToTranslate;
+
+ // We need to keep a safe pointer to the Buffer so we can attach the correct dirty callbacks.
+ std::vector<BindingPointer<gl::Buffer>> mCurrentBuffers;
+
+ std::vector<angle::ChannelBinding> mOnBufferDataDirty;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
new file mode 100755
index 000000000..6cd91bd35
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
@@ -0,0 +1,191 @@
+//
+// Copyright (c) 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/VertexAttribute.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
+{
+ mBuffer = NULL;
+ mBufferSize = 0;
+ mDynamicUsage = false;
+ mMappedResourceData = NULL;
+}
+
+VertexBuffer11::~VertexBuffer11()
+{
+ ASSERT(mMappedResourceData == NULL);
+ SafeRelease(mBuffer);
+}
+
+gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
+{
+ SafeRelease(mBuffer);
+
+ updateSerial();
+
+ if (size > 0)
+ {
+ ID3D11Device *dxDevice = mRenderer->getDevice();
+
+ 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;
+
+ HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to allocate internal vertex buffer of size, %lu.", size);
+ }
+
+ if (dynamicUsage)
+ {
+ d3d11::SetDebugName(mBuffer, "VertexBuffer11 (dynamic)");
+ }
+ else
+ {
+ d3d11::SetDebugName(mBuffer, "VertexBuffer11 (static)");
+ }
+ }
+
+ mBufferSize = size;
+ mDynamicUsage = dynamicUsage;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error VertexBuffer11::mapResource()
+{
+ if (mMappedResourceData == NULL)
+ {
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+
+ HRESULT result =
+ dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result);
+ }
+
+ mMappedResourceData = reinterpret_cast<uint8_t *>(mappedResource.pData);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void VertexBuffer11::hintUnmapResource()
+{
+ if (mMappedResourceData != NULL)
+ {
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+ dxContext->Unmap(mBuffer, 0);
+
+ mMappedResourceData = NULL;
+ }
+}
+
+gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib,
+ GLenum currentValueType,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ unsigned int offset,
+ const uint8_t *sourceData)
+{
+ if (!mBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+ }
+
+ int inputStride = static_cast<int>(ComputeVertexAttributeStride(attrib));
+
+ // This will map the resource if it isn't already mapped.
+ ANGLE_TRY(mapResource());
+
+ uint8_t *output = mMappedResourceData + offset;
+
+ const uint8_t *input = sourceData;
+
+ if (instances == 0 || attrib.divisor == 0)
+ {
+ input += inputStride * start;
+ }
+
+ gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType);
+ const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
+ const d3d11::VertexFormat &vertexFormatInfo =
+ d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel);
+ ASSERT(vertexFormatInfo.copyFunction != NULL);
+ vertexFormatInfo.copyFunction(input, inputStride, count, output);
+
+ return gl::NoError();
+}
+
+unsigned int VertexBuffer11::getBufferSize() const
+{
+ return mBufferSize;
+}
+
+gl::Error VertexBuffer11::setBufferSize(unsigned int size)
+{
+ if (size > mBufferSize)
+ {
+ return initialize(size, mDynamicUsage);
+ }
+ else
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+gl::Error VertexBuffer11::discard()
+{
+ if (!mBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+ }
+
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result);
+ }
+
+ dxContext->Unmap(mBuffer, 0);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+ID3D11Buffer *VertexBuffer11::getBuffer() const
+{
+ return mBuffer;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
new file mode 100755
index 000000000..e8339db49
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 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"
+
+namespace rx
+{
+class Renderer11;
+
+class VertexBuffer11 : public VertexBuffer
+{
+ public:
+ explicit VertexBuffer11(Renderer11 *const renderer);
+
+ gl::Error initialize(unsigned int size, bool dynamicUsage) override;
+
+ gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib,
+ GLenum currentValueType,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ unsigned int offset,
+ const uint8_t *sourceData) override;
+
+ unsigned int getBufferSize() const override;
+ gl::Error setBufferSize(unsigned int size) override;
+ gl::Error discard() override;
+
+ void hintUnmapResource() override;
+
+ ID3D11Buffer *getBuffer() const;
+
+ private:
+ ~VertexBuffer11() override;
+ gl::Error mapResource();
+
+ Renderer11 *const mRenderer;
+
+ ID3D11Buffer *mBuffer;
+ unsigned int mBufferSize;
+ bool mDynamicUsage;
+
+ uint8_t *mMappedResourceData;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h
new file mode 100755
index 000000000..5501e361f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// copyvertex.h: Defines D3D11 vertex buffer copying and conversion functions
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_
+
+#include "common/mathutil.h"
+
+namespace rx
+{
+
+// 'alphaDefaultValueBits' gives the default value for the alpha channel (4th component)
+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);
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <size_t componentCount>
+inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline 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>
+inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <bool isSigned, bool normalized, bool toFloat>
+inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+}
+
+#include "copyvertex.inl"
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl
new file mode 100755
index 000000000..7c5c157c6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl
@@ -0,0 +1,386 @@
+//
+// Copyright (c) 2014-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.
+//
+
+namespace rx
+{
+
+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 *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 *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 GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(input + (stride * i));
+ float* offsetOutput = reinterpret_cast<float*>(output) + i * outputComponentCount;
+
+ for (size_t j = 0; j < inputComponentCount; j++)
+ {
+ offsetOutput[j] = static_cast<float>(offsetInput[j]) * 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>
+inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+ typedef std::numeric_limits<T> NL;
+
+ for (size_t i = 0; i < count; i++)
+ {
+ const T *offsetInput = reinterpret_cast<const T*>(input + (stride * i));
+ float *offsetOutput = reinterpret_cast<float*>(output) + i * outputComponentCount;
+
+ for (size_t j = 0; j < inputComponentCount; j++)
+ {
+ if (normalized)
+ {
+ if (NL::is_signed)
+ {
+ const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1);
+ offsetOutput[j] = (2 * static_cast<float>(offsetInput[j]) + 1) * divisor;
+ }
+ else
+ {
+ offsetOutput[j] = static_cast<float>(offsetInput[j]) / NL::max();
+ }
+ }
+ else
+ {
+ offsetOutput[j] = static_cast<float>(offsetInput[j]);
+ }
+ }
+
+ // This would require special padding.
+ 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;
+ }
+ }
+}
+
+namespace priv
+{
+
+template <bool isSigned, bool normalized, bool toFloat>
+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)
+ {
+ GLfloat *floatOutput = reinterpret_cast<GLfloat*>(output);
+ if (isSigned)
+ {
+ GLfloat finalValue = 0;
+ if (data & rgbSignMask)
+ {
+ int negativeNumber = data | negativeMask;
+ finalValue = static_cast<GLfloat>(negativeNumber);
+ }
+ else
+ {
+ finalValue = static_cast<GLfloat>(data);
+ }
+
+ 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;
+ *floatOutput = ((finalValue - minValue) / halfRange) - 1.0f;
+ }
+ else
+ {
+ *floatOutput = finalValue;
+ }
+ }
+ else
+ {
+ if (normalized)
+ {
+ const uint32_t maxValue = 0x3FF; // 1 set in bits 0 through 9
+ *floatOutput = static_cast<GLfloat>(data) / static_cast<GLfloat>(maxValue);
+ }
+ else
+ {
+ *floatOutput = static_cast<GLfloat>(data);
+ }
+ }
+ }
+ 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>
+inline void CopyPackedAlpha(uint32_t data, uint8_t *output)
+{
+ if (toFloat)
+ {
+ GLfloat *floatOutput = reinterpret_cast<GLfloat*>(output);
+ if (isSigned)
+ {
+ if (normalized)
+ {
+ switch (data)
+ {
+ case 0x0: *floatOutput = 0.0f; break;
+ case 0x1: *floatOutput = 1.0f; break;
+ case 0x2: *floatOutput = -1.0f; break;
+ case 0x3: *floatOutput = -1.0f; break;
+ default: UNREACHABLE();
+ }
+ }
+ else
+ {
+ switch (data)
+ {
+ case 0x0: *floatOutput = 0.0f; break;
+ case 0x1: *floatOutput = 1.0f; break;
+ case 0x2: *floatOutput = -2.0f; break;
+ case 0x3: *floatOutput = -1.0f; break;
+ default: UNREACHABLE();
+ }
+ }
+ }
+ else
+ {
+ if (normalized)
+ {
+ switch (data)
+ {
+ case 0x0: *floatOutput = 0.0f / 3.0f; break;
+ case 0x1: *floatOutput = 1.0f / 3.0f; break;
+ case 0x2: *floatOutput = 2.0f / 3.0f; break;
+ case 0x3: *floatOutput = 3.0f / 3.0f; break;
+ default: UNREACHABLE();
+ }
+ }
+ else
+ {
+ switch (data)
+ {
+ case 0x0: *floatOutput = 0.0f; break;
+ case 0x1: *floatOutput = 1.0f; break;
+ case 0x2: *floatOutput = 2.0f; break;
+ case 0x3: *floatOutput = 3.0f; break;
+ default: UNREACHABLE();
+ }
+ }
+ }
+ }
+ 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
+ {
+ GLushort *uintOutput = reinterpret_cast<GLushort*>(output);
+ switch (data)
+ {
+ case 0x0: *uintOutput = 0; break;
+ case 0x1: *uintOutput = 1; break;
+ case 0x2: *uintOutput = 2; break;
+ case 0x3: *uintOutput = 3; break;
+ default: UNREACHABLE();
+ }
+ }
+ }
+}
+
+}
+
+template <bool isSigned, bool normalized, bool toFloat>
+inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+ const size_t outputComponentSize = toFloat ? 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>( (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize));
+ priv::CopyPackedRGB<isSigned, normalized, toFloat>( (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize));
+ priv::CopyPackedRGB<isSigned, normalized, toFloat>( (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize));
+ priv::CopyPackedAlpha<isSigned, normalized, toFloat>((packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize));
+ }
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json
new file mode 100644
index 000000000..5b8d73568
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json
@@ -0,0 +1,118 @@
+{
+ "UNKNOWN": "NONE",
+ "R32G32B32A32_TYPELESS": "",
+ "R32G32B32A32_FLOAT": "",
+ "R32G32B32A32_UINT": "",
+ "R32G32B32A32_SINT": "",
+ "R32G32B32_TYPELESS": "",
+ "R32G32B32_FLOAT": "",
+ "R32G32B32_UINT": "",
+ "R32G32B32_SINT": "",
+ "R16G16B16A16_TYPELESS": "",
+ "R16G16B16A16_FLOAT": "",
+ "R16G16B16A16_UNORM": "",
+ "R16G16B16A16_UINT": "",
+ "R16G16B16A16_SNORM": "",
+ "R16G16B16A16_SINT": "",
+ "R32G32_TYPELESS": "",
+ "R32G32_FLOAT": "",
+ "R32G32_UINT": "",
+ "R32G32_SINT": "",
+ "R32G8X24_TYPELESS": "",
+ "D32_FLOAT_S8X24_UINT": "",
+ "R32_FLOAT_X8X24_TYPELESS": "",
+ "X32_TYPELESS_G8X24_UINT": "",
+ "R10G10B10A2_TYPELESS": "",
+ "R10G10B10A2_UNORM": "",
+ "R10G10B10A2_UINT": "",
+ "R11G11B10_FLOAT": "",
+ "R8G8B8A8_TYPELESS": "",
+ "R8G8B8A8_UNORM": "",
+ "R8G8B8A8_UNORM_SRGB": "",
+ "R8G8B8A8_UINT": "",
+ "R8G8B8A8_SNORM": "",
+ "R8G8B8A8_SINT": "",
+ "R16G16_TYPELESS": "",
+ "R16G16_FLOAT": "",
+ "R16G16_UNORM": "",
+ "R16G16_UINT": "",
+ "R16G16_SNORM": "",
+ "R16G16_SINT": "",
+ "R32_TYPELESS": "",
+ "D32_FLOAT": "",
+ "R32_FLOAT": "",
+ "R32_UINT": "",
+ "R32_SINT": "",
+ "R24G8_TYPELESS": "",
+ "D24_UNORM_S8_UINT": "",
+ "R24_UNORM_X8_TYPELESS": "",
+ "X24_TYPELESS_G8_UINT": "",
+ "R8G8_TYPELESS": "",
+ "R8G8_UNORM": "",
+ "R8G8_UINT": "",
+ "R8G8_SNORM": "",
+ "R8G8_SINT": "",
+ "R16_TYPELESS": "",
+ "R16_FLOAT": "",
+ "D16_UNORM": "",
+ "R16_UNORM": "",
+ "R16_UINT": "",
+ "R16_SNORM": "",
+ "R16_SINT": "",
+ "R8_TYPELESS": "",
+ "R8_UNORM": "",
+ "R8_UINT": "",
+ "R8_SNORM": "",
+ "R8_SINT": "",
+ "A8_UNORM": "",
+ "R1_UNORM": "",
+ "R9G9B9E5_SHAREDEXP": "",
+ "R8G8_B8G8_UNORM": "",
+ "G8R8_G8B8_UNORM": "",
+ "BC1_TYPELESS": "",
+ "BC1_UNORM": "BC1_RGBA_UNORM_BLOCK",
+ "BC1_UNORM_SRGB": "",
+ "BC2_TYPELESS": "",
+ "BC2_UNORM": "BC2_RGBA_UNORM_BLOCK",
+ "BC2_UNORM_SRGB": "",
+ "BC3_TYPELESS": "",
+ "BC3_UNORM": "BC3_RGBA_UNORM_BLOCK",
+ "BC3_UNORM_SRGB": "",
+ "BC4_TYPELESS": "",
+ "BC4_UNORM": "",
+ "BC4_SNORM": "",
+ "BC5_TYPELESS": "",
+ "BC5_UNORM": "",
+ "BC5_SNORM": "",
+ "B5G6R5_UNORM": "",
+ "B5G5R5A1_UNORM": "",
+ "B8G8R8A8_UNORM": "",
+ "B8G8R8X8_UNORM": "",
+ "R10G10B10_XR_BIAS_A2_UNORM": "",
+ "B8G8R8A8_TYPELESS": "",
+ "B8G8R8A8_UNORM_SRGB": "",
+ "B8G8R8X8_TYPELESS": "",
+ "B8G8R8X8_UNORM_SRGB": "",
+ "BC6H_TYPELESS": "",
+ "BC6H_UF16": "",
+ "BC6H_SF16": "",
+ "BC7_TYPELESS": "",
+ "BC7_UNORM": "",
+ "BC7_UNORM_SRGB": "",
+ "AYUV": "",
+ "Y410": "",
+ "Y416": "",
+ "NV12": "",
+ "P010": "",
+ "P016": "",
+ "420_OPAQUE": "",
+ "YUY2": "",
+ "Y210": "",
+ "Y216": "",
+ "NV11": "",
+ "AI44": "",
+ "IA44": "",
+ "P8": "",
+ "A8P8": "",
+ "B4G4R4A4_UNORM": ""
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp
new file mode 100644
index 000000000..66610cac9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/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 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.
+//
+// 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(Format::ID::A8_UNORM);
+ case DXGI_FORMAT_AI44:
+ break;
+ case DXGI_FORMAT_AYUV:
+ break;
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return Format::Get(Format::ID::B4G4R4A4_UNORM);
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ return Format::Get(Format::ID::B5G5R5A1_UNORM);
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ return Format::Get(Format::ID::B5G6R5_UNORM);
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ break;
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return Format::Get(Format::ID::B8G8R8A8_UNORM);
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ break;
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ break;
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ return Format::Get(Format::ID::B8G8R8X8_UNORM);
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ break;
+ case DXGI_FORMAT_BC1_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC1_UNORM:
+ return Format::Get(Format::ID::BC1_RGBA_UNORM_BLOCK);
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ break;
+ case DXGI_FORMAT_BC2_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC2_UNORM:
+ return Format::Get(Format::ID::BC2_RGBA_UNORM_BLOCK);
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ break;
+ case DXGI_FORMAT_BC3_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC3_UNORM:
+ return Format::Get(Format::ID::BC3_RGBA_UNORM_BLOCK);
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ break;
+ case DXGI_FORMAT_BC4_SNORM:
+ break;
+ case DXGI_FORMAT_BC4_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC4_UNORM:
+ break;
+ case DXGI_FORMAT_BC5_SNORM:
+ break;
+ case DXGI_FORMAT_BC5_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC5_UNORM:
+ break;
+ 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(Format::ID::D16_UNORM);
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ return Format::Get(Format::ID::D24_UNORM_S8_UINT);
+ case DXGI_FORMAT_D32_FLOAT:
+ return Format::Get(Format::ID::D32_FLOAT);
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ return Format::Get(Format::ID::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(Format::ID::R10G10B10A2_UINT);
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ return Format::Get(Format::ID::R10G10B10A2_UNORM);
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ break;
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ return Format::Get(Format::ID::R11G11B10_FLOAT);
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ return Format::Get(Format::ID::R16G16B16A16_FLOAT);
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ return Format::Get(Format::ID::R16G16B16A16_SINT);
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ return Format::Get(Format::ID::R16G16B16A16_SNORM);
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ return Format::Get(Format::ID::R16G16B16A16_UINT);
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ return Format::Get(Format::ID::R16G16B16A16_UNORM);
+ case DXGI_FORMAT_R16G16_FLOAT:
+ return Format::Get(Format::ID::R16G16_FLOAT);
+ case DXGI_FORMAT_R16G16_SINT:
+ return Format::Get(Format::ID::R16G16_SINT);
+ case DXGI_FORMAT_R16G16_SNORM:
+ return Format::Get(Format::ID::R16G16_SNORM);
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16G16_UINT:
+ return Format::Get(Format::ID::R16G16_UINT);
+ case DXGI_FORMAT_R16G16_UNORM:
+ return Format::Get(Format::ID::R16G16_UNORM);
+ case DXGI_FORMAT_R16_FLOAT:
+ return Format::Get(Format::ID::R16_FLOAT);
+ case DXGI_FORMAT_R16_SINT:
+ return Format::Get(Format::ID::R16_SINT);
+ case DXGI_FORMAT_R16_SNORM:
+ return Format::Get(Format::ID::R16_SNORM);
+ case DXGI_FORMAT_R16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16_UINT:
+ return Format::Get(Format::ID::R16_UINT);
+ case DXGI_FORMAT_R16_UNORM:
+ return Format::Get(Format::ID::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(Format::ID::R32G32B32A32_FLOAT);
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return Format::Get(Format::ID::R32G32B32A32_SINT);
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ return Format::Get(Format::ID::R32G32B32A32_UINT);
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ return Format::Get(Format::ID::R32G32B32_FLOAT);
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return Format::Get(Format::ID::R32G32B32_SINT);
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32B32_UINT:
+ return Format::Get(Format::ID::R32G32B32_UINT);
+ case DXGI_FORMAT_R32G32_FLOAT:
+ return Format::Get(Format::ID::R32G32_FLOAT);
+ case DXGI_FORMAT_R32G32_SINT:
+ return Format::Get(Format::ID::R32G32_SINT);
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32_UINT:
+ return Format::Get(Format::ID::R32G32_UINT);
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_FLOAT:
+ return Format::Get(Format::ID::R32_FLOAT);
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_SINT:
+ return Format::Get(Format::ID::R32_SINT);
+ case DXGI_FORMAT_R32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_UINT:
+ return Format::Get(Format::ID::R32_UINT);
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ return Format::Get(Format::ID::R8G8B8A8_SINT);
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ return Format::Get(Format::ID::R8G8B8A8_SNORM);
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ return Format::Get(Format::ID::R8G8B8A8_UINT);
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ return Format::Get(Format::ID::R8G8B8A8_UNORM);
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ return Format::Get(Format::ID::R8G8B8A8_UNORM_SRGB);
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ break;
+ case DXGI_FORMAT_R8G8_SINT:
+ return Format::Get(Format::ID::R8G8_SINT);
+ case DXGI_FORMAT_R8G8_SNORM:
+ return Format::Get(Format::ID::R8G8_SNORM);
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8G8_UINT:
+ return Format::Get(Format::ID::R8G8_UINT);
+ case DXGI_FORMAT_R8G8_UNORM:
+ return Format::Get(Format::ID::R8G8_UNORM);
+ case DXGI_FORMAT_R8_SINT:
+ return Format::Get(Format::ID::R8_SINT);
+ case DXGI_FORMAT_R8_SNORM:
+ return Format::Get(Format::ID::R8_SNORM);
+ case DXGI_FORMAT_R8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8_UINT:
+ return Format::Get(Format::ID::R8_UINT);
+ case DXGI_FORMAT_R8_UNORM:
+ return Format::Get(Format::ID::R8_UNORM);
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ return Format::Get(Format::ID::R9G9B9E5_SHAREDEXP);
+ case DXGI_FORMAT_UNKNOWN:
+ return Format::Get(Format::ID::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(Format::ID::NONE);
+}
+
+} // namespace d3d11_angle
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json
new file mode 100755
index 000000000..dce0997d9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json
@@ -0,0 +1,1279 @@
+[
+ {
+ "DXGI_FORMAT_UNKNOWN":
+ {
+ "texture2D": "never",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32G32B32A32_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32G32B32A32_FLOAT":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0check10_1always",
+ "renderTarget": "always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "always"
+ },
+ "DXGI_FORMAT_R32G32B32A32_UINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32G32B32A32_SINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32G32B32_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32G32B32_FLOAT":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "11_0check",
+ "renderTarget": "check",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32G32B32_UINT":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "check",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32G32B32_SINT":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "check",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R16G16B16A16_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R16G16B16A16_FLOAT":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "9_3check_10_0always",
+ "renderTarget": "always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "always"
+ },
+ "DXGI_FORMAT_R16G16B16A16_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "always",
+ "renderTarget": "always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "always"
+ },
+ "DXGI_FORMAT_R16G16B16A16_UINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R16G16B16A16_SNORM":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "10_0",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R16G16B16A16_SINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32G32_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32G32_FLOAT":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0check10_1always",
+ "renderTarget": "always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R32G32_UINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32G32_SINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32G8X24_TYPELESS":
+ {
+ "texture2D": "10_0",
+ "texture3D": "never",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_D32_FLOAT_S8X24_UINT":
+ {
+ "texture2D": "always",
+ "texture3D": "never",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "check",
+ "depthStencil": "10_0",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "never",
+ "textureCube": "always",
+ "shaderSample": "10_0check10_1always",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_X32_TYPELESS_G8X24_UINT":
+ {
+ "texture2D": "always",
+ "texture3D": "never",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R10G10B10A2_TYPELESS":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R10G10B10A2_UNORM":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "10_0",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R10G10B10A2_UINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R11G11B10_FLOAT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "10_0",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R8G8B8A8_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R8G8B8A8_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "always",
+ "renderTarget": "always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "always"
+ },
+ "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "always",
+ "renderTarget": "always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "always"
+ },
+ "DXGI_FORMAT_R8G8B8A8_UINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R8G8B8A8_SNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "always",
+ "renderTarget": "always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R8G8B8A8_SINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R16G16_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R16G16_FLOAT":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0",
+ "renderTarget": "always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "always"
+ },
+ "DXGI_FORMAT_R16G16_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "always",
+ "renderTarget": "always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "always"
+ },
+ "DXGI_FORMAT_R16G16_UINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R16G16_SNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "always",
+ "renderTarget": "always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R16G16_SINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32_TYPELESS":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_D32_FLOAT":
+ {
+ "texture2D": "always",
+ "texture3D": "never",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "check",
+ "depthStencil": "10_0",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32_FLOAT":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0check10_1always",
+ "renderTarget": "always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "always"
+ },
+ "DXGI_FORMAT_R32_UINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R32_SINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R24G8_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "never",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_D24_UNORM_S8_UINT":
+ {
+ "texture2D": "always",
+ "texture3D": "never",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "check",
+ "depthStencil": "always"
+ },
+ "DXGI_FORMAT_R24_UNORM_X8_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "never",
+ "textureCube": "always",
+ "shaderSample": "10_0check10_1always",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_X24_TYPELESS_G8_UINT":
+ {
+ "texture2D": "always",
+ "texture3D": "never",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R8G8_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R8G8_UNORM":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "9_3check_10_0always",
+ "renderTarget": "9_3check_10_0always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R8G8_UINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R8G8_SNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "always",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R8G8_SINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R16_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R16_FLOAT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "10_0",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_D16_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "never",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "check",
+ "depthStencil": "always",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R16_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "always",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R16_UINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R16_SNORM":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "10_0",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R16_SINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R8_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R8_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "always",
+ "renderTarget": "9_3check_10_0always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R8_UINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R8_SNORM":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "10_0",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R8_SINT":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "never",
+ "renderTarget": "10_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_A8_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0",
+ "renderTarget": "always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
+ },
+ "DXGI_FORMAT_R1_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "11_0",
+ "textureCube": "11_0",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R9G9B9E5_SHAREDEXP":
+ {
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "10_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R8G8_B8G8_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_G8R8_G8B8_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC1_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC1_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "always",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC1_UNORM_SRGB":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC2_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC2_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "always",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC2_UNORM_SRGB":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC3_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC3_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "always",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC3_UNORM_SRGB":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC4_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC4_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC4_SNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC5_TYPELESS":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC5_UNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC5_SNORM":
+ {
+ "texture2D": "always",
+ "texture3D": "always",
+ "textureCube": "always",
+ "shaderSample": "10_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_B5G6R5_UNORM":
+ {
+ "texture2D": "dxgi1_2",
+ "texture3D": "dxgi1_2",
+ "textureCube": "dxgi1_2",
+ "shaderSample": "dxgi1_2",
+ "renderTarget": "dxgi1_2",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "dxgi1_2"
+ },
+ "DXGI_FORMAT_B5G5R5A1_UNORM":
+ {
+ "texture2D": "dxgi1_2",
+ "texture3D": "dxgi1_2",
+ "textureCube": "dxgi1_2",
+ "shaderSample": "dxgi1_2",
+ "renderTarget": "check",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "dxgi1_2"
+ },
+ "DXGI_FORMAT_B8G8R8A8_UNORM":
+ {
+ "texture2D": "check",
+ "texture3D": "check",
+ "textureCube": "check",
+ "shaderSample": "9_3always_10_0check11_0always",
+ "renderTarget": "9_3always_10_0check11_0always",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "always"
+ },
+ "DXGI_FORMAT_B8G8R8X8_UNORM":
+ {
+ "texture2D": "check",
+ "texture3D": "check",
+ "textureCube": "check",
+ "shaderSample": "10_0check11_0always",
+ "renderTarget": "11_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM":
+ {
+ "texture2D": "check",
+ "texture3D": "check",
+ "textureCube": "never",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_B8G8R8A8_TYPELESS":
+ {
+ "texture2D": "check",
+ "texture3D": "check",
+ "textureCube": "check",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB":
+ {
+ "texture2D": "check",
+ "texture3D": "check",
+ "textureCube": "check",
+ "shaderSample": "10_0check11_0always",
+ "renderTarget": "11_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_B8G8R8X8_TYPELESS":
+ {
+ "texture2D": "check",
+ "texture3D": "check",
+ "textureCube": "check",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_B8G8R8X8_UNORM_SRGB":
+ {
+ "texture2D": "check",
+ "texture3D": "check",
+ "textureCube": "check",
+ "shaderSample": "10_0check11_0always",
+ "renderTarget": "11_0",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC6H_TYPELESS":
+ {
+ "texture2D": "11_0",
+ "texture3D": "11_0",
+ "textureCube": "11_0",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC6H_UF16":
+ {
+ "texture2D": "11_0",
+ "texture3D": "11_0",
+ "textureCube": "11_0",
+ "shaderSample": "11_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC6H_SF16":
+ {
+ "texture2D": "11_0",
+ "texture3D": "11_0",
+ "textureCube": "11_0",
+ "shaderSample": "11_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC7_TYPELESS":
+ {
+ "texture2D": "11_0",
+ "texture3D": "11_0",
+ "textureCube": "11_0",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC7_UNORM":
+ {
+ "texture2D": "11_0",
+ "texture3D": "11_0",
+ "textureCube": "11_0",
+ "shaderSample": "11_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_BC7_UNORM_SRGB":
+ {
+ "texture2D": "11_0",
+ "texture3D": "11_0",
+ "textureCube": "11_0",
+ "shaderSample": "11_0",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_AYUV":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "11_1",
+ "renderTarget": "11_1",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_Y410":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "11_1",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_Y416":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "11_1",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_NV12":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "11_1",
+ "renderTarget": "11_1",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_P010":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "11_1",
+ "renderTarget": "11_1",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_P016":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "11_1",
+ "renderTarget": "11_1",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_420_OPAQUE":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_YUY2":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "11_1",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_Y210":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "11_1",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_Y216":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "11_1",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_NV11":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "11_1",
+ "renderTarget": "11_1",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_AI44":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_IA44":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_P8":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_A8P8":
+ {
+ "texture2D": "11_1",
+ "texture3D": "never",
+ "textureCube": "never",
+ "shaderSample": "never",
+ "renderTarget": "never",
+ "multisampleRT": "never",
+ "depthStencil": "never",
+ "mipAutoGen": "never"
+ },
+ "DXGI_FORMAT_B4G4R4A4_UNORM":
+ {
+ "texture2D": "dxgi1_2",
+ "texture3D": "dxgi1_2",
+ "textureCube": "dxgi1_2",
+ "shaderSample": "dxgi1_2",
+ "renderTarget": "check",
+ "multisampleRT": "check",
+ "depthStencil": "never",
+ "mipAutoGen": "dxgi1_2"
+ }
+ }
+]
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp
new file mode 100755
index 000000000..d202ce130
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp
@@ -0,0 +1,2447 @@
+// 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/d3d/d3d11/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_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(0, 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_RT, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_AI44:
+ {
+ 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_AYUV:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, 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(0, F_DS | F_MIPGEN, 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(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_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_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_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_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_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_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_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_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(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_NV12:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P010:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P016:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P8:
+ {
+ 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_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_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y216:
+ {
+ 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_Y410:
+ {
+ 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_Y416:
+ {
+ 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_YUY2:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 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_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(0, 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(0, 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(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, 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(0, F_DS | F_MIPGEN, 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_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(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_NV12:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P010:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P016:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P8:
+ {
+ 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_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_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y216:
+ {
+ 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_Y410:
+ {
+ 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_Y416:
+ {
+ 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_YUY2:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 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_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(0, 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(0, 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(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, 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(0, F_DS | F_MIPGEN, 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_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(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_NV12:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P010:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P016:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P8:
+ {
+ 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_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_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y216:
+ {
+ 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_Y410:
+ {
+ 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_Y416:
+ {
+ 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_YUY2:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 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_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(0, 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(0, 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(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, 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_RT | F_SAMPLE, F_DS | F_MIPGEN, 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_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(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_NV12:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P010:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P016:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P8:
+ {
+ 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_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_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y216:
+ {
+ 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_Y410:
+ {
+ 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_Y416:
+ {
+ 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_YUY2:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+
+ default:
+ UNREACHABLE();
+ return GetDefaultSupport();
+ }
+ // clang-format on
+}
+
+}
+
+#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);
+ default:
+ return GetDefaultSupport();
+ }
+}
+
+} // namespace d3d11
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h
new file mode 100755
index 000000000..4abae478b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h
@@ -0,0 +1,49 @@
+//
+// 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_D3D_D3D11_DXGISUPPORTTABLE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_DXGISUPPORTTABLE_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_D3D_D3D11_DXGISUPPORTTABLE_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
new file mode 100755
index 000000000..695ad468d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
@@ -0,0 +1,1023 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// 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/d3d/d3d11/copyvertex.h"
+#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.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(NULL)
+{
+}
+
+constexpr VertexFormat::VertexFormat(VertexConversionType conversionTypeIn,
+ DXGI_FORMAT nativeFormatIn,
+ VertexCopyFunction copyFunctionIn)
+ : conversionType(conversionTypeIn), nativeFormat(nativeFormatIn), copyFunction(copyFunctionIn)
+{
+}
+
+const VertexFormat *GetVertexFormatInfo_FL_9_3(gl::VertexFormatType vertexFormatType)
+{
+ // 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 (vertexFormatType)
+ {
+ // GL_BYTE -- unnormalized
+ case gl::VERTEX_FORMAT_SBYTE1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT,
+ &Copy8SintTo16SintVertexData<1, 2>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT,
+ &Copy8SintTo16SintVertexData<2, 2>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT,
+ &Copy8SintTo16SintVertexData<3, 4>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE4:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT,
+ &Copy8SintTo16SintVertexData<4, 4>);
+ return &info;
+ }
+
+ // GL_BYTE -- normalized
+ case gl::VERTEX_FORMAT_SBYTE1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM,
+ &Copy8SnormTo16SnormVertexData<1, 2>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE2_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM,
+ &Copy8SnormTo16SnormVertexData<2, 2>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE3_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM,
+ &Copy8SnormTo16SnormVertexData<3, 4>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE4_NORM:
+ {
+ 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 gl::VERTEX_FORMAT_UBYTE1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 1, 4, 1>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE2:
+ {
+ 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 gl::VERTEX_FORMAT_UBYTE1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM,
+ &CopyNativeVertexData<GLubyte, 1, 4, UINT8_MAX>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE2_NORM:
+ {
+ 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 gl::VERTEX_FORMAT_SSHORT1:
+ {
+ 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 gl::VERTEX_FORMAT_SSHORT1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM,
+ &CopyNativeVertexData<GLshort, 1, 2, 0>);
+ return &info;
+ }
+
+ // GL_UNSIGNED_SHORT -- un-normalized
+ case gl::VERTEX_FORMAT_USHORT1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 1, 2, false>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_USHORT2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 2, 2, false>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_USHORT3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 3, 3, false>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_USHORT4:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 4, 4, false>);
+ return &info;
+ }
+
+ // GL_UNSIGNED_SHORT -- normalized
+ case gl::VERTEX_FORMAT_USHORT1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 1, 2, true>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_USHORT2_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 2, 2, true>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_USHORT3_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 3, 3, true>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_USHORT4_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 4, 4, true>);
+ 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 gl::VERTEX_FORMAT_FIXED1:
+ {
+ 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 gl::VERTEX_FORMAT_FLOAT1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 1, 2, 0>);
+ return &info;
+ }
+
+ default:
+ return nullptr;
+ }
+}
+
+const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D3D_FEATURE_LEVEL featureLevel)
+{
+ if (featureLevel == D3D_FEATURE_LEVEL_9_3)
+ {
+ const VertexFormat *result = GetVertexFormatInfo_FL_9_3(vertexFormatType);
+ if (result)
+ {
+ return *result;
+ }
+ }
+
+ switch (vertexFormatType)
+ {
+ //
+ // Float formats
+ //
+
+ // GL_BYTE -- un-normalized
+ case gl::VERTEX_FORMAT_SBYTE1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT,
+ &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT,
+ &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT,
+ &CopyNativeVertexData<GLbyte, 3, 4, 1>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE4:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT,
+ &CopyNativeVertexData<GLbyte, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_BYTE -- normalized
+ case gl::VERTEX_FORMAT_SBYTE1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM,
+ &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE2_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM,
+ &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE3_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM,
+ &CopyNativeVertexData<GLbyte, 3, 4, INT8_MAX>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE4_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM,
+ &CopyNativeVertexData<GLbyte, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_BYTE -- un-normalized
+ case gl::VERTEX_FORMAT_UBYTE1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT,
+ &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT,
+ &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 3, 4, 1>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE4:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_BYTE -- normalized
+ case gl::VERTEX_FORMAT_UBYTE1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM,
+ &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE2_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM,
+ &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE3_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM,
+ &CopyNativeVertexData<GLubyte, 3, 4, UINT8_MAX>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE4_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM,
+ &CopyNativeVertexData<GLubyte, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_SHORT -- un-normalized
+ case gl::VERTEX_FORMAT_SSHORT1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT,
+ &CopyNativeVertexData<GLshort, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SSHORT2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT,
+ &CopyNativeVertexData<GLshort, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SSHORT3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyNativeVertexData<GLshort, 3, 4, 1>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SSHORT4:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyNativeVertexData<GLshort, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_SHORT -- normalized
+ case gl::VERTEX_FORMAT_SSHORT1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM,
+ &CopyNativeVertexData<GLshort, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SSHORT2_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM,
+ &CopyNativeVertexData<GLshort, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SSHORT3_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM,
+ &CopyNativeVertexData<GLshort, 3, 4, INT16_MAX>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SSHORT4_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM,
+ &CopyNativeVertexData<GLshort, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_SHORT -- un-normalized
+ case gl::VERTEX_FORMAT_USHORT1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT,
+ &CopyNativeVertexData<GLushort, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_USHORT2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT,
+ &CopyNativeVertexData<GLushort, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_USHORT3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT,
+ &CopyNativeVertexData<GLushort, 3, 4, 1>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_USHORT4:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT,
+ &CopyNativeVertexData<GLushort, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_SHORT -- normalized
+ case gl::VERTEX_FORMAT_USHORT1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM,
+ &CopyNativeVertexData<GLushort, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_USHORT2_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM,
+ &CopyNativeVertexData<GLushort, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_USHORT3_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM,
+ &CopyNativeVertexData<GLushort, 3, 4, UINT16_MAX>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_USHORT4_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM,
+ &CopyNativeVertexData<GLushort, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_INT -- un-normalized
+ case gl::VERTEX_FORMAT_SINT1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT,
+ &CopyNativeVertexData<GLint, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SINT2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT,
+ &CopyNativeVertexData<GLint, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SINT3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT,
+ &CopyNativeVertexData<GLint, 3, 3, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SINT4:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT,
+ &CopyNativeVertexData<GLint, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_INT -- normalized
+ case gl::VERTEX_FORMAT_SINT1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT,
+ &CopyTo32FVertexData<GLint, 1, 1, true>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SINT2_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyTo32FVertexData<GLint, 2, 2, true>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SINT3_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyTo32FVertexData<GLint, 3, 3, true>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SINT4_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyTo32FVertexData<GLint, 4, 4, true>);
+ return info;
+ }
+
+ // GL_UNSIGNED_INT -- un-normalized
+ case gl::VERTEX_FORMAT_UINT1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT,
+ &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UINT2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT,
+ &CopyNativeVertexData<GLuint, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UINT3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT,
+ &CopyNativeVertexData<GLuint, 3, 3, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UINT4:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT,
+ &CopyNativeVertexData<GLuint, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_INT -- normalized
+ case gl::VERTEX_FORMAT_UINT1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT,
+ &CopyTo32FVertexData<GLuint, 1, 1, true>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UINT2_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyTo32FVertexData<GLuint, 2, 2, true>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UINT3_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyTo32FVertexData<GLuint, 3, 3, true>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UINT4_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyTo32FVertexData<GLuint, 4, 4, true>);
+ return info;
+ }
+
+ // GL_FIXED
+ case gl::VERTEX_FORMAT_FIXED1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT,
+ &Copy32FixedTo32FVertexData<1, 1>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_FIXED2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &Copy32FixedTo32FVertexData<2, 2>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_FIXED3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &Copy32FixedTo32FVertexData<3, 3>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_FIXED4:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &Copy32FixedTo32FVertexData<4, 4>);
+ return info;
+ }
+
+ // GL_HALF_FLOAT
+ case gl::VERTEX_FORMAT_HALF1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT,
+ &CopyNativeVertexData<GLhalf, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_HALF2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT,
+ &CopyNativeVertexData<GLhalf, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_HALF3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT,
+ &CopyNativeVertexData<GLhalf, 3, 4, gl::Float16One>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_HALF4:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT,
+ &CopyNativeVertexData<GLhalf, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_FLOAT
+ case gl::VERTEX_FORMAT_FLOAT1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_FLOAT2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_FLOAT3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 3, 3, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_FLOAT4:
+ {
+ 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 gl::VERTEX_FORMAT_SINT210:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyXYZ10W2ToXYZW32FVertexData<true, false, true>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SINT210_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyXYZ10W2ToXYZW32FVertexData<true, true, true>);
+ return info;
+ }
+
+ // GL_UNSIGNED_INT_2_10_10_10_REV
+ case gl::VERTEX_FORMAT_UINT210:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyXYZ10W2ToXYZW32FVertexData<false, false, true>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UINT210_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM,
+ &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ return info;
+ }
+
+ //
+ // Integer Formats
+ //
+
+ // GL_BYTE
+ case gl::VERTEX_FORMAT_SBYTE1_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT,
+ &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE2_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT,
+ &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE3_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT,
+ &CopyNativeVertexData<GLbyte, 3, 4, 1>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE4_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT,
+ &CopyNativeVertexData<GLbyte, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_BYTE
+ case gl::VERTEX_FORMAT_UBYTE1_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT,
+ &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE2_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT,
+ &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE3_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 3, 4, 1>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE4_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_SHORT
+ case gl::VERTEX_FORMAT_SSHORT1_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT,
+ &CopyNativeVertexData<GLshort, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SSHORT2_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT,
+ &CopyNativeVertexData<GLshort, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SSHORT3_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyNativeVertexData<GLshort, 3, 4, 1>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SSHORT4_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyNativeVertexData<GLshort, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_SHORT
+ case gl::VERTEX_FORMAT_USHORT1_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT,
+ &CopyNativeVertexData<GLushort, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_USHORT2_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT,
+ &CopyNativeVertexData<GLushort, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_USHORT3_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT,
+ &CopyNativeVertexData<GLushort, 3, 4, 1>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_USHORT4_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT,
+ &CopyNativeVertexData<GLushort, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_INT
+ case gl::VERTEX_FORMAT_SINT1_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT,
+ &CopyNativeVertexData<GLint, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SINT2_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT,
+ &CopyNativeVertexData<GLint, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SINT3_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT,
+ &CopyNativeVertexData<GLint, 3, 3, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_SINT4_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT,
+ &CopyNativeVertexData<GLint, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_INT
+ case gl::VERTEX_FORMAT_UINT1_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT,
+ &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UINT2_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT,
+ &CopyNativeVertexData<GLuint, 2, 2, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UINT3_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT,
+ &CopyNativeVertexData<GLuint, 3, 3, 0>);
+ return info;
+ }
+ case gl::VERTEX_FORMAT_UINT4_INT:
+ {
+ 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 gl::VERTEX_FORMAT_SINT210_INT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyXYZ10W2ToXYZW32FVertexData<true, true, false>);
+ return info;
+ }
+
+ // GL_UNSIGNED_INT_2_10_10_10_REV
+ case gl::VERTEX_FORMAT_UINT210_INT:
+ {
+ 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/src/libANGLE/renderer/d3d/d3d11/formatutils11.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
new file mode 100755
index 000000000..3a9fd63df
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
@@ -0,0 +1,71 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// 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/renderer_utils.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.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 : angle::NonCopyable
+{
+ constexpr VertexFormat();
+ constexpr VertexFormat(VertexConversionType conversionType,
+ DXGI_FORMAT nativeFormat,
+ VertexCopyFunction copyFunction);
+
+ VertexConversionType conversionType;
+ DXGI_FORMAT nativeFormat;
+ VertexCopyFunction copyFunction;
+};
+
+const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType,
+ D3D_FEATURE_LEVEL featureLevel);
+
+// Auto-generated in dxgi_format_map_autogen.cpp.
+GLenum GetComponentType(DXGI_FORMAT dxgiFormat);
+
+} // namespace d3d11
+
+namespace d3d11_angle
+{
+const angle::Format &GetFormat(DXGI_FORMAT dxgiFormat);
+}
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_format_table.py b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_format_table.py
new file mode 100644
index 000000000..6c6d1906a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_format_table.py
@@ -0,0 +1,134 @@
+#!/usr/bin/python
+# 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.
+#
+# gen_dxgi_format_table.py:
+# Code generation for DXGI format map.
+
+from datetime import date
+import sys
+
+sys.path.append('../..')
+import angle_format
+
+template_cpp = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}.
+//
+// Copyright {copyright_year} The ANGLE Project 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)
+ {{
+{component_type_cases} default:
+ break;
+ }}
+
+ UNREACHABLE();
+ return GL_NONE;
+}}
+
+}} // namespace d3d11
+
+namespace d3d11_angle
+{{
+
+const Format &GetFormat(DXGI_FORMAT dxgiFormat)
+{{
+ switch (dxgiFormat)
+ {{
+{format_cases} default:
+ break;
+ }}
+
+ UNREACHABLE();
+ return Format::Get(Format::ID::NONE);
+}}
+
+}} // namespace d3d11_angle
+
+}} // namespace rx
+"""
+
+template_format_case = """ case DXGI_FORMAT_{dxgi_format}:
+ return {result};
+"""
+
+template_undefined_case = """ case DXGI_FORMAT_{dxgi_format}:
+ break;
+"""
+
+def format_case(dxgi_format, result):
+ return template_format_case.format(
+ dxgi_format = dxgi_format,
+ result = result)
+
+def undefined_case(dxgi_format):
+ return template_undefined_case.format(dxgi_format = dxgi_format)
+
+component_cases = ""
+format_cases = ""
+
+input_data = 'dxgi_format_data.json'
+
+dxgi_map = angle_format.load_json(input_data)
+
+types = {
+ 'SNORM': 'GL_SIGNED_NORMALIZED',
+ 'UNORM': 'GL_UNSIGNED_NORMALIZED',
+ 'SINT': 'GL_INT',
+ 'UINT': 'GL_UNSIGNED_INT',
+ 'FLOAT': 'GL_FLOAT',
+ 'SHAREDEXP': 'GL_FLOAT'
+}
+
+angle_to_gl = angle_format.load_inverse_table('../../angle_format_map.json')
+all_angle = angle_to_gl.keys()
+
+for dxgi_format, angle_format in sorted(dxgi_map.iteritems()):
+
+ found = [ctype in dxgi_format for ctype in types.keys()]
+ count = reduce((lambda a, b: int(a) + int(b)), found)
+
+ component_type = 'GL_NONE'
+
+ if count == 1:
+ gltype = next(gltype for ctype, gltype in types.iteritems() if ctype in dxgi_format)
+ component_cases += format_case(dxgi_format, gltype)
+ else:
+ component_cases += undefined_case(dxgi_format)
+
+ if angle_format == "":
+ angle_format = dxgi_format
+
+ if angle_format in all_angle:
+ angle_format = "Format::Get(Format::ID::" + angle_format + ")"
+ format_cases += format_case(dxgi_format, angle_format)
+ else:
+ format_cases += undefined_case(dxgi_format)
+
+with open('dxgi_format_map_autogen.cpp', 'wt') as out_file:
+ output_cpp = template_cpp.format(
+ script_name = sys.argv[0],
+ data_source_name = input_data,
+ copyright_year = date.today().year,
+ component_type_cases = component_cases,
+ format_cases = format_cases)
+ out_file.write(output_cpp)
+ out_file.close()
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_support_tables.py b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_support_tables.py
new file mode 100755
index 000000000..dba583f1e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_dxgi_support_tables.py
@@ -0,0 +1,281 @@
+#!/usr/bin/python
+# 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.
+#
+# gen_dxgi_support_tables.py:
+# Code generation for the DXGI support tables. Determines which formats
+# are natively support in D3D10+.
+#
+# MSDN links:
+# 10_0: https://msdn.microsoft.com/en-us/library/windows/desktop/cc627090.aspx
+# 10_1: https://msdn.microsoft.com/en-us/library/windows/desktop/cc627091.aspx
+# 11_0: https://msdn.microsoft.com/en-us/library/windows/desktop/ff471325.aspx
+# 11_1: https://msdn.microsoft.com/en-us/library/windows/desktop/hh404483.aspx
+
+import sys
+import json
+
+macro_prefix = 'F_'
+
+template = """// 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/d3d/d3d11/dxgi_support_table.h"
+
+#include "common/debug.h"
+
+namespace rx
+{{
+
+namespace d3d11
+{{
+
+#define {prefix}2D D3D11_FORMAT_SUPPORT_TEXTURE2D
+#define {prefix}3D D3D11_FORMAT_SUPPORT_TEXTURE3D
+#define {prefix}CUBE D3D11_FORMAT_SUPPORT_TEXTURECUBE
+#define {prefix}SAMPLE D3D11_FORMAT_SUPPORT_SHADER_SAMPLE
+#define {prefix}RT D3D11_FORMAT_SUPPORT_RENDER_TARGET
+#define {prefix}MS D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
+#define {prefix}DS D3D11_FORMAT_SUPPORT_DEPTH_STENCIL
+#define {prefix}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)
+ {{
+{table_data_9_3}
+ default:
+ UNREACHABLE();
+ return GetDefaultSupport();
+ }}
+ // clang-format on
+}}
+
+const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
+{{
+ // clang-format off
+ switch (dxgiFormat)
+ {{
+{table_data_10_0}
+ default:
+ UNREACHABLE();
+ return GetDefaultSupport();
+ }}
+ // clang-format on
+}}
+
+const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat)
+{{
+ // clang-format off
+ switch (dxgiFormat)
+ {{
+{table_data_10_1}
+ default:
+ UNREACHABLE();
+ return GetDefaultSupport();
+ }}
+ // clang-format on
+}}
+
+const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat)
+{{
+ // clang-format off
+ switch (dxgiFormat)
+ {{
+{table_data_11_0}
+ default:
+ UNREACHABLE();
+ return GetDefaultSupport();
+ }}
+ // clang-format on
+}}
+
+}}
+
+#undef {prefix}2D
+#undef {prefix}3D
+#undef {prefix}CUBE
+#undef {prefix}SAMPLE
+#undef {prefix}RT
+#undef {prefix}MS
+#undef {prefix}DS
+#undef {prefix}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);
+ default:
+ return GetDefaultSupport();
+ }}
+}}
+
+}} // namespace d3d11
+
+}} // namespace rx
+"""
+
+table_init = ""
+
+def do_format(format_data):
+ table_data = {'9_3': '', '10_0': '', '10_1': '', '11_0': ''}
+
+ json_flag_to_d3d = {
+ 'texture2D': macro_prefix + '2D',
+ 'texture3D': macro_prefix + '3D',
+ 'textureCube': macro_prefix + 'CUBE',
+ 'shaderSample': macro_prefix + 'SAMPLE',
+ 'renderTarget': macro_prefix + 'RT',
+ 'multisampleRT': macro_prefix + 'MS',
+ 'depthStencil': macro_prefix + 'DS',
+ 'mipAutoGen': macro_prefix + 'MIPGEN'
+ }
+
+ for format_name, format_support in sorted(format_data.iteritems()):
+
+ always_supported = set()
+ never_supported = set()
+ optionally_supported = set()
+ fl_9_3_supported = set()
+ fl_9_3_check = set()
+ fl_10_0_supported = set()
+ fl_10_1_supported = set()
+ fl_11_0_supported = set()
+ fl_11_0_check = set()
+ fl_10_0_check_10_1_supported = set()
+ fl_10_0_check_11_0_supported = set()
+
+ for json_flag, support in format_support.iteritems():
+
+ d3d_flag = [json_flag_to_d3d[json_flag]]
+
+ if support == 'check':
+ optionally_supported.update(d3d_flag)
+ elif support == 'always':
+ always_supported.update(d3d_flag)
+ elif support == 'never':
+ never_supported.update(d3d_flag)
+ elif support == '10_0':
+ fl_10_0_supported.update(d3d_flag)
+ elif support == '10_1':
+ fl_10_1_supported.update(d3d_flag)
+ elif support == '11_0':
+ fl_11_0_supported.update(d3d_flag)
+ elif support == '11_1':
+ # TODO(jmadill): D3D 11.1 handling
+ never_supported.update(d3d_flag)
+ elif support == 'dxgi1_2':
+ # TODO(jmadill): DXGI 1.2 handling.
+ always_supported.update(d3d_flag)
+ elif support == '10_0check10_1always':
+ fl_10_0_check_10_1_supported.update(d3d_flag)
+ elif support == '10_0check11_0always':
+ fl_10_0_check_11_0_supported.update(d3d_flag)
+ elif support == '11_0check':
+ fl_11_0_check.update(d3d_flag)
+ elif support == '9_3always_10_0check11_0always':
+ fl_9_3_supported.update(d3d_flag)
+ fl_10_0_check_11_0_supported.update(d3d_flag)
+ elif support == '9_3check_10_0always':
+ fl_9_3_check.update(d3d_flag)
+ fl_10_0_supported.update(d3d_flag)
+ else:
+ print("Data specification error: " + support)
+ sys.exit(1)
+
+ for feature_level in ['9_3', '10_0', '10_1', '11_0']:
+ always_for_fl = always_supported
+ optional_for_fl = optionally_supported
+ if feature_level == '9_3':
+ always_for_fl = fl_9_3_supported.union(always_for_fl)
+ optional_for_fl = fl_9_3_check.union(optional_for_fl)
+ elif feature_level == '10_0':
+ always_for_fl = fl_10_0_supported.union(always_for_fl)
+ optional_for_fl = fl_10_0_check_10_1_supported.union(optional_for_fl)
+ optional_for_fl = fl_10_0_check_11_0_supported.union(optional_for_fl)
+ elif feature_level == '10_1':
+ always_for_fl = fl_10_0_supported.union(always_for_fl)
+ always_for_fl = fl_10_1_supported.union(always_for_fl)
+ always_for_fl = fl_10_0_check_10_1_supported.union(always_for_fl)
+ optional_for_fl = fl_10_0_check_11_0_supported.union(optional_for_fl)
+ elif feature_level == '11_0':
+ always_for_fl = fl_10_0_supported.union(always_for_fl)
+ always_for_fl = fl_10_0_check_10_1_supported.union(always_for_fl)
+ always_for_fl = fl_10_0_check_11_0_supported.union(always_for_fl)
+ always_for_fl = fl_10_1_supported.union(always_for_fl)
+ always_for_fl = fl_11_0_supported.union(always_for_fl)
+
+ always = ' | '.join(sorted(always_for_fl))
+ never = ' | '.join(sorted(never_supported))
+ optional = ' | '.join(sorted(optional_for_fl))
+
+ if not always: always = '0'
+ if not never: never = '0'
+ if not optional: optional = '0'
+
+ table_data[feature_level] += ' case ' + format_name + ':\n'
+ table_data[feature_level] += ' {\n'
+ table_data[feature_level] += ' static const DXGISupport info(' + always + ', ' + never + ', ' + optional + ');\n'
+ table_data[feature_level] += ' return info;\n'
+ table_data[feature_level] += ' }\n'
+
+ return table_data
+
+def join_table_data(table_data_1, table_data_2):
+ return {'9_3': table_data_1['9_3'] + table_data_2['9_3'],
+ '10_0': table_data_1['10_0'] + table_data_2['10_0'],
+ '10_1': table_data_1['10_1'] + table_data_2['10_1'],
+ '11_0': table_data_1['11_0'] + table_data_2['11_0']}
+
+with open('dxgi_support_data.json') as dxgi_file:
+ file_data = dxgi_file.read()
+ dxgi_file.close()
+ json_data = json.loads(file_data)
+
+ table_data = {'9_3': '', '10_0': '', '10_1': '', '11_0': ''}
+
+ for format_data in json_data:
+ table_data = join_table_data(table_data, do_format(format_data))
+
+ out_data = template.format(prefix=macro_prefix,
+ table_data_9_3=table_data['9_3'],
+ table_data_10_0=table_data['10_0'],
+ table_data_10_1=table_data['10_1'],
+ table_data_11_0=table_data['11_0'])
+
+ with open('dxgi_support_table.cpp', 'wt') as out_file:
+ out_file.write(out_data)
+ out_file.close()
+
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
new file mode 100755
index 000000000..3c4b228e4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
@@ -0,0 +1,360 @@
+#!/usr/bin/python
+# 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.
+#
+# gen_texture_format_table.py:
+# Code generation for texture format map
+#
+
+from datetime import date
+import json
+import math
+import pprint
+import os
+import re
+import sys
+
+sys.path.append('../..')
+import angle_format
+
+template_texture_format_table_autogen_cpp = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}
+//
+// Copyright {copyright_year} The ANGLE Project 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)
+ {{
+{angle_format_info_cases}
+ default:
+ break;
+ }}
+ // clang-format on
+
+ UNREACHABLE();
+ static constexpr Format defaultInfo;
+ return defaultInfo;
+}}
+
+}} // namespace d3d11
+
+}} // namespace rx
+"""
+
+# TODO(oetuaho): Expand this code so that it could generate the gl format info tables as well.
+def gl_format_channels(internal_format):
+ if internal_format == 'GL_BGR5_A1_ANGLEX':
+ return 'bgra'
+ if internal_format == 'GL_R11F_G11F_B10F':
+ return 'rgb'
+ if internal_format == 'GL_RGB5_A1':
+ return 'rgba'
+ if internal_format.find('GL_RGB10_A2') == 0:
+ return 'rgba'
+
+ channels_pattern = re.compile('GL_(COMPRESSED_)?(SIGNED_)?(ETC\d_)?([A-Z]+)')
+ match = re.search(channels_pattern, internal_format)
+ channels_string = match.group(4)
+
+ if channels_string == 'ALPHA':
+ return 'a'
+ if channels_string == 'LUMINANCE':
+ if (internal_format.find('ALPHA') >= 0):
+ return 'la'
+ return 'l'
+ if channels_string == 'SRGB':
+ if (internal_format.find('ALPHA') >= 0):
+ return 'rgba'
+ return 'rgb'
+ if channels_string == 'DEPTH':
+ if (internal_format.find('STENCIL') >= 0):
+ return 'ds'
+ return 'd'
+ if channels_string == 'STENCIL':
+ return 's'
+ return channels_string.lower()
+
+def get_internal_format_initializer(internal_format, angle_format):
+ internal_format_initializer = 'nullptr'
+ gl_channels = gl_format_channels(internal_format)
+ gl_format_no_alpha = gl_channels == 'rgb' or gl_channels == 'l'
+ if gl_format_no_alpha and angle_format['channels'] == 'rgba':
+ if angle_format['texFormat'] == 'DXGI_FORMAT_BC1_UNORM':
+ # BC1 is a special case since the texture data determines whether each block has an alpha channel or not.
+ # This if statement is hit by COMPRESSED_RGB_S3TC_DXT1, which is a bit of a mess.
+ # TODO(oetuaho): Look into whether COMPRESSED_RGB_S3TC_DXT1 works right in general.
+ # Reference: https://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt
+ pass
+ elif 'componentType' not in angle_format:
+ raise ValueError('warning: internal format initializer could not be generated and may be needed for ' + internal_format)
+ elif angle_format['componentType'] == 'uint' and angle_format['bits']['red'] == 8:
+ internal_format_initializer = 'Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>'
+ elif angle_format['componentType'] == 'unorm' and angle_format['bits']['red'] == 8:
+ internal_format_initializer = 'Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>'
+ elif angle_format['componentType'] == 'unorm' and angle_format['bits']['red'] == 16:
+ internal_format_initializer = 'Initialize4ComponentData<GLubyte, 0x0000, 0x0000, 0x0000, 0xFFFF>'
+ elif angle_format['componentType'] == 'int' and angle_format['bits']['red'] == 8:
+ internal_format_initializer = 'Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>'
+ elif angle_format['componentType'] == 'snorm' and angle_format['bits']['red'] == 8:
+ internal_format_initializer = 'Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x7F>'
+ elif angle_format['componentType'] == 'snorm' and angle_format['bits']['red'] == 16:
+ internal_format_initializer = 'Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x7FFF>'
+ elif angle_format['componentType'] == 'float' and angle_format['bits']['red'] == 16:
+ internal_format_initializer = 'Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>'
+ elif angle_format['componentType'] == 'uint' and angle_format['bits']['red'] == 16:
+ internal_format_initializer = 'Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>'
+ elif angle_format['componentType'] == 'int' and angle_format['bits']['red'] == 16:
+ internal_format_initializer = 'Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>'
+ elif angle_format['componentType'] == 'float' and angle_format['bits']['red'] == 32:
+ internal_format_initializer = 'Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>'
+ elif angle_format['componentType'] == 'int' and angle_format['bits']['red'] == 32:
+ internal_format_initializer = 'Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>'
+ elif angle_format['componentType'] == 'uint' and angle_format['bits']['red'] == 32:
+ internal_format_initializer = 'Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>'
+ else:
+ raise ValueError('warning: internal format initializer could not be generated and may be needed for ' + internal_format)
+
+ return internal_format_initializer
+
+def get_swizzle_format_id(internal_format, angle_format):
+ angle_format_id = angle_format["formatName"]
+ if (internal_format == 'GL_NONE') or (angle_format_id == 'NONE'):
+ return 'GL_NONE'
+
+ elif 'swizzleFormat' in angle_format:
+ # For some special formats like compressed formats that don't have a clearly defined number
+ # of bits per channel, swizzle format needs to be specified manually.
+ return angle_format['swizzleFormat']
+
+ if 'bits' not in angle_format:
+ raise ValueError('no bits information for determining swizzleformat for format: ' + internal_format)
+
+ bits = angle_format['bits']
+ max_component_bits = max(bits.itervalues())
+ channels_different = not all([component_bits == bits.itervalues().next() for component_bits in bits.itervalues()])
+
+ # The format itself can be used for swizzles if it can be accessed as a render target and
+ # sampled and the bit count for all 4 channels is the same.
+ if "rtvFormat" in angle_format and "srvFormat" in angle_format and not channels_different and len(angle_format['channels']) == 4:
+ return angle_format["glInternalFormat"] if "glInternalFormat" in angle_format else internal_format
+
+ b = int(math.ceil(float(max_component_bits) / 8) * 8)
+
+ # Depth formats need special handling, since combined depth/stencil formats don't have a clearly
+ # defined component type.
+ if angle_format['channels'].find('d') >= 0:
+ if b == 24 or b == 32:
+ return 'GL_RGBA32F'
+ if b == 16:
+ return 'GL_RGBA16_EXT'
+
+ if b == 24:
+ raise ValueError('unexpected 24-bit format when determining swizzleformat for format: ' + internal_format)
+
+ if 'componentType' not in angle_format:
+ raise ValueError('no component type information for determining swizzleformat for format: ' + internal_format)
+
+ component_type = angle_format['componentType']
+
+ swizzle = "GL_RGBA" + str(b)
+
+ if component_type == 'uint':
+ swizzle += "I"
+ elif component_type == 'int':
+ swizzle += "I"
+ elif component_type == 'unorm':
+ if (b == 16):
+ swizzle += "_EXT"
+ elif component_type == 'snorm':
+ swizzle += "_SNORM"
+ if (b == 16):
+ swizzle += "_EXT"
+ elif component_type == 'float':
+ swizzle += "F"
+ if (b == 16):
+ swizzle += "_EXT"
+ else:
+ raise ValueError('could not determine swizzleformat based on componentType for format: ' + internal_format)
+
+ return swizzle
+
+def get_blit_srv_format(angle_format):
+ if 'channels' not in angle_format:
+ return 'DXGI_FORMAT_UNKNOWN'
+ if 'r' in angle_format['channels'] and angle_format['componentType'] in ['int', 'uint']:
+ return angle_format['rtvFormat']
+
+ return angle_format["srvFormat"] if "srvFormat" in angle_format else "DXGI_FORMAT_UNKNOWN"
+
+
+format_entry_template = """{space}{{
+{space} static constexpr Format info({internalFormat},
+{space} angle::Format::ID::{formatName},
+{space} {texFormat},
+{space} {srvFormat},
+{space} {rtvFormat},
+{space} {dsvFormat},
+{space} {blitSRVFormat},
+{space} {swizzleFormat},
+{space} {initializer});
+{space} return info;
+{space}}}
+"""
+
+split_format_entry_template = """{space} {condition}
+{space} {{
+{space} static constexpr Format info({internalFormat},
+{space} angle::Format::ID::{formatName},
+{space} {texFormat},
+{space} {srvFormat},
+{space} {rtvFormat},
+{space} {dsvFormat},
+{space} {blitSRVFormat},
+{space} {swizzleFormat},
+{space} {initializer});
+{space} return info;
+{space} }}
+"""
+
+def json_to_table_data(internal_format, format_name, prefix, json):
+
+ table_data = ""
+
+ parsed = {
+ "space": " ",
+ "internalFormat": internal_format,
+ "formatName": format_name,
+ "texFormat": "DXGI_FORMAT_UNKNOWN",
+ "srvFormat": "DXGI_FORMAT_UNKNOWN",
+ "rtvFormat": "DXGI_FORMAT_UNKNOWN",
+ "dsvFormat": "DXGI_FORMAT_UNKNOWN",
+ "condition": prefix,
+ }
+
+ for k, v in json.iteritems():
+ parsed[k] = v
+
+ # Derived values.
+ parsed["blitSRVFormat"] = get_blit_srv_format(parsed)
+ parsed["swizzleFormat"] = get_swizzle_format_id(internal_format, parsed)
+ parsed["initializer"] = get_internal_format_initializer(internal_format, json)
+
+ if len(prefix) > 0:
+ return split_format_entry_template.format(**parsed)
+ else:
+ return format_entry_template.format(**parsed)
+
+def parse_json_angle_format_case(format_name, angle_format, json_data):
+ supported_case = {}
+ unsupported_case = {}
+ support_test = None
+ fallback = None
+
+ for k, v in angle_format.iteritems():
+ if k == "FL10Plus":
+ assert support_test is None
+ support_test = "OnlyFL10Plus(deviceCaps)"
+ for k2, v2 in v.iteritems():
+ supported_case[k2] = v2
+ elif k == "FL9_3":
+ split = True
+ for k2, v2 in v.iteritems():
+ unsupported_case[k2] = v2
+ elif k == "supportTest":
+ assert support_test is None
+ support_test = v
+ elif k == "fallbackFormat":
+ fallback = v
+ else:
+ supported_case[k] = v
+ unsupported_case[k] = v
+
+ if fallback != None:
+ unsupported_case, _, _ = parse_json_angle_format_case(
+ fallback, json_data[fallback], json_data)
+ unsupported_case["formatName"] = fallback
+
+ if support_test != None:
+ return supported_case, unsupported_case, support_test
+ else:
+ return supported_case, None, None
+
+def parse_json_into_switch_angle_format_string(json_map, json_data):
+ table_data = ''
+
+ for internal_format, format_name in sorted(json_map.iteritems()):
+
+ if format_name not in json_data:
+ continue
+
+ angle_format = json_data[format_name]
+
+ supported_case, unsupported_case, support_test = parse_json_angle_format_case(
+ format_name, angle_format, json_data)
+
+ table_data += ' case ' + internal_format + ':\n'
+
+ if support_test != None:
+ table_data += " {\n"
+ table_data += json_to_table_data(internal_format, format_name, "if (" + support_test + ")", supported_case)
+ table_data += json_to_table_data(internal_format, format_name, "else", unsupported_case)
+ table_data += " }\n"
+ else:
+ table_data += json_to_table_data(internal_format, format_name, "", supported_case)
+
+ return table_data
+
+def reject_duplicate_keys(pairs):
+ found_keys = {}
+ for key, value in pairs:
+ if key in found_keys:
+ raise ValueError("duplicate key: %r" % (key,))
+ else:
+ found_keys[key] = value
+ return found_keys
+
+json_map = angle_format.load_with_override(os.path.abspath('texture_format_map.json'))
+data_source_name = 'texture_format_data.json'
+
+with open(data_source_name) as texture_format_json_file:
+ texture_format_data = texture_format_json_file.read()
+ texture_format_json_file.close()
+ json_data = json.loads(texture_format_data, object_pairs_hook=angle_format.reject_duplicate_keys)
+
+ angle_format_cases = parse_json_into_switch_angle_format_string(json_map, json_data)
+ output_cpp = template_texture_format_table_autogen_cpp.format(
+ script_name = sys.argv[0],
+ copyright_year = date.today().year,
+ angle_format_info_cases = angle_format_cases,
+ data_source_name = data_source_name)
+ with open('texture_format_table_autogen.cpp', 'wt') as out_file:
+ out_file.write(output_cpp)
+ out_file.close()
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
new file mode 100755
index 000000000..5bb51feca
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -0,0 +1,2096 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// renderer11_utils.cpp: Conversion functions and other utility routines
+// specific to the D3D11 renderer.
+
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include <algorithm>
+
+#include "common/debug.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
+#include "libANGLE/renderer/driver_utils.h"
+
+namespace rx
+{
+
+namespace d3d11_gl
+{
+namespace
+{
+
+// 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%x", dxgiFormat);
+ }
+ }
+
+ return ((supportedBits & supportMask) == supportMask);
+ }
+
+ private:
+ ID3D11Device *mDevice;
+ D3D_FEATURE_LEVEL mFeatureLevel;
+};
+
+gl::TextureCaps GenerateTextureFormatCaps(GLint 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::GetInternalFormatInfo(internalFormat);
+
+ UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D;
+ if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0)
+ {
+ texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE;
+ if (maxClientVersion > 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.renderable =
+ (support.query(formatInfo.rtvFormat, D3D11_FORMAT_SUPPORT_RENDER_TARGET)) ||
+ (support.query(formatInfo.dsvFormat, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL));
+
+ 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+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;
+ }
+}
+
+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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+size_t 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;
+ }
+}
+
+} // 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 3;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ return 3;
+
+ 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 2;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, const Renderer11DeviceCaps &renderer11DeviceCaps, gl::Caps *caps,
+ gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions, gl::Limitations *limitations)
+{
+ GLuint maxSamples = 0;
+ D3D_FEATURE_LEVEL featureLevel = renderer11DeviceCaps.featureLevel;
+ const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
+ for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat)
+ {
+ gl::TextureCaps textureCaps = GenerateTextureFormatCaps(GetMaximumClientVersion(featureLevel), *internalFormat, device, renderer11DeviceCaps);
+ textureCapsMap->insert(*internalFormat, textureCaps);
+
+ maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
+
+ if (gl::GetInternalFormatInfo(*internalFormat).compressed)
+ {
+ caps->compressedTextureFormats.push_back(*internalFormat);
+ }
+ }
+
+ // 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 = static_cast<GLuint>(GetMaximum3DTextureSize(featureLevel));
+ caps->max2DTextureSize = static_cast<GLuint>(GetMaximum2DTextureSize(featureLevel));
+ caps->maxCubeMapTextureSize = static_cast<GLuint>(GetMaximumCubeMapTextureSize(featureLevel));
+ caps->maxArrayTextureLayers = static_cast<GLuint>(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 = static_cast<GLuint>(GetMaximumSimultaneousRenderTargets(featureLevel));
+ caps->maxColorAttachments =
+ static_cast<GLuint>(GetMaximumSimultaneousRenderTargets(featureLevel));
+
+ // D3D11 has the same limit for viewport width and height
+ caps->maxViewportWidth = static_cast<GLuint>(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 = static_cast<GLuint>(GetMaximumDrawIndexedIndexCount(featureLevel));
+ caps->maxElementsVertices = static_cast<GLuint>(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 = static_cast<GLuint>(GetMaximumVertexInputSlots(featureLevel));
+ caps->maxVertexUniformComponents =
+ static_cast<GLuint>(GetMaximumVertexUniformVectors(featureLevel)) * 4;
+ caps->maxVertexUniformVectors =
+ static_cast<GLuint>(GetMaximumVertexUniformVectors(featureLevel));
+ caps->maxVertexUniformBlocks = static_cast<GLuint>(GetMaximumVertexUniformBlocks(featureLevel));
+ caps->maxVertexOutputComponents =
+ static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel)) * 4;
+ caps->maxVertexTextureImageUnits =
+ static_cast<GLuint>(GetMaximumVertexTextureUnits(featureLevel));
+
+ // Fragment shader limits
+ caps->maxFragmentUniformComponents =
+ static_cast<GLuint>(GetMaximumPixelUniformVectors(featureLevel)) * 4;
+ caps->maxFragmentUniformVectors =
+ static_cast<GLuint>(GetMaximumPixelUniformVectors(featureLevel));
+ caps->maxFragmentUniformBlocks =
+ static_cast<GLuint>(GetMaximumPixelUniformBlocks(featureLevel));
+ caps->maxFragmentInputComponents =
+ static_cast<GLuint>(GetMaximumPixelInputVectors(featureLevel)) * 4;
+ caps->maxTextureImageUnits = static_cast<GLuint>(GetMaximumPixelTextureUnits(featureLevel));
+ caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel);
+ caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel);
+
+ // Aggregate shader limits
+ caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks;
+ caps->maxUniformBlockSize = GetMaximumConstantBufferSize(featureLevel);
+
+ // 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->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks;
+ caps->maxCombinedVertexUniformComponents = (static_cast<GLint64>(caps->maxVertexUniformBlocks) * static_cast<GLint64>(caps->maxUniformBlockSize / 4)) +
+ static_cast<GLint64>(caps->maxVertexUniformComponents);
+ caps->maxCombinedFragmentUniformComponents = (static_cast<GLint64>(caps->maxFragmentUniformBlocks) * static_cast<GLint64>(caps->maxUniformBlockSize / 4)) +
+ static_cast<GLint64>(caps->maxFragmentUniformComponents);
+ caps->maxVaryingComponents =
+ static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel)) * 4;
+ caps->maxVaryingVectors = static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel));
+ caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
+
+ // Transform feedback limits
+ caps->maxTransformFeedbackInterleavedComponents =
+ static_cast<GLuint>(GetMaximumStreamOutputInterleavedComponents(featureLevel));
+ caps->maxTransformFeedbackSeparateAttributes =
+ static_cast<GLuint>(GetMaximumStreamOutputBuffers(featureLevel));
+ caps->maxTransformFeedbackSeparateComponents =
+ static_cast<GLuint>(GetMaximumStreamOutputSeparateComponents(featureLevel));
+
+ // Multisample limits
+ caps->maxSamples = maxSamples;
+
+ // GL extension support
+ extensions->setTextureExtensionSupport(*textureCapsMap);
+ extensions->elementIndexUint = true;
+ extensions->getProgramBinary = true;
+ extensions->rgb8rgba8 = true;
+ extensions->readFormatBGRA = true;
+ extensions->pixelBufferObject = true;
+ extensions->mapBuffer = true;
+ extensions->mapBufferRange = true;
+ extensions->textureNPOT = GetNPOTTextureSupport(featureLevel);
+ extensions->drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1;
+ extensions->textureStorage = true;
+ extensions->textureFilterAnisotropic = true;
+ extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel);
+ extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel);
+ extensions->fence = GetEventQuerySupport(featureLevel);
+ extensions->timerQuery = false; // Unimplemented
+ extensions->disjointTimerQuery = true;
+ extensions->queryCounterBitsTimeElapsed = 64;
+ extensions->queryCounterBitsTimestamp =
+ 0; // Timestamps cannot be supported due to D3D11 limitations
+ extensions->robustness = true;
+ extensions->blendMinMax = true;
+ extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel);
+ extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel);
+ extensions->instancedArrays = GetInstancingSupport(featureLevel);
+ extensions->packReverseRowOrder = true;
+ extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel);
+ extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel);
+ extensions->fragDepth = true;
+ extensions->textureUsage = true; // This could be false since it has no effect in D3D11
+ extensions->discardFramebuffer = true;
+ extensions->translatedShaderSource = true;
+ extensions->fboRenderMipmap = false;
+ extensions->debugMarker = true;
+ extensions->eglImage = true;
+ extensions->eglImageExternal = true;
+ extensions->eglImageExternalEssl3 = true;
+ extensions->eglStreamConsumerExternal = true;
+ extensions->unpackSubimage = true;
+ extensions->packSubimage = true;
+ extensions->lossyETCDecode = true;
+ extensions->syncQuery = GetEventQuerySupport(featureLevel);
+ extensions->copyTexture = true;
+ extensions->copyCompressedTexture = true;
+
+ // 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;
+
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ // 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;
+ 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, GLenum cullMode)
+{
+ D3D11_CULL_MODE cull = D3D11_CULL_NONE;
+
+ if (cullEnabled)
+ {
+ switch (cullMode)
+ {
+ case GL_FRONT:
+ cull = D3D11_CULL_FRONT;
+ break;
+ case GL_BACK:
+ cull = D3D11_CULL_BACK;
+ break;
+ case GL_FRONT_AND_BACK:
+ 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_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(GLenum queryType)
+{
+ switch (queryType)
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ return D3D11_QUERY_OCCLUSION;
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ return D3D11_QUERY_SO_STATISTICS;
+ case GL_TIME_ELAPSED_EXT:
+ // Two internal queries are also created for begin/end timestamps
+ return D3D11_QUERY_TIMESTAMP_DISJOINT;
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ return D3D11_QUERY_EVENT;
+ default:
+ UNREACHABLE();
+ return D3D11_QUERY_EVENT;
+ }
+}
+
+} // 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);
+
+ 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>(dxgiFormatInfo.blockWidth) ||
+ *requestHeight < static_cast<GLsizei>(dxgiFormatInfo.blockHeight))
+ {
+ while (*requestWidth % dxgiFormatInfo.blockWidth != 0 || *requestHeight % dxgiFormatInfo.blockHeight != 0)
+ {
+ *requestWidth <<= 1;
+ *requestHeight <<= 1;
+ upsampleCount++;
+ }
+ }
+ *levelOffset = upsampleCount;
+}
+
+void GenerateInitialTextureData(GLint internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ GLuint width,
+ GLuint height,
+ GLuint depth,
+ GLuint mipLevels,
+ std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData,
+ std::vector<std::vector<BYTE>> *outData)
+{
+ const d3d11::Format &d3dFormatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
+ ASSERT(d3dFormatInfo.dataInitializerFunction != NULL);
+
+ const d3d11::DXGIFormatSize &dxgiFormatInfo =
+ d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat);
+
+ outSubresourceData->resize(mipLevels);
+ outData->resize(mipLevels);
+
+ for (unsigned int i = 0; i < mipLevels; i++)
+ {
+ unsigned int mipWidth = std::max(width >> i, 1U);
+ unsigned int mipHeight = std::max(height >> i, 1U);
+ unsigned int mipDepth = std::max(depth >> i, 1U);
+
+ unsigned int rowWidth = dxgiFormatInfo.pixelBytes * mipWidth;
+ unsigned int imageSize = rowWidth * height;
+
+ outData->at(i).resize(rowWidth * mipHeight * mipDepth);
+ d3dFormatInfo.dataInitializerFunction(mipWidth, mipHeight, mipDepth, outData->at(i).data(), rowWidth, imageSize);
+
+ outSubresourceData->at(i).pSysMem = outData->at(i).data();
+ outSubresourceData->at(i).SysMemPitch = rowWidth;
+ outSubresourceData->at(i).SysMemSlicePitch = imageSize;
+ }
+}
+
+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;
+}
+
+HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
+{
+#if defined(_DEBUG)
+ UINT existingDataSize = 0;
+ resource->GetPrivateData(WKPDID_D3DDebugObjectName, &existingDataSize, nullptr);
+ // Don't check the HRESULT- if it failed then that probably just means that no private data
+ // exists yet
+
+ if (existingDataSize > 0)
+ {
+ // In some cases, ANGLE will try to apply two names to one object, which causes
+ // a D3D SDK Layers warning. This can occur if, for example, you 'create' two objects
+ // (e.g.Rasterizer States) with identical DESCs on the same device. D3D11 will optimize
+ // these calls and return the same object both times.
+ static const char *multipleNamesUsed = "Multiple names set by ANGLE";
+
+ // Remove the existing name
+ HRESULT hr = resource->SetPrivateData(WKPDID_D3DDebugObjectName, 0, nullptr);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Apply the new name
+ return resource->SetPrivateData(WKPDID_D3DDebugObjectName,
+ static_cast<unsigned int>(strlen(multipleNamesUsed)),
+ multipleNamesUsed);
+ }
+ else
+ {
+ return resource->SetPrivateData(WKPDID_D3DDebugObjectName,
+ static_cast<unsigned int>(strlen(name)), name);
+ }
+#else
+ return S_OK;
+#endif
+}
+
+LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
+ size_t inputDescLen,
+ const BYTE *byteCode,
+ size_t byteCodeLen,
+ const char *debugName)
+ : mInputDesc(inputDescLen),
+ mByteCodeLen(byteCodeLen),
+ mByteCode(byteCode),
+ mDebugName(debugName)
+{
+ memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen);
+}
+
+ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device)
+{
+ checkAssociatedDevice(device);
+
+ if (mResource == nullptr)
+ {
+ HRESULT result =
+ device->CreateInputLayout(&mInputDesc[0], static_cast<UINT>(mInputDesc.size()),
+ mByteCode, mByteCodeLen, &mResource);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mResource, mDebugName);
+ }
+
+ return mResource;
+}
+
+LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName)
+ : mDesc(desc), mDebugName(debugName)
+{
+}
+
+ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device)
+{
+ checkAssociatedDevice(device);
+
+ if (mResource == nullptr)
+ {
+ HRESULT result = device->CreateBlendState(&mDesc, &mResource);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mResource, mDebugName);
+ }
+
+ return mResource;
+}
+
+WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
+ const DXGI_ADAPTER_DESC &adapterDesc)
+{
+ bool is9_3 = (deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
+
+ WorkaroundsD3D workarounds;
+ workarounds.mrtPerfWorkaround = true;
+ workarounds.setDataFasterThanImageUpload = true;
+ workarounds.zeroMaxLodWorkaround = is9_3;
+ workarounds.useInstancedPointSpriteEmulation = is9_3;
+
+ // TODO(jmadill): Narrow problematic driver range.
+ if (IsNvidia(adapterDesc.VendorId))
+ {
+ if (deviceCaps.driverVersion.valid())
+ {
+ 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.
+ workarounds.depthStencilBlitExtraCopy = (part1 <= 13u && part2 < 6881);
+ }
+ else
+ {
+ workarounds.depthStencilBlitExtraCopy = true;
+ }
+ }
+
+ // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
+ workarounds.expandIntegerPowExpressions = true;
+
+ workarounds.flushAfterEndingTransformFeedback = IsNvidia(adapterDesc.VendorId);
+ workarounds.getDimensionsIgnoresBaseLevel = IsNvidia(adapterDesc.VendorId);
+
+ workarounds.preAddTexelFetchOffsets = IsIntel(adapterDesc.VendorId);
+ workarounds.disableB5G6R5Support = IsIntel(adapterDesc.VendorId);
+ workarounds.rewriteUnaryMinusOperator =
+ IsIntel(adapterDesc.VendorId) &&
+ (IsBroadwell(adapterDesc.DeviceId) || IsHaswell(adapterDesc.DeviceId));
+ workarounds.emulateIsnanFloat =
+ IsIntel(adapterDesc.VendorId) && IsSkylake(adapterDesc.DeviceId);
+ workarounds.callClearTwice =
+ IsIntel(adapterDesc.VendorId) && IsSkylake(adapterDesc.DeviceId);
+
+ // TODO(jmadill): Disable when we have a fixed driver version.
+ workarounds.emulateTinyStencilTextures = IsAMD(adapterDesc.VendorId);
+
+ // 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).
+ if (deviceCaps.featureLevel < D3D_FEATURE_LEVEL_10_1)
+ {
+ workarounds.emulateTinyStencilTextures = false;
+ }
+
+ workarounds.useSystemMemoryForConstantBuffers = IsIntel(adapterDesc.VendorId);
+
+ return workarounds;
+}
+
+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::TextureHelper11()
+ : mTextureType(GL_NONE),
+ mFormat(DXGI_FORMAT_UNKNOWN),
+ mFormatSet(nullptr),
+ mSampleCount(0),
+ mTexture2D(nullptr),
+ mTexture3D(nullptr)
+{
+}
+
+TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy)
+ : mTextureType(toCopy.mTextureType),
+ mExtents(toCopy.mExtents),
+ mFormat(toCopy.mFormat),
+ mFormatSet(toCopy.mFormatSet),
+ mSampleCount(toCopy.mSampleCount),
+ mTexture2D(toCopy.mTexture2D),
+ mTexture3D(toCopy.mTexture3D)
+{
+ toCopy.reset();
+}
+
+// static
+TextureHelper11 TextureHelper11::MakeAndReference(ID3D11Resource *genericResource,
+ const d3d11::Format &formatSet)
+{
+ TextureHelper11 newHelper;
+ newHelper.mFormatSet = &formatSet;
+ newHelper.mTexture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(genericResource);
+ newHelper.mTexture3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(genericResource);
+ newHelper.mTextureType = newHelper.mTexture2D ? GL_TEXTURE_2D : GL_TEXTURE_3D;
+ newHelper.initDesc();
+ return newHelper;
+}
+
+// static
+TextureHelper11 TextureHelper11::MakeAndPossess2D(ID3D11Texture2D *texToOwn,
+ const d3d11::Format &formatSet)
+{
+ TextureHelper11 newHelper;
+ newHelper.mFormatSet = &formatSet;
+ newHelper.mTexture2D = texToOwn;
+ newHelper.mTextureType = GL_TEXTURE_2D;
+ newHelper.initDesc();
+ return newHelper;
+}
+
+// static
+TextureHelper11 TextureHelper11::MakeAndPossess3D(ID3D11Texture3D *texToOwn,
+ const d3d11::Format &formatSet)
+{
+ TextureHelper11 newHelper;
+ newHelper.mFormatSet = &formatSet;
+ newHelper.mTexture3D = texToOwn;
+ newHelper.mTextureType = GL_TEXTURE_3D;
+ newHelper.initDesc();
+ return newHelper;
+}
+
+void TextureHelper11::initDesc()
+{
+ if (mTextureType == GL_TEXTURE_2D)
+ {
+ ASSERT(!mTexture3D);
+ D3D11_TEXTURE2D_DESC desc2D;
+ mTexture2D->GetDesc(&desc2D);
+
+ mExtents.width = static_cast<int>(desc2D.Width);
+ mExtents.height = static_cast<int>(desc2D.Height);
+ mExtents.depth = 1;
+ mFormat = desc2D.Format;
+ mSampleCount = desc2D.SampleDesc.Count;
+ }
+ else
+ {
+ ASSERT(mTexture3D && mTextureType == GL_TEXTURE_3D);
+ D3D11_TEXTURE3D_DESC desc3D;
+ mTexture3D->GetDesc(&desc3D);
+
+ mExtents.width = static_cast<int>(desc3D.Width);
+ mExtents.height = static_cast<int>(desc3D.Height);
+ mExtents.depth = static_cast<int>(desc3D.Depth);
+ mFormat = desc3D.Format;
+ mSampleCount = 1;
+ }
+ ASSERT(mFormatSet && mFormat == mFormatSet->texFormat);
+}
+
+TextureHelper11::~TextureHelper11()
+{
+ SafeRelease(mTexture2D);
+ SafeRelease(mTexture3D);
+}
+
+ID3D11Resource *TextureHelper11::getResource() const
+{
+ return mTexture2D ? static_cast<ID3D11Resource *>(mTexture2D)
+ : static_cast<ID3D11Resource *>(mTexture3D);
+}
+
+TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&texture)
+{
+ SafeRelease(mTexture2D);
+ SafeRelease(mTexture3D);
+
+ mTextureType = texture.mTextureType;
+ mExtents = texture.mExtents;
+ mFormat = texture.mFormat;
+ mFormatSet = texture.mFormatSet;
+ mSampleCount = texture.mSampleCount;
+ mTexture2D = texture.mTexture2D;
+ mTexture3D = texture.mTexture3D;
+ texture.reset();
+ return *this;
+}
+
+void TextureHelper11::reset()
+{
+ mTextureType = GL_NONE;
+ mExtents = gl::Extents();
+ mFormat = DXGI_FORMAT_UNKNOWN;
+ mFormatSet = nullptr;
+ mSampleCount = 0;
+ mTexture2D = nullptr;
+ mTexture3D = nullptr;
+}
+
+bool TextureHelper11::valid() const
+{
+ return (mTextureType != GL_NONE);
+}
+
+gl::ErrorOrResult<TextureHelper11> CreateStagingTexture(GLenum textureType,
+ const d3d11::Format &formatSet,
+ const gl::Extents &size,
+ StagingAccess readAndWriteAccess,
+ ID3D11Device *device)
+{
+ if (textureType == GL_TEXTURE_2D)
+ {
+ 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;
+ }
+
+ ID3D11Texture2D *stagingTex = nullptr;
+ HRESULT result = device->CreateTexture2D(&stagingDesc, nullptr, &stagingTex);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "CreateStagingTextureFor failed, HRESULT: 0x%X.",
+ result);
+ }
+
+ return TextureHelper11::MakeAndPossess2D(stagingTex, formatSet);
+ }
+ ASSERT(textureType == GL_TEXTURE_3D);
+
+ 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;
+
+ ID3D11Texture3D *stagingTex = nullptr;
+ HRESULT result = device->CreateTexture3D(&stagingDesc, nullptr, &stagingTex);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "CreateStagingTextureFor failed, HRESULT: 0x%X.",
+ result);
+ }
+
+ return TextureHelper11::MakeAndPossess3D(stagingTex, formatSet);
+}
+
+bool UsePresentPathFast(const Renderer11 *renderer,
+ const gl::FramebufferAttachment *framebufferAttachment)
+{
+ if (framebufferAttachment == nullptr)
+ {
+ return false;
+ }
+
+ return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT &&
+ renderer->presentPathFastEnabled());
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
new file mode 100755
index 000000000..463571cf9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
@@ -0,0 +1,419 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace rx
+{
+class Renderer11;
+class RenderTarget11;
+struct WorkaroundsD3D;
+struct Renderer11DeviceCaps;
+
+using RenderTargetArray = std::array<RenderTarget11 *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+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, GLenum 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(GLenum queryType);
+
+} // namespace gl_d3d11
+
+namespace d3d11_gl
+{
+
+unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel);
+
+unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel);
+
+GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel);
+void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, const Renderer11DeviceCaps &renderer11DeviceCaps, gl::Caps *caps,
+ gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions, gl::Limitations *limitations);
+
+} // 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);
+
+void GenerateInitialTextureData(GLint internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ GLuint width,
+ GLuint height,
+ GLuint depth,
+ GLuint mipLevels,
+ std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData,
+ std::vector<std::vector<BYTE>> *outData);
+
+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);
+
+template <typename T>
+struct PositionDepthColorVertex
+{
+ float x, y, z;
+ T r, g, b, a;
+};
+
+template <typename T>
+void SetPositionDepthColorVertex(PositionDepthColorVertex<T>* vertex, float x, float y, float z,
+ const gl::Color<T> &color)
+{
+ vertex->x = x;
+ vertex->y = y;
+ vertex->z = z;
+ vertex->r = color.red;
+ vertex->g = color.green;
+ vertex->b = color.blue;
+ vertex->a = color.alpha;
+}
+
+HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name);
+
+template <typename outType>
+outType* DynamicCastComObject(IUnknown* object)
+{
+ outType *outObject = NULL;
+ HRESULT result = object->QueryInterface(__uuidof(outType), reinterpret_cast<void**>(&outObject));
+ if (SUCCEEDED(result))
+ {
+ return outObject;
+ }
+ else
+ {
+ SafeRelease(outObject);
+ return NULL;
+ }
+}
+
+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;
+ }
+}
+
+inline ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name)
+{
+ ID3D11VertexShader *vs = nullptr;
+ HRESULT result = device->CreateVertexShader(byteCode, N, nullptr, &vs);
+ ASSERT(SUCCEEDED(result));
+ if (SUCCEEDED(result))
+ {
+ SetDebugName(vs, name);
+ return vs;
+ }
+ return nullptr;
+}
+
+template <unsigned int N>
+ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name)
+{
+ return CompileVS(device, byteCode, N, name);
+}
+
+inline ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name)
+{
+ ID3D11GeometryShader *gs = nullptr;
+ HRESULT result = device->CreateGeometryShader(byteCode, N, nullptr, &gs);
+ ASSERT(SUCCEEDED(result));
+ if (SUCCEEDED(result))
+ {
+ SetDebugName(gs, name);
+ return gs;
+ }
+ return nullptr;
+}
+
+template <unsigned int N>
+ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name)
+{
+ return CompileGS(device, byteCode, N, name);
+}
+
+inline ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name)
+{
+ ID3D11PixelShader *ps = nullptr;
+ HRESULT result = device->CreatePixelShader(byteCode, N, nullptr, &ps);
+ ASSERT(SUCCEEDED(result));
+ if (SUCCEEDED(result))
+ {
+ SetDebugName(ps, name);
+ return ps;
+ }
+ return nullptr;
+}
+
+template <unsigned int N>
+ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name)
+{
+ return CompilePS(device, byteCode, N, name);
+}
+
+template <typename ResourceType>
+class LazyResource : public angle::NonCopyable
+{
+ public:
+ LazyResource() : mResource(nullptr), mAssociatedDevice(nullptr) {}
+ virtual ~LazyResource() { release(); }
+
+ virtual ResourceType *resolve(ID3D11Device *device) = 0;
+ void release() { SafeRelease(mResource); }
+
+ protected:
+ void checkAssociatedDevice(ID3D11Device *device);
+
+ ResourceType *mResource;
+ ID3D11Device *mAssociatedDevice;
+};
+
+template <typename ResourceType>
+void LazyResource<ResourceType>::checkAssociatedDevice(ID3D11Device *device)
+{
+ ASSERT(mAssociatedDevice == nullptr || device == mAssociatedDevice);
+ mAssociatedDevice = device;
+}
+
+template <typename D3D11ShaderType>
+class LazyShader final : public LazyResource<D3D11ShaderType>
+{
+ public:
+ // All parameters must be constexpr. Not supported in VS2013.
+ LazyShader(const BYTE *byteCode,
+ size_t byteCodeSize,
+ const char *name)
+ : mByteCode(byteCode),
+ mByteCodeSize(byteCodeSize),
+ mName(name)
+ {
+ }
+
+ D3D11ShaderType *resolve(ID3D11Device *device) override;
+
+ private:
+ const BYTE *mByteCode;
+ size_t mByteCodeSize;
+ const char *mName;
+};
+
+template <>
+inline ID3D11VertexShader *LazyShader<ID3D11VertexShader>::resolve(ID3D11Device *device)
+{
+ checkAssociatedDevice(device);
+ if (mResource == nullptr)
+ {
+ mResource = CompileVS(device, mByteCode, mByteCodeSize, mName);
+ }
+ return mResource;
+}
+
+template <>
+inline ID3D11GeometryShader *LazyShader<ID3D11GeometryShader>::resolve(ID3D11Device *device)
+{
+ checkAssociatedDevice(device);
+ if (mResource == nullptr)
+ {
+ mResource = CompileGS(device, mByteCode, mByteCodeSize, mName);
+ }
+ return mResource;
+}
+
+template <>
+inline ID3D11PixelShader *LazyShader<ID3D11PixelShader>::resolve(ID3D11Device *device)
+{
+ checkAssociatedDevice(device);
+ if (mResource == nullptr)
+ {
+ mResource = CompilePS(device, mByteCode, mByteCodeSize, mName);
+ }
+ return mResource;
+}
+
+class LazyInputLayout final : public LazyResource<ID3D11InputLayout>
+{
+ public:
+ LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
+ size_t inputDescLen,
+ const BYTE *byteCode,
+ size_t byteCodeLen,
+ const char *debugName);
+
+ ID3D11InputLayout *resolve(ID3D11Device *device) override;
+
+ private:
+ std::vector<D3D11_INPUT_ELEMENT_DESC> mInputDesc;
+ size_t mByteCodeLen;
+ const BYTE *mByteCode;
+ const char *mDebugName;
+};
+
+class LazyBlendState final : public LazyResource<ID3D11BlendState>
+{
+ public:
+ LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName);
+
+ ID3D11BlendState *resolve(ID3D11Device *device) 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);
+ }
+}
+
+WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
+ const DXGI_ADAPTER_DESC &adapterDesc);
+
+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);
+} // namespace d3d11
+
+// A helper class which wraps a 2D or 3D texture.
+class TextureHelper11 : angle::NonCopyable
+{
+ public:
+ TextureHelper11();
+ TextureHelper11(TextureHelper11 &&toCopy);
+ ~TextureHelper11();
+ TextureHelper11 &operator=(TextureHelper11 &&texture);
+
+ static TextureHelper11 MakeAndReference(ID3D11Resource *genericResource,
+ const d3d11::Format &formatSet);
+ static TextureHelper11 MakeAndPossess2D(ID3D11Texture2D *texToOwn,
+ const d3d11::Format &formatSet);
+ static TextureHelper11 MakeAndPossess3D(ID3D11Texture3D *texToOwn,
+ const d3d11::Format &formatSet);
+
+ GLenum getTextureType() const { return mTextureType; }
+ gl::Extents getExtents() const { return mExtents; }
+ DXGI_FORMAT getFormat() const { return mFormat; }
+ const d3d11::Format &getFormatSet() const { return *mFormatSet; }
+ int getSampleCount() const { return mSampleCount; }
+ ID3D11Texture2D *getTexture2D() const { return mTexture2D; }
+ ID3D11Texture3D *getTexture3D() const { return mTexture3D; }
+ ID3D11Resource *getResource() const;
+ bool valid() const;
+
+ private:
+ void reset();
+ void initDesc();
+
+ GLenum mTextureType;
+ gl::Extents mExtents;
+ DXGI_FORMAT mFormat;
+ const d3d11::Format *mFormatSet;
+ int mSampleCount;
+ ID3D11Texture2D *mTexture2D;
+ ID3D11Texture3D *mTexture3D;
+};
+
+enum class StagingAccess
+{
+ READ,
+ READ_WRITE,
+};
+
+gl::ErrorOrResult<TextureHelper11> CreateStagingTexture(GLenum textureType,
+ const d3d11::Format &formatSet,
+ const gl::Extents &size,
+ StagingAccess readAndWriteAccess,
+ ID3D11Device *device);
+
+bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer);
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl
new file mode 100755
index 000000000..c43734f6a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl
@@ -0,0 +1,77 @@
+Buffer<float4> Buffer4F : register(t0);
+Buffer<int4> Buffer4I : register(t0);
+Buffer<uint4> Buffer4UI : register(t0);
+
+struct VS_OUTPUT
+{
+ float4 position : SV_Position;
+ uint index : TEXCOORD0;
+ uint slice : LAYER;
+};
+
+struct GS_OUTPUT
+{
+ float4 position : SV_Position;
+ uint index : TEXCOORD0;
+ uint slice : SV_RenderTargetArrayIndex;
+};
+
+cbuffer BufferCopyParams : register(b0)
+{
+ uint FirstPixelOffset;
+ uint PixelsPerRow;
+ uint RowStride;
+ uint RowsPerSlice;
+ float2 PositionOffset;
+ float2 PositionScale;
+ int2 TexLocationOffset;
+ int2 TexLocationScale;
+ uint FirstSlice;
+}
+
+void ComputePositionAndIndex(uint vertexID, out VS_OUTPUT outVertex)
+{
+ uint PixelsPerSlice = PixelsPerRow * RowsPerSlice;
+ uint SliceStride = RowStride * RowsPerSlice;
+
+ uint slice = vertexID / PixelsPerSlice;
+ uint sliceOffset = slice * PixelsPerSlice;
+ uint row = (vertexID - sliceOffset) / PixelsPerRow;
+ uint col = vertexID - sliceOffset - (row * PixelsPerRow);
+
+ float2 coords = float2(float(col), float(row));
+
+ outVertex.position = float4(PositionOffset + PositionScale * coords, 0.0f, 1.0f);
+ outVertex.index = FirstPixelOffset + slice * SliceStride + row * RowStride + col;
+ outVertex.slice = FirstSlice + slice;
+}
+
+void VS_BufferToTexture(in uint vertexID : SV_VertexID, out VS_OUTPUT outVertex)
+{
+ ComputePositionAndIndex(vertexID, outVertex);
+}
+
+[maxvertexcount(1)]
+void GS_BufferToTexture(point VS_OUTPUT inVertex[1], inout PointStream<GS_OUTPUT> outStream)
+{
+ GS_OUTPUT outVertex;
+ outVertex.position = inVertex[0].position;
+ outVertex.index = inVertex[0].index;
+ outVertex.slice = inVertex[0].slice;
+ outStream.Append(outVertex);
+}
+
+float4 PS_BufferToTexture_4F(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target
+{
+ return Buffer4F.Load(inIndex);
+}
+
+int4 PS_BufferToTexture_4I(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target
+{
+ return Buffer4I.Load(inIndex);
+}
+
+uint4 PS_BufferToTexture_4UI(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target
+{
+ return Buffer4UI.Load(inIndex);
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl
new file mode 100755
index 000000000..2b3e1ebe4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl
@@ -0,0 +1,119 @@
+// Assume we are in SM4+, which has 8 color outputs
+
+void VS_ClearFloat( in float3 inPosition : POSITION, in float4 inColor : COLOR,
+ out float4 outPosition : SV_POSITION, out float4 outColor : COLOR)
+{
+ outPosition = float4(inPosition, 1.0f);
+ outColor = inColor;
+}
+
+struct PS_OutputFloat
+{
+ float4 color0 : SV_TARGET0;
+ float4 color1 : SV_TARGET1;
+ float4 color2 : SV_TARGET2;
+ float4 color3 : SV_TARGET3;
+ float4 color4 : SV_TARGET4;
+ float4 color5 : SV_TARGET5;
+ float4 color6 : SV_TARGET6;
+ float4 color7 : SV_TARGET7;
+};
+
+PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR)
+{
+ PS_OutputFloat outColor;
+ outColor.color0 = inColor;
+ outColor.color1 = inColor;
+ outColor.color2 = inColor;
+ outColor.color3 = inColor;
+ outColor.color4 = inColor;
+ outColor.color5 = inColor;
+ outColor.color6 = inColor;
+ outColor.color7 = inColor;
+ return outColor;
+}
+
+struct PS_OutputFloat_FL9
+{
+ float4 color0 : SV_TARGET0;
+ float4 color1 : SV_TARGET1;
+ float4 color2 : SV_TARGET2;
+ float4 color3 : SV_TARGET3;
+};
+
+PS_OutputFloat_FL9 PS_ClearFloat_FL9(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR)
+{
+ PS_OutputFloat_FL9 outColor;
+ outColor.color0 = inColor;
+ outColor.color1 = inColor;
+ outColor.color2 = inColor;
+ outColor.color3 = inColor;
+ return outColor;
+}
+
+void VS_ClearUint( in float3 inPosition : POSITION, in uint4 inColor : COLOR,
+ out float4 outPosition : SV_POSITION, out uint4 outColor : COLOR)
+{
+ outPosition = float4(inPosition, 1.0f);
+ outColor = inColor;
+}
+
+struct PS_OutputUint
+{
+ uint4 color0 : SV_TARGET0;
+ uint4 color1 : SV_TARGET1;
+ uint4 color2 : SV_TARGET2;
+ uint4 color3 : SV_TARGET3;
+ uint4 color4 : SV_TARGET4;
+ uint4 color5 : SV_TARGET5;
+ uint4 color6 : SV_TARGET6;
+ uint4 color7 : SV_TARGET7;
+};
+
+PS_OutputUint PS_ClearUint(in float4 inPosition : SV_POSITION, in uint4 inColor : COLOR)
+{
+ PS_OutputUint outColor;
+ outColor.color0 = inColor;
+ outColor.color1 = inColor;
+ outColor.color2 = inColor;
+ outColor.color3 = inColor;
+ outColor.color4 = inColor;
+ outColor.color5 = inColor;
+ outColor.color6 = inColor;
+ outColor.color7 = inColor;
+ return outColor;
+}
+
+
+void VS_ClearSint( in float3 inPosition : POSITION, in int4 inColor : COLOR,
+ out float4 outPosition : SV_POSITION, out int4 outColor : COLOR)
+{
+ outPosition = float4(inPosition, 1.0f);
+ outColor = inColor;
+}
+
+struct PS_OutputSint
+{
+ int4 color0 : SV_TARGET0;
+ int4 color1 : SV_TARGET1;
+ int4 color2 : SV_TARGET2;
+ int4 color3 : SV_TARGET3;
+ int4 color4 : SV_TARGET4;
+ int4 color5 : SV_TARGET5;
+ int4 color6 : SV_TARGET6;
+ int4 color7 : SV_TARGET7;
+};
+
+PS_OutputSint PS_ClearSint(in float4 inPosition : SV_POSITION, in int4 inColor : COLOR)
+{
+ PS_OutputSint outColor;
+ outColor.color0 = inColor;
+ outColor.color1 = inColor;
+ outColor.color2 = inColor;
+ outColor.color3 = inColor;
+ outColor.color4 = inColor;
+ outColor.color5 = inColor;
+ outColor.color6 = inColor;
+ outColor.color7 = inColor;
+ return outColor;
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
new file mode 100755
index 000000000..21024e3b7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
@@ -0,0 +1,145 @@
+Texture2D<float4> TextureF : register(t0);
+Texture2D<uint4> TextureUI : register(t0);
+Texture2D<int4> TextureI : register(t0);
+
+SamplerState Sampler : register(s0);
+
+void VS_Passthrough2D( in float2 inPosition : POSITION, in float2 inTexCoord : TEXCOORD0,
+ out float4 outPosition : SV_POSITION, out float2 outTexCoord : TEXCOORD0)
+{
+ outPosition = float4(inPosition, 0.0f, 1.0f);
+ outTexCoord = inTexCoord;
+}
+
+float PS_PassthroughDepth2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_DEPTH
+{
+ return TextureF.Sample(Sampler, inTexCoord).r;
+}
+
+float4 PS_PassthroughRGBA2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return TextureF.Sample(Sampler, inTexCoord).rgba;
+}
+
+float4 PS_PassthroughRGBAPremultiply2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ color.rgb *= color.a;
+ return color;
+}
+
+float4 PS_PassthroughRGBAUnmultiply2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ if (color.a > 0.0f)
+ {
+ color.rgb /= color.a;
+ }
+ return color;
+}
+
+uint4 PS_PassthroughRGBA2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint2 size;
+ TextureUI.GetDimensions(size.x, size.y);
+
+ return TextureUI.Load(int3(size * inTexCoord, 0)).rgba;
+}
+
+int4 PS_PassthroughRGBA2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint2 size;
+ TextureI.GetDimensions(size.x, size.y);
+
+ return TextureI.Load(int3(size * inTexCoord, 0)).rgba;
+}
+
+float4 PS_PassthroughRGB2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return float4(TextureF.Sample(Sampler, inTexCoord).rgb, 1.0f);
+}
+
+float4 PS_PassthroughRGBPremultiply2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ color.rgb *= color.a;
+ return color;
+}
+
+float4 PS_PassthroughRGBUnmultiply2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ if (color.a > 0.0f)
+ {
+ color.rgb /= color.a;
+ }
+ return color;
+}
+
+uint4 PS_PassthroughRGB2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint2 size;
+ TextureUI.GetDimensions(size.x, size.y);
+
+ return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rgb, 0);
+}
+
+int4 PS_PassthroughRGB2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint2 size;
+ TextureI.GetDimensions(size.x, size.y);
+
+ return int4(TextureI.Load(int3(size * inTexCoord, 0)).rgb, 0);
+}
+
+float4 PS_PassthroughRG2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return float4(TextureF.Sample(Sampler, inTexCoord).rg, 0.0f, 1.0f);
+}
+
+uint4 PS_PassthroughRG2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint2 size;
+ TextureUI.GetDimensions(size.x, size.y);
+
+ return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rg, 0, 0);
+}
+
+int4 PS_PassthroughRG2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint2 size;
+ TextureI.GetDimensions(size.x, size.y);
+
+ return int4(TextureI.Load(int3(size * inTexCoord, 0)).rg, 0, 0);
+}
+
+float4 PS_PassthroughR2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return float4(TextureF.Sample(Sampler, inTexCoord).r, 0.0f, 0.0f, 1.0f);
+}
+
+uint4 PS_PassthroughR2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint2 size;
+ TextureUI.GetDimensions(size.x, size.y);
+
+ return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0);
+}
+
+int4 PS_PassthroughR2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint2 size;
+ TextureI.GetDimensions(size.x, size.y);
+
+ return int4(TextureI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0);
+}
+
+float4 PS_PassthroughLum2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return float4(TextureF.Sample(Sampler, inTexCoord).rrr, 1.0f);
+}
+
+float4 PS_PassthroughLumAlpha2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return TextureF.Sample(Sampler, inTexCoord).rrra;
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl
new file mode 100755
index 000000000..c23c9032e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl
@@ -0,0 +1,146 @@
+Texture3D<float4> TextureF : register(t0);
+Texture3D<uint4> TextureUI : register(t0);
+Texture3D<int4> TextureI : register(t0);
+
+SamplerState Sampler : register(s0);
+
+struct VS_INPUT
+{
+ float2 Position : POSITION;
+ uint Layer : LAYER;
+ float3 TexCoord : TEXCOORD;
+};
+
+struct VS_OUTPUT
+{
+ float4 Position : SV_POSITION;
+ uint Layer : LAYER;
+ float3 TexCoord : TEXCOORD;
+};
+
+struct GS_OUTPUT
+{
+ float4 Position : SV_POSITION;
+ uint Layer : SV_RENDERTARGETARRAYINDEX;
+ float3 TexCoord : TEXCOORD;
+};
+
+VS_OUTPUT VS_Passthrough3D(VS_INPUT input)
+{
+ VS_OUTPUT output;
+
+ output.Position = float4(input.Position, 0.0f, 1.0f);
+ output.Layer = input.Layer;
+ output.TexCoord = input.TexCoord;
+
+ return output;
+}
+
+[maxvertexcount(3)]
+void GS_Passthrough3D(triangle VS_OUTPUT input[3], inout TriangleStream<GS_OUTPUT> outputStream)
+{
+ GS_OUTPUT output;
+
+ for (int i = 0; i < 3; i++)
+ {
+ output.Position = input[i].Position;
+ output.Layer = input[i].Layer;
+ output.TexCoord = input[i].TexCoord;
+
+ outputStream.Append(output);
+ }
+}
+
+float4 PS_PassthroughRGBA3D(GS_OUTPUT input) : SV_TARGET0
+{
+ return TextureF.Sample(Sampler, input.TexCoord).rgba;
+}
+
+uint4 PS_PassthroughRGBA3DUI(GS_OUTPUT input) : SV_TARGET0
+{
+ uint3 size;
+ TextureUI.GetDimensions(size.x, size.y, size.z);
+
+ return TextureUI.Load(int4(size * input.TexCoord, 0)).rgba;
+}
+
+int4 PS_PassthroughRGBA3DI(GS_OUTPUT input) : SV_TARGET0
+{
+ uint3 size;
+ TextureI.GetDimensions(size.x, size.y, size.z);
+
+ return TextureI.Load(int4(size * input.TexCoord, 0)).rgba;
+}
+
+float4 PS_PassthroughRGB3D(GS_OUTPUT input) : SV_TARGET0
+{
+ return float4(TextureF.Sample(Sampler, input.TexCoord).rgb, 1.0f);
+}
+
+uint4 PS_PassthroughRGB3DUI(GS_OUTPUT input) : SV_TARGET0
+{
+ uint3 size;
+ TextureUI.GetDimensions(size.x, size.y, size.z);
+
+ return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rgb, 0);
+}
+
+int4 PS_PassthroughRGB3DI(GS_OUTPUT input) : SV_TARGET0
+{
+ uint3 size;
+ TextureI.GetDimensions(size.x, size.y, size.z);
+
+ return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rgb, 0);
+}
+
+float4 PS_PassthroughRG3D(GS_OUTPUT input) : SV_TARGET0
+{
+ return float4(TextureF.Sample(Sampler, input.TexCoord).rg, 0.0f, 1.0f);
+}
+
+uint4 PS_PassthroughRG3DUI(GS_OUTPUT input) : SV_TARGET0
+{
+ uint3 size;
+ TextureUI.GetDimensions(size.x, size.y, size.z);
+
+ return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0);
+}
+
+int4 PS_PassthroughRG3DI(GS_OUTPUT input) : SV_TARGET0
+{
+ uint3 size;
+ TextureI.GetDimensions(size.x, size.y, size.z);
+
+ return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0);
+}
+
+float4 PS_PassthroughR3D(GS_OUTPUT input) : SV_TARGET0
+{
+ return float4(TextureF.Sample(Sampler, input.TexCoord).r, 0.0f, 0.0f, 1.0f);
+}
+
+uint4 PS_PassthroughR3DUI(GS_OUTPUT input) : SV_TARGET0
+{
+ uint3 size;
+ TextureUI.GetDimensions(size.x, size.y, size.z);
+
+ return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0);
+}
+
+int4 PS_PassthroughR3DI(GS_OUTPUT input) : SV_TARGET0
+{
+ uint3 size;
+ TextureI.GetDimensions(size.x, size.y, size.z);
+
+ return int4(TextureI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0);
+}
+
+float4 PS_PassthroughLum3D(GS_OUTPUT input) : SV_TARGET0
+{
+ return float4(TextureF.Sample(Sampler, input.TexCoord).rrr, 1.0f);
+}
+
+float4 PS_PassthroughLumAlpha3D(GS_OUTPUT input) : SV_TARGET0
+{
+ return TextureF.Sample(Sampler, input.TexCoord).rrra;
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl
new file mode 100755
index 000000000..70df1d1b6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl
@@ -0,0 +1,56 @@
+static const float2 g_Corners[6] =
+{
+ float2(-1.0f, 1.0f),
+ float2( 1.0f, -1.0f),
+ float2(-1.0f, -1.0f),
+ float2(-1.0f, 1.0f),
+ float2( 1.0f, 1.0f),
+ float2( 1.0f, -1.0f),
+};
+
+void VS_ResolveDepthStencil(in uint id : SV_VertexID,
+ out float4 position : SV_Position,
+ out float2 texCoord : TEXCOORD0)
+{
+ float2 corner = g_Corners[id];
+ position = float4(corner.x, corner.y, 0.0f, 1.0f);
+ texCoord = float2((corner.x + 1.0f) * 0.5f, (-corner.y + 1.0f) * 0.5f);
+}
+
+Texture2DMS<float> Depth : register(t0);
+Texture2DMS<uint2> Stencil : register(t1);
+
+void PS_ResolveDepth(in float4 position : SV_Position,
+ in float2 texCoord : TEXCOORD0,
+ out float depth : SV_Target0)
+{
+ // MS samplers must use Load
+ uint width, height, samples;
+ Depth.GetDimensions(width, height, samples);
+ uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height));
+ depth = Depth.Load(coord, 0).r;
+}
+
+void PS_ResolveDepthStencil(in float4 position : SV_Position,
+ in float2 texCoord : TEXCOORD0,
+ out float2 depthStencil : SV_Target0)
+{
+ // MS samplers must use Load
+ uint width, height, samples;
+ Depth.GetDimensions(width, height, samples);
+ uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height));
+ depthStencil.r = Depth.Load(coord, 0).r;
+ depthStencil.g = float(Stencil.Load(coord, 0).g);
+}
+
+void PS_ResolveStencil(in float4 position : SV_Position,
+ in float2 texCoord : TEXCOORD0,
+ out float2 stencil : SV_Target0)
+{
+ // MS samplers must use Load
+ uint width, height, samples;
+ Stencil.GetDimensions(width, height, samples);
+ uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height));
+ stencil.r = 0.0f;
+ stencil.g = float(Stencil.Load(coord, 0).g);
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl
new file mode 100755
index 000000000..505e22213
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl
@@ -0,0 +1,99 @@
+Texture2D<float4> TextureF2D : register(t0);
+Texture2D<uint4> TextureUI2D : register(t0);
+Texture2D<int4> TextureI2D : register(t0);
+
+Texture3D<float4> TextureF3D : register(t0);
+Texture3D<uint4> TextureUI3D : register(t0);
+Texture3D<int4> TextureI3D : register(t0);
+
+Texture2DArray<float4> TextureF2DArray : register(t0);
+Texture2DArray<uint4> TextureUI2DArray : register(t0);
+Texture2DArray<int4> TextureI2DArray : register(t0);
+
+SamplerState Sampler : register(s0);
+
+cbuffer SwizzleProperties : register(b0)
+{
+ uint4 SwizzleIndices : packoffset(c0);
+}
+
+float4 SwizzleLookup(in float4 sample)
+{
+ float lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f };
+ return float4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]);
+}
+
+int4 SwizzleLookup(in int4 sample)
+{
+ int lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f };
+ return int4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]);
+}
+
+uint4 SwizzleLookup(in uint4 sample)
+{
+ uint lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f };
+ return uint4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]);
+}
+
+float4 PS_SwizzleF2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return SwizzleLookup(TextureF2D.Sample(Sampler, inTexCoord));
+}
+
+int4 PS_SwizzleI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint2 size;
+ TextureI2D.GetDimensions(size.x, size.y);
+
+ return SwizzleLookup(TextureI2D.Load(int3(size * inTexCoord, 0)));
+}
+
+uint4 PS_SwizzleUI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint2 size;
+ TextureUI2D.GetDimensions(size.x, size.y);
+
+ return SwizzleLookup(TextureUI2D.Load(int3(size * inTexCoord, 0)));
+}
+
+float4 PS_SwizzleF3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return SwizzleLookup(TextureF3D.Sample(Sampler, inTexCoord));
+}
+
+int4 PS_SwizzleI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint3 size;
+ TextureI3D.GetDimensions(size.x, size.y, size.z);
+
+ return SwizzleLookup(TextureI3D.Load(int4(size * inTexCoord, 0)));
+}
+
+uint4 PS_SwizzleUI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint3 size;
+ TextureUI3D.GetDimensions(size.x, size.y, size.z);
+
+ return SwizzleLookup(TextureUI3D.Load(int4(size * inTexCoord, 0)));
+}
+
+float4 PS_SwizzleF2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return SwizzleLookup(TextureF2DArray.Sample(Sampler, float3(inTexCoord.xy, inLayer)));
+}
+
+int4 PS_SwizzleI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint3 size;
+ TextureI2DArray.GetDimensions(size.x, size.y, size.z);
+
+ return SwizzleLookup(TextureI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0)));
+}
+
+uint4 PS_SwizzleUI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ uint3 size;
+ TextureUI2DArray.GetDimensions(size.x, size.y, size.z);
+
+ return SwizzleLookup(TextureUI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0)));
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h
new file mode 100755
index 000000000..71a2fec64
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h
@@ -0,0 +1,165 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// 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, 79, 166,
+ 191, 97, 16, 63, 142, 167,
+ 231, 92, 119, 74, 86, 7,
+ 58, 165, 1, 0, 0, 0,
+ 212, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 0, 1,
+ 0, 0, 136, 1, 0, 0,
+ 88, 2, 0, 0, 82, 68,
+ 69, 70, 80, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h
new file mode 100755
index 000000000..cfc0c3faa
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h
@@ -0,0 +1,229 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer BufferCopyParams
+// {
+//
+// uint FirstPixelOffset; // Offset: 0 Size: 4 [unused]
+// uint PixelsPerRow; // Offset: 4 Size: 4 [unused]
+// uint RowStride; // Offset: 8 Size: 4 [unused]
+// uint RowsPerSlice; // Offset: 12 Size: 4 [unused]
+// float2 PositionOffset; // Offset: 16 Size: 8 [unused]
+// float2 PositionScale; // Offset: 24 Size: 8 [unused]
+// int2 TexLocationOffset; // Offset: 32 Size: 8 [unused]
+// int2 TexLocationScale; // Offset: 40 Size: 8 [unused]
+// uint FirstSlice; // Offset: 48 Size: 4 [unused]
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Buffer4F texture float4 buf 0 1
+// BufferCopyParams cbuffer NA NA 0 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_constantbuffer cb0[1], immediateIndexed
+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, 176, 15,
+ 76, 123, 100, 38, 152, 23,
+ 150, 99, 165, 184, 222, 157,
+ 235, 80, 1, 0, 0, 0,
+ 252, 3, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 2, 0, 0, 228, 2,
+ 0, 0, 24, 3, 0, 0,
+ 128, 3, 0, 0, 82, 68,
+ 69, 70, 80, 2, 0, 0,
+ 1, 0, 0, 0, 120, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 28, 2, 0, 0, 92, 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,
+ 101, 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, 52, 70, 0, 66,
+ 117, 102, 102, 101, 114, 67,
+ 111, 112, 121, 80, 97, 114,
+ 97, 109, 115, 0, 171, 171,
+ 101, 0, 0, 0, 9, 0,
+ 0, 0, 144, 0, 0, 0,
+ 64, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 104, 1, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 124, 1,
+ 0, 0, 0, 0, 0, 0,
+ 140, 1, 0, 0, 4, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 124, 1,
+ 0, 0, 0, 0, 0, 0,
+ 153, 1, 0, 0, 8, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 124, 1,
+ 0, 0, 0, 0, 0, 0,
+ 163, 1, 0, 0, 12, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 124, 1,
+ 0, 0, 0, 0, 0, 0,
+ 176, 1, 0, 0, 16, 0,
+ 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 192, 1,
+ 0, 0, 0, 0, 0, 0,
+ 208, 1, 0, 0, 24, 0,
+ 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 192, 1,
+ 0, 0, 0, 0, 0, 0,
+ 222, 1, 0, 0, 32, 0,
+ 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 240, 1,
+ 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 40, 0,
+ 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 240, 1,
+ 0, 0, 0, 0, 0, 0,
+ 17, 2, 0, 0, 48, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 124, 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, 54,
+ 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 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,
+ 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, 96, 0,
+ 0, 0, 64, 0, 0, 0,
+ 24, 0, 0, 0, 89, 0,
+ 0, 4, 70, 142, 32, 0,
+ 0, 0, 0, 0, 1, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h
new file mode 100755
index 000000000..ac952f6df
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h
@@ -0,0 +1,128 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Buffer4I texture sint4 buf 0 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, 154, 139,
+ 95, 210, 76, 52, 228, 55,
+ 1, 175, 60, 90, 13, 234,
+ 138, 3, 1, 0, 0, 0,
+ 20, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 152, 1, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h
new file mode 100755
index 000000000..fe7d6b27a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h
@@ -0,0 +1,128 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Buffer4UI texture uint4 buf 0 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, 25, 164,
+ 1, 224, 250, 219, 16, 200,
+ 83, 99, 38, 137, 116, 129,
+ 200, 39, 1, 0, 0, 0,
+ 20, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 152, 1, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h
new file mode 100755
index 000000000..ac72f4be9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h
@@ -0,0 +1,311 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// 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 Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// BufferCopyParams cbuffer NA NA 0 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, 39, 207,
+ 138, 15, 42, 195, 141, 208,
+ 2, 107, 135, 197, 122, 36,
+ 114, 227, 1, 0, 0, 0,
+ 152, 5, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 100, 2, 0, 0, 152, 2,
+ 0, 0, 12, 3, 0, 0,
+ 28, 5, 0, 0, 82, 68,
+ 69, 70, 40, 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, 54, 46, 51, 46, 57,
+ 54, 48, 48, 46, 49, 54,
+ 51, 56, 52, 0, 171, 171,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h
new file mode 100755
index 000000000..f8115b727
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h
@@ -0,0 +1,176 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// COLOR 0 xyzw 1 NONE float xyzw
+//
+//
+// 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
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ dcl t0
+ mov oC0, t0
+ mov oC1, t0
+ mov oC2, t0
+ mov oC3, t0
+
+// approximately 4 instruction slots used
+ps_4_0
+dcl_input_ps linear v1.xyzw
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+mov o0.xyzw, v1.xyzw
+mov o1.xyzw, v1.xyzw
+mov o2.xyzw, v1.xyzw
+mov o3.xyzw, v1.xyzw
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat_FL9[] =
+{
+ 68, 88, 66, 67, 36, 167,
+ 59, 21, 253, 46, 206, 132,
+ 254, 28, 18, 118, 51, 115,
+ 45, 31, 1, 0, 0, 0,
+ 236, 2, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 168, 0, 0, 0, 72, 1,
+ 0, 0, 196, 1, 0, 0,
+ 28, 2, 0, 0, 112, 2,
+ 0, 0, 65, 111, 110, 57,
+ 104, 0, 0, 0, 104, 0,
+ 0, 0, 0, 2, 255, 255,
+ 68, 0, 0, 0, 36, 0,
+ 0, 0, 0, 0, 36, 0,
+ 0, 0, 36, 0, 0, 0,
+ 36, 0, 0, 0, 36, 0,
+ 0, 0, 36, 0, 1, 2,
+ 255, 255, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 176, 1, 0, 0, 2,
+ 0, 8, 15, 128, 0, 0,
+ 228, 176, 1, 0, 0, 2,
+ 1, 8, 15, 128, 0, 0,
+ 228, 176, 1, 0, 0, 2,
+ 2, 8, 15, 128, 0, 0,
+ 228, 176, 1, 0, 0, 2,
+ 3, 8, 15, 128, 0, 0,
+ 228, 176, 255, 255, 0, 0,
+ 83, 72, 68, 82, 152, 0,
+ 0, 0, 64, 0, 0, 0,
+ 38, 0, 0, 0, 98, 16,
+ 0, 3, 242, 16, 16, 0,
+ 1, 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, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 2, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 3, 0, 0, 0, 70, 30,
+ 16, 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,
+ 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, 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, 82, 68, 69, 70,
+ 80, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 28, 0,
+ 0, 0, 0, 4, 255, 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, 54, 46, 51, 46, 57,
+ 54, 48, 48, 46, 49, 54,
+ 51, 56, 52, 0, 171, 171,
+ 73, 83, 71, 78, 76, 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,
+ 15, 15, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 67, 79,
+ 76, 79, 82, 0, 171, 171,
+ 79, 83, 71, 78, 116, 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, 104, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 3, 0, 0, 0,
+ 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69,
+ 84, 0, 171, 171
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h
new file mode 100755
index 000000000..a32268783
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h
@@ -0,0 +1,195 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// COLOR 0 xyzw 1 NONE float xyzw
+//
+//
+// 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
+//
+ps_4_0
+dcl_input_ps linear v1.xyzw
+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
+mov o0.xyzw, v1.xyzw
+mov o1.xyzw, v1.xyzw
+mov o2.xyzw, v1.xyzw
+mov o3.xyzw, v1.xyzw
+mov o4.xyzw, v1.xyzw
+mov o5.xyzw, v1.xyzw
+mov o6.xyzw, v1.xyzw
+mov o7.xyzw, v1.xyzw
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat[] =
+{
+ 68, 88, 66, 67, 19, 30,
+ 102, 69, 166, 219, 165, 14,
+ 173, 41, 171, 133, 144, 58,
+ 14, 224, 1, 0, 0, 0,
+ 88, 3, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 224, 0,
+ 0, 0, 188, 1, 0, 0,
+ 220, 2, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 76, 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, 15, 15, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 67, 79, 76, 79, 82, 0,
+ 171, 171, 79, 83, 71, 78,
+ 212, 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,
+ 200, 0, 0, 0, 7, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 7, 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, 98, 16,
+ 0, 3, 242, 16, 16, 0,
+ 1, 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, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 2, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 3, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 4, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 5, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 6, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 7, 0, 0, 0,
+ 70, 30, 16, 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, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h
new file mode 100755
index 000000000..06d75b95e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h
@@ -0,0 +1,175 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xyz 0 NONE float xyz
+// COLOR 0 xyzw 1 NONE float xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// COLOR 0 xyzw 1 NONE float xyzw
+//
+//
+// Runtime generated constant mappings:
+//
+// Target Reg Constant Description
+// ---------- --------------------------------------------------
+// c0 Vertex Shader position offset
+//
+//
+// Level9 shader bytecode:
+//
+ vs_2_x
+ def c1, 1, 0, 0, 0
+ dcl_texcoord v0
+ dcl_texcoord1 v1
+ add oPos.xy, v0, c0
+ mad oPos.zw, v0.z, c1.xyxy, c1.xyyx
+ mov oT0, v1
+
+// approximately 3 instruction slots used
+vs_4_0
+dcl_input v0.xyz
+dcl_input v1.xyzw
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xyzw
+mov o0.xyz, v0.xyzx
+mov o0.w, l(1.000000)
+mov o1.xyzw, v1.xyzw
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_VS_ClearFloat[] =
+{
+ 68, 88, 66, 67, 254, 253,
+ 200, 174, 22, 35, 97, 190,
+ 187, 200, 253, 161, 246, 45,
+ 67, 66, 1, 0, 0, 0,
+ 204, 2, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 208, 0, 0, 0, 84, 1,
+ 0, 0, 208, 1, 0, 0,
+ 40, 2, 0, 0, 120, 2,
+ 0, 0, 65, 111, 110, 57,
+ 144, 0, 0, 0, 144, 0,
+ 0, 0, 0, 2, 254, 255,
+ 104, 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, 128, 63,
+ 0, 0, 0, 0, 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, 4, 0,
+ 0, 4, 0, 0, 12, 192,
+ 0, 0, 170, 144, 1, 0,
+ 68, 160, 1, 0, 20, 160,
+ 1, 0, 0, 2, 0, 0,
+ 15, 224, 1, 0, 228, 144,
+ 255, 255, 0, 0, 83, 72,
+ 68, 82, 124, 0, 0, 0,
+ 64, 0, 1, 0, 31, 0,
+ 0, 0, 95, 0, 0, 3,
+ 114, 16, 16, 0, 0, 0,
+ 0, 0, 95, 0, 0, 3,
+ 242, 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, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 18, 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, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 1, 0, 0, 0, 70, 30,
+ 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,
+ 80, 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, 54, 46, 51, 46, 57,
+ 54, 48, 48, 46, 49, 54,
+ 51, 56, 52, 0, 171, 171,
+ 73, 83, 71, 78, 72, 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,
+ 7, 7, 0, 0, 65, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 15, 15, 0, 0, 80, 79,
+ 83, 73, 84, 73, 79, 78,
+ 0, 67, 79, 76, 79, 82,
+ 0, 171, 79, 83, 71, 78,
+ 76, 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, 15, 0, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 67, 79, 76, 79, 82, 0,
+ 171, 171
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h
new file mode 100755
index 000000000..6e009f472
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h
@@ -0,0 +1,195 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// COLOR 0 xyzw 1 NONE int xyzw
+//
+//
+// 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
+//
+ps_4_0
+dcl_input_ps constant v1.xyzw
+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
+mov o0.xyzw, v1.xyzw
+mov o1.xyzw, v1.xyzw
+mov o2.xyzw, v1.xyzw
+mov o3.xyzw, v1.xyzw
+mov o4.xyzw, v1.xyzw
+mov o5.xyzw, v1.xyzw
+mov o6.xyzw, v1.xyzw
+mov o7.xyzw, v1.xyzw
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_ClearSint[] =
+{
+ 68, 88, 66, 67, 206, 129,
+ 255, 236, 115, 217, 216, 20,
+ 88, 47, 155, 195, 145, 179,
+ 183, 28, 1, 0, 0, 0,
+ 88, 3, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 224, 0,
+ 0, 0, 188, 1, 0, 0,
+ 220, 2, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 76, 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,
+ 2, 0, 0, 0, 1, 0,
+ 0, 0, 15, 15, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 67, 79, 76, 79, 82, 0,
+ 171, 171, 79, 83, 71, 78,
+ 212, 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,
+ 200, 0, 0, 0, 7, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 7, 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, 98, 8,
+ 0, 3, 242, 16, 16, 0,
+ 1, 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, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 2, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 3, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 4, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 5, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 6, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 7, 0, 0, 0,
+ 70, 30, 16, 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, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h
new file mode 100755
index 000000000..f162b4449
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h
@@ -0,0 +1,130 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xyz 0 NONE float xyz
+// COLOR 0 xyzw 1 NONE int xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// COLOR 0 xyzw 1 NONE int xyzw
+//
+vs_4_0
+dcl_input v0.xyz
+dcl_input v1.xyzw
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xyzw
+mov o0.xyz, v0.xyzx
+mov o0.w, l(1.000000)
+mov o1.xyzw, v1.xyzw
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_VS_ClearSint[] =
+{
+ 68, 88, 66, 67, 20, 240,
+ 85, 136, 255, 181, 253, 103,
+ 207, 181, 122, 106, 92, 25,
+ 228, 89, 1, 0, 0, 0,
+ 48, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 220, 0,
+ 0, 0, 48, 1, 0, 0,
+ 180, 1, 0, 0, 82, 68,
+ 69, 70, 80, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 72, 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, 7, 7, 0, 0,
+ 65, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0,
+ 0, 0, 15, 15, 0, 0,
+ 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 67, 79, 76,
+ 79, 82, 0, 171, 79, 83,
+ 71, 78, 76, 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, 2, 0, 0, 0,
+ 1, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 67, 79, 76, 79,
+ 82, 0, 171, 171, 83, 72,
+ 68, 82, 124, 0, 0, 0,
+ 64, 0, 1, 0, 31, 0,
+ 0, 0, 95, 0, 0, 3,
+ 114, 16, 16, 0, 0, 0,
+ 0, 0, 95, 0, 0, 3,
+ 242, 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, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 18, 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, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 1, 0, 0, 0, 70, 30,
+ 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
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h
new file mode 100755
index 000000000..c53650bd8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h
@@ -0,0 +1,195 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// COLOR 0 xyzw 1 NONE uint xyzw
+//
+//
+// 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
+//
+ps_4_0
+dcl_input_ps constant v1.xyzw
+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
+mov o0.xyzw, v1.xyzw
+mov o1.xyzw, v1.xyzw
+mov o2.xyzw, v1.xyzw
+mov o3.xyzw, v1.xyzw
+mov o4.xyzw, v1.xyzw
+mov o5.xyzw, v1.xyzw
+mov o6.xyzw, v1.xyzw
+mov o7.xyzw, v1.xyzw
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_ClearUint[] =
+{
+ 68, 88, 66, 67, 117, 209,
+ 142, 159, 65, 29, 212, 206,
+ 242, 37, 169, 58, 35, 236,
+ 222, 73, 1, 0, 0, 0,
+ 88, 3, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 224, 0,
+ 0, 0, 188, 1, 0, 0,
+ 220, 2, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 76, 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, 15, 15, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 67, 79, 76, 79, 82, 0,
+ 171, 171, 79, 83, 71, 78,
+ 212, 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,
+ 200, 0, 0, 0, 7, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 7, 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, 98, 8,
+ 0, 3, 242, 16, 16, 0,
+ 1, 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, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 2, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 3, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 4, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 5, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 6, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 7, 0, 0, 0,
+ 70, 30, 16, 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, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h
new file mode 100755
index 000000000..cfad90f68
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h
@@ -0,0 +1,130 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xyz 0 NONE float xyz
+// COLOR 0 xyzw 1 NONE uint xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// COLOR 0 xyzw 1 NONE uint xyzw
+//
+vs_4_0
+dcl_input v0.xyz
+dcl_input v1.xyzw
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xyzw
+mov o0.xyz, v0.xyzx
+mov o0.w, l(1.000000)
+mov o1.xyzw, v1.xyzw
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_VS_ClearUint[] =
+{
+ 68, 88, 66, 67, 62, 191,
+ 52, 95, 60, 98, 193, 75,
+ 194, 36, 187, 194, 54, 24,
+ 232, 224, 1, 0, 0, 0,
+ 48, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 220, 0,
+ 0, 0, 48, 1, 0, 0,
+ 180, 1, 0, 0, 82, 68,
+ 69, 70, 80, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 73, 83, 71, 78,
+ 72, 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, 7, 7, 0, 0,
+ 65, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 15, 15, 0, 0,
+ 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 67, 79, 76,
+ 79, 82, 0, 171, 79, 83,
+ 71, 78, 76, 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, 15, 0,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 67, 79, 76, 79,
+ 82, 0, 171, 171, 83, 72,
+ 68, 82, 124, 0, 0, 0,
+ 64, 0, 1, 0, 31, 0,
+ 0, 0, 95, 0, 0, 3,
+ 114, 16, 16, 0, 0, 0,
+ 0, 0, 95, 0, 0, 3,
+ 242, 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, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 18, 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, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 1, 0, 0, 0, 70, 30,
+ 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
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h
new file mode 100755
index 000000000..050040e74
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h
@@ -0,0 +1,177 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// 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, 230, 95,
+ 115, 230, 65, 211, 74, 82,
+ 143, 170, 109, 175, 63, 210,
+ 14, 229, 1, 0, 0, 0,
+ 216, 2, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 200, 0, 0, 0, 88, 1,
+ 0, 0, 212, 1, 0, 0,
+ 44, 2, 0, 0, 128, 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, 80, 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, 54,
+ 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 0, 171, 171, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h
new file mode 100755
index 000000000..ae2d9485e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h
@@ -0,0 +1,191 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// 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, 92, 129,
+ 41, 170, 114, 75, 160, 250,
+ 95, 161, 230, 161, 11, 78,
+ 252, 65, 1, 0, 0, 0,
+ 72, 3, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 0, 1,
+ 0, 0, 136, 1, 0, 0,
+ 204, 2, 0, 0, 82, 68,
+ 69, 70, 80, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h
new file mode 100755
index 000000000..5701a4036
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h
@@ -0,0 +1,155 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// 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, 229, 65,
+ 217, 172, 143, 180, 152, 72,
+ 16, 12, 254, 66, 0, 215,
+ 50, 173, 1, 0, 0, 0,
+ 168, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 252, 0,
+ 0, 0, 112, 1, 0, 0,
+ 44, 2, 0, 0, 82, 68,
+ 69, 70, 80, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h
new file mode 100755
index 000000000..38acea3aa
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h
@@ -0,0 +1,145 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 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, 8, 33,
+ 154, 92, 164, 28, 139, 205,
+ 1, 168, 30, 229, 51, 127,
+ 173, 221, 1, 0, 0, 0,
+ 100, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 52, 1,
+ 0, 0, 104, 1, 0, 0,
+ 232, 1, 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,
+ 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,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h
new file mode 100755
index 000000000..e0bcbc8fe
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h
@@ -0,0 +1,196 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 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, 144, 18,
+ 242, 89, 150, 125, 18, 219,
+ 193, 196, 127, 207, 14, 165,
+ 198, 119, 1, 0, 0, 0,
+ 28, 3, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 208, 0, 0, 0, 108, 1,
+ 0, 0, 232, 1, 0, 0,
+ 144, 2, 0, 0, 232, 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,
+ 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, 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, 54, 46,
+ 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h
new file mode 100755
index 000000000..ac2bb4035
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h
@@ -0,0 +1,160 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 3d 0 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, 173, 177,
+ 219, 35, 149, 130, 33, 215,
+ 183, 219, 250, 244, 100, 17,
+ 62, 106, 1, 0, 0, 0,
+ 176, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 100, 1,
+ 0, 0, 152, 1, 0, 0,
+ 52, 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,
+ 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,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h
new file mode 100755
index 000000000..88599fca9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h
@@ -0,0 +1,185 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 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, 246, 240,
+ 158, 208, 214, 197, 166, 221,
+ 45, 58, 235, 164, 12, 157,
+ 62, 31, 1, 0, 0, 0,
+ 232, 2, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 176, 0, 0, 0, 56, 1,
+ 0, 0, 180, 1, 0, 0,
+ 92, 2, 0, 0, 180, 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, 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,
+ 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,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h
new file mode 100755
index 000000000..19091d035
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h
@@ -0,0 +1,156 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 3d 0 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, 224, 152,
+ 208, 227, 44, 106, 62, 235,
+ 129, 97, 207, 213, 29, 232,
+ 163, 6, 1, 0, 0, 0,
+ 156, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 100, 1,
+ 0, 0, 152, 1, 0, 0,
+ 32, 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,
+ 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,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h
new file mode 100755
index 000000000..d42101670
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h
@@ -0,0 +1,198 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 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, 212, 251,
+ 117, 250, 99, 185, 28, 44,
+ 178, 14, 83, 133, 173, 0,
+ 182, 196, 1, 0, 0, 0,
+ 40, 3, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 208, 0, 0, 0, 120, 1,
+ 0, 0, 244, 1, 0, 0,
+ 156, 2, 0, 0, 244, 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,
+ 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, 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, 54, 46,
+ 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h
new file mode 100755
index 000000000..4d8d9933a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h
@@ -0,0 +1,167 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 2d 0 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, 123, 230,
+ 45, 18, 63, 217, 12, 210,
+ 151, 254, 16, 78, 107, 211,
+ 57, 255, 1, 0, 0, 0,
+ 208, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 84, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h
new file mode 100755
index 000000000..3f3885a1f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h
@@ -0,0 +1,167 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 2d 0 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, 4, 26,
+ 62, 109, 94, 45, 124, 238,
+ 150, 245, 85, 155, 185, 37,
+ 234, 152, 1, 0, 0, 0,
+ 208, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 84, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h
new file mode 100755
index 000000000..506baef44
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h
@@ -0,0 +1,162 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 3d 0 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, 11, 235,
+ 208, 143, 219, 183, 141, 78,
+ 136, 182, 62, 182, 243, 12,
+ 239, 125, 1, 0, 0, 0,
+ 188, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 100, 1,
+ 0, 0, 152, 1, 0, 0,
+ 64, 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,
+ 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,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h
new file mode 100755
index 000000000..89c35d600
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h
@@ -0,0 +1,174 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 3d 0 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, 222, 251,
+ 30, 61, 15, 80, 81, 247,
+ 175, 137, 44, 19, 23, 84,
+ 149, 211, 1, 0, 0, 0,
+ 244, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 120, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h
new file mode 100755
index 000000000..64386841c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h
@@ -0,0 +1,174 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 3d 0 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, 69, 5,
+ 86, 212, 201, 54, 97, 205,
+ 89, 161, 100, 72, 246, 114,
+ 40, 214, 1, 0, 0, 0,
+ 244, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 120, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h
new file mode 100755
index 000000000..201cbff60
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h
@@ -0,0 +1,198 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 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, 217, 171,
+ 153, 248, 26, 15, 102, 119,
+ 86, 174, 121, 245, 223, 83,
+ 2, 181, 1, 0, 0, 0,
+ 40, 3, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 208, 0, 0, 0, 120, 1,
+ 0, 0, 244, 1, 0, 0,
+ 156, 2, 0, 0, 244, 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,
+ 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, 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, 54, 46,
+ 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h
new file mode 100755
index 000000000..a66e53094
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h
@@ -0,0 +1,167 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 2d 0 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, 89, 123,
+ 129, 251, 206, 105, 221, 141,
+ 5, 160, 186, 187, 168, 157,
+ 145, 246, 1, 0, 0, 0,
+ 208, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 84, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h
new file mode 100755
index 000000000..5146cd936
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h
@@ -0,0 +1,167 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 2d 0 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, 253, 188,
+ 138, 153, 226, 194, 182, 197,
+ 184, 36, 111, 24, 198, 171,
+ 241, 145, 1, 0, 0, 0,
+ 208, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 84, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h
new file mode 100755
index 000000000..a31301170
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h
@@ -0,0 +1,162 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 3d 0 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, 117, 159,
+ 238, 81, 51, 223, 126, 31,
+ 223, 171, 227, 2, 248, 7,
+ 72, 91, 1, 0, 0, 0,
+ 188, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 100, 1,
+ 0, 0, 152, 1, 0, 0,
+ 64, 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,
+ 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,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h
new file mode 100755
index 000000000..ef6ec1723
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h
@@ -0,0 +1,174 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 3d 0 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, 62, 119,
+ 61, 21, 83, 42, 80, 125,
+ 121, 208, 247, 10, 223, 62,
+ 33, 18, 1, 0, 0, 0,
+ 244, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 120, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h
new file mode 100755
index 000000000..d1540cee7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h
@@ -0,0 +1,174 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 3d 0 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, 37, 56,
+ 43, 206, 81, 137, 125, 191,
+ 216, 50, 86, 76, 61, 78,
+ 25, 246, 1, 0, 0, 0,
+ 244, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 120, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h
new file mode 100755
index 000000000..0047ef3ca
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h
@@ -0,0 +1,196 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 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, 51, 90,
+ 49, 167, 211, 79, 20, 215,
+ 57, 227, 70, 56, 132, 117,
+ 66, 156, 1, 0, 0, 0,
+ 28, 3, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 208, 0, 0, 0, 108, 1,
+ 0, 0, 232, 1, 0, 0,
+ 144, 2, 0, 0, 232, 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,
+ 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, 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, 54, 46,
+ 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h
new file mode 100755
index 000000000..0f318fd8b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h
@@ -0,0 +1,165 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 2d 0 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, 16, 227,
+ 172, 190, 246, 118, 223, 239,
+ 176, 78, 90, 11, 135, 138,
+ 109, 174, 1, 0, 0, 0,
+ 196, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 72, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h
new file mode 100755
index 000000000..943f7a2be
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h
@@ -0,0 +1,165 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 2d 0 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, 245, 219,
+ 46, 32, 34, 74, 2, 47,
+ 124, 96, 216, 40, 253, 243,
+ 104, 178, 1, 0, 0, 0,
+ 196, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 72, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h
new file mode 100755
index 000000000..528f27361
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h
@@ -0,0 +1,160 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 3d 0 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, 3, 213,
+ 227, 200, 132, 255, 7, 95,
+ 0, 252, 77, 33, 254, 184,
+ 83, 110, 1, 0, 0, 0,
+ 176, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 100, 1,
+ 0, 0, 152, 1, 0, 0,
+ 52, 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,
+ 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,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h
new file mode 100755
index 000000000..fa2a63959
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h
@@ -0,0 +1,172 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 3d 0 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, 194, 157,
+ 8, 194, 167, 235, 14, 127,
+ 69, 198, 32, 35, 167, 35,
+ 213, 248, 1, 0, 0, 0,
+ 232, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 108, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h
new file mode 100755
index 000000000..e90b40d00
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h
@@ -0,0 +1,172 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 3d 0 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, 253, 147,
+ 1, 158, 41, 31, 253, 138,
+ 52, 213, 103, 41, 188, 192,
+ 79, 199, 1, 0, 0, 0,
+ 232, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 108, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h
new file mode 100755
index 000000000..a4ee9d5ab
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h
@@ -0,0 +1,176 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 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, 240, 186,
+ 163, 221, 151, 45, 139, 68,
+ 172, 121, 30, 230, 203, 102,
+ 92, 33, 1, 0, 0, 0,
+ 192, 2, 0, 0, 6, 0,
+ 0, 0, 56, 0, 0, 0,
+ 164, 0, 0, 0, 16, 1,
+ 0, 0, 140, 1, 0, 0,
+ 52, 2, 0, 0, 140, 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, 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, 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, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h
new file mode 100755
index 000000000..d87d043d8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h
@@ -0,0 +1,157 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 2d 0 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, 81, 147,
+ 194, 141, 92, 236, 184, 192,
+ 11, 249, 14, 215, 122, 110,
+ 35, 111, 1, 0, 0, 0,
+ 156, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 32, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h
new file mode 100755
index 000000000..35cff53a4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h
@@ -0,0 +1,157 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 2d 0 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, 128, 252,
+ 255, 238, 68, 109, 10, 133,
+ 175, 163, 216, 152, 219, 103,
+ 163, 223, 1, 0, 0, 0,
+ 156, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 12, 1,
+ 0, 0, 64, 1, 0, 0,
+ 32, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h
new file mode 100755
index 000000000..ac4cbeae9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h
@@ -0,0 +1,149 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 3d 0 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, 246, 41,
+ 15, 240, 168, 172, 91, 145,
+ 236, 221, 187, 89, 12, 0,
+ 93, 149, 1, 0, 0, 0,
+ 128, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 100, 1,
+ 0, 0, 152, 1, 0, 0,
+ 4, 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,
+ 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,
+ 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h
new file mode 100755
index 000000000..1921c9f20
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h
@@ -0,0 +1,164 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI texture sint4 3d 0 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, 139, 158,
+ 6, 251, 163, 134, 3, 183,
+ 5, 227, 185, 108, 35, 91,
+ 67, 191, 1, 0, 0, 0,
+ 192, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 68, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h
new file mode 100755
index 000000000..cba1502da
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h
@@ -0,0 +1,164 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI texture uint4 3d 0 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, 16, 111,
+ 56, 218, 148, 233, 100, 164,
+ 0, 199, 73, 155, 213, 171,
+ 78, 18, 1, 0, 0, 0,
+ 192, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 180, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0,
+ 68, 2, 0, 0, 82, 68,
+ 69, 70, 120, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h
new file mode 100755
index 000000000..3ce18ee6b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h
@@ -0,0 +1,101 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 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
+ mul r0.xyz, r0.w, r0
+ 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
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBAPremultiply2D[] = {
+ 68, 88, 66, 67, 139, 254, 84, 241, 202, 33, 132, 221, 123, 19, 241, 182, 75, 155, 177,
+ 115, 1, 0, 0, 0, 8, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 180, 0,
+ 0, 0, 88, 1, 0, 0, 212, 1, 0, 0, 124, 2, 0, 0, 212, 2, 0, 0, 65,
+ 111, 110, 57, 116, 0, 0, 0, 116, 0, 0, 0, 0, 2, 255, 255, 76, 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, 5, 0, 0, 3,
+ 0, 0, 7, 128, 0, 0, 255, 128, 0, 0, 228, 128, 1, 0, 0, 2, 0, 8, 15,
+ 128, 0, 0, 228, 128, 255, 255, 0, 0, 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, 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, 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, 54, 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h
new file mode 100755
index 000000000..c1354f740
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h
@@ -0,0 +1,110 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 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
+ rcp r1.w, r0.w
+ mul r1.xyz, r0, r1.w
+ cmp r0.xyz, -r0.w, r0, r1
+ mov oC0, r0
+
+// approximately 5 instruction slots used (1 texture, 4 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 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_PassthroughRGBAUnmultiply2D[] = {
+ 68, 88, 66, 67, 180, 87, 43, 111, 255, 135, 28, 224, 42, 85, 197, 16, 17, 172, 176,
+ 70, 1, 0, 0, 0, 104, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 212, 0,
+ 0, 0, 184, 1, 0, 0, 52, 2, 0, 0, 220, 2, 0, 0, 52, 3, 0, 0, 65,
+ 111, 110, 57, 148, 0, 0, 0, 148, 0, 0, 0, 0, 2, 255, 255, 108, 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, 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, 0, 8, 15, 128, 0, 0, 228, 128, 255,
+ 255, 0, 0, 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, 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, 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, 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h
new file mode 100755
index 000000000..c88a1414b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h
@@ -0,0 +1,101 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 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
+ mul r0.xyz, r0.w, r0
+ 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
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBPremultiply2D[] = {
+ 68, 88, 66, 67, 139, 254, 84, 241, 202, 33, 132, 221, 123, 19, 241, 182, 75, 155, 177,
+ 115, 1, 0, 0, 0, 8, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 180, 0,
+ 0, 0, 88, 1, 0, 0, 212, 1, 0, 0, 124, 2, 0, 0, 212, 2, 0, 0, 65,
+ 111, 110, 57, 116, 0, 0, 0, 116, 0, 0, 0, 0, 2, 255, 255, 76, 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, 5, 0, 0, 3,
+ 0, 0, 7, 128, 0, 0, 255, 128, 0, 0, 228, 128, 1, 0, 0, 2, 0, 8, 15,
+ 128, 0, 0, 228, 128, 255, 255, 0, 0, 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, 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, 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, 54, 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h
new file mode 100755
index 000000000..9dd3c02f3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h
@@ -0,0 +1,110 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF texture float4 2d 0 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
+ rcp r1.w, r0.w
+ mul r1.xyz, r0, r1.w
+ cmp r0.xyz, -r0.w, r0, r1
+ mov oC0, r0
+
+// approximately 5 instruction slots used (1 texture, 4 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 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_PassthroughRGBUnmultiply2D[] = {
+ 68, 88, 66, 67, 180, 87, 43, 111, 255, 135, 28, 224, 42, 85, 197, 16, 17, 172, 176,
+ 70, 1, 0, 0, 0, 104, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 212, 0,
+ 0, 0, 184, 1, 0, 0, 52, 2, 0, 0, 220, 2, 0, 0, 52, 3, 0, 0, 65,
+ 111, 110, 57, 148, 0, 0, 0, 148, 0, 0, 0, 0, 2, 255, 255, 108, 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, 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, 0, 8, 15, 128, 0, 0, 228, 128, 255,
+ 255, 0, 0, 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, 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, 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, 54, 46, 51, 46, 57, 54,
+ 48, 48, 46, 49, 54, 51, 56, 52, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h
new file mode 100755
index 000000000..b44a27c58
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h
@@ -0,0 +1,82 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Depth texture float 2dMS 0 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 x 0 TARGET float x
+//
+ps_4_1
+dcl_globalFlags refactoringAllowed
+dcl_resource_texture2dms(0) (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.x
+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 o0.x, r0.x
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_ResolveDepth[] = {
+ 68, 88, 66, 67, 205, 219, 191, 201, 103, 134, 243, 76, 11, 91, 23, 182, 42, 8, 17,
+ 173, 1, 0, 0, 0, 184, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 176, 0,
+ 0, 0, 8, 1, 0, 0, 60, 1, 0, 0, 60, 2, 0, 0, 82, 68, 69, 70, 116,
+ 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, 54, 46, 51, 46, 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 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, 1, 14, 0, 0,
+ 83, 86, 95, 84, 97, 114, 103, 101, 116, 0, 171, 171, 83, 72, 68, 82, 248, 0, 0,
+ 0, 65, 0, 0, 0, 62, 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, 18, 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, 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,
+ 5, 18, 32, 16, 0, 0, 0, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h
new file mode 100755
index 000000000..58834eb65
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h
@@ -0,0 +1,92 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Depth texture float 2dMS 0 1
+// Stencil texture uint2 2dMS 1 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, 229, 191, 254, 12, 10, 19, 181, 162, 222, 203, 244, 146, 104, 226, 195,
+ 177, 1, 0, 0, 0, 40, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 216, 0,
+ 0, 0, 48, 1, 0, 0, 100, 1, 0, 0, 172, 2, 0, 0, 82, 68, 69, 70, 156,
+ 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, 54, 46, 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52, 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, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h
new file mode 100755
index 000000000..989a316f6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h
@@ -0,0 +1,84 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+//
+// 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, 205, 15, 103, 70, 202, 235, 195, 98, 255, 82, 84, 239, 130, 6, 12,
+ 104, 1, 0, 0, 0, 0, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 140, 0,
+ 0, 0, 192, 0, 0, 0, 24, 1, 0, 0, 132, 2, 0, 0, 82, 68, 69, 70, 80,
+ 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, 54, 46, 51, 46, 57, 54, 48, 48, 46, 49,
+ 54, 51, 56, 52, 0, 171, 171, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h
new file mode 100755
index 000000000..1730df345
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h
@@ -0,0 +1,84 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Stencil texture uint2 2dMS 1 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, 122, 29, 34, 146, 254, 203, 175, 97, 151, 254, 255, 190, 91, 40, 55,
+ 118, 1, 0, 0, 0, 208, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 180, 0,
+ 0, 0, 12, 1, 0, 0, 64, 1, 0, 0, 84, 2, 0, 0, 82, 68, 69, 70, 120,
+ 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, 54, 46, 51, 46, 57, 54, 48, 48,
+ 46, 49, 54, 51, 56, 52, 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, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h
new file mode 100755
index 000000000..b34914b39
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h
@@ -0,0 +1,278 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF2DArray texture float4 2darray 0 1
+// SwizzleProperties cbuffer NA NA 0 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, 39, 232,
+ 91, 166, 165, 217, 22, 39,
+ 183, 202, 191, 64, 238, 104,
+ 217, 199, 1, 0, 0, 0,
+ 204, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 104, 1, 0, 0, 240, 1,
+ 0, 0, 36, 2, 0, 0,
+ 80, 4, 0, 0, 82, 68,
+ 69, 70, 44, 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, 54, 46, 51, 46, 57,
+ 54, 48, 48, 46, 49, 54,
+ 51, 56, 52, 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, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h
new file mode 100755
index 000000000..ea57e8737
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h
@@ -0,0 +1,256 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF2D texture float4 2d 0 1
+// SwizzleProperties cbuffer NA NA 0 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, 187, 204,
+ 160, 39, 195, 158, 245, 72,
+ 125, 249, 70, 140, 158, 199,
+ 246, 220, 1, 0, 0, 0,
+ 96, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 100, 1, 0, 0, 188, 1,
+ 0, 0, 240, 1, 0, 0,
+ 228, 3, 0, 0, 82, 68,
+ 69, 70, 40, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h
new file mode 100755
index 000000000..7938639e6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h
@@ -0,0 +1,265 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// TextureF3D texture float4 3d 0 1
+// SwizzleProperties cbuffer NA NA 0 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, 238, 60,
+ 80, 74, 42, 65, 120, 165,
+ 177, 91, 253, 216, 89, 102,
+ 2, 228, 1, 0, 0, 0,
+ 144, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 100, 1, 0, 0, 236, 1,
+ 0, 0, 32, 2, 0, 0,
+ 20, 4, 0, 0, 82, 68,
+ 69, 70, 40, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h
new file mode 100755
index 000000000..76176fcbe
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h
@@ -0,0 +1,286 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI2DArray texture sint4 2darray 0 1
+// SwizzleProperties cbuffer NA NA 0 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, 85, 61,
+ 60, 36, 33, 245, 58, 113,
+ 238, 227, 230, 200, 136, 227,
+ 36, 193, 1, 0, 0, 0,
+ 240, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 64, 1, 0, 0, 200, 1,
+ 0, 0, 252, 1, 0, 0,
+ 116, 4, 0, 0, 82, 68,
+ 69, 70, 4, 1, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h
new file mode 100755
index 000000000..1df27a0bf
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h
@@ -0,0 +1,270 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI2D texture sint4 2d 0 1
+// SwizzleProperties cbuffer NA NA 0 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, 180, 37,
+ 54, 19, 39, 134, 185, 230,
+ 234, 82, 113, 129, 69, 135,
+ 140, 27, 1, 0, 0, 0,
+ 164, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 60, 1, 0, 0, 148, 1,
+ 0, 0, 200, 1, 0, 0,
+ 40, 4, 0, 0, 82, 68,
+ 69, 70, 0, 1, 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, 54,
+ 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h
new file mode 100755
index 000000000..96f042b5b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h
@@ -0,0 +1,277 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureI3D texture sint4 3d 0 1
+// SwizzleProperties cbuffer NA NA 0 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, 48, 84,
+ 97, 193, 216, 245, 101, 196,
+ 167, 81, 215, 168, 25, 164,
+ 144, 38, 1, 0, 0, 0,
+ 200, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 60, 1, 0, 0, 196, 1,
+ 0, 0, 248, 1, 0, 0,
+ 76, 4, 0, 0, 82, 68,
+ 69, 70, 0, 1, 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, 54,
+ 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h
new file mode 100755
index 000000000..cca965c6f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h
@@ -0,0 +1,286 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI2DArray texture uint4 2darray 0 1
+// SwizzleProperties cbuffer NA NA 0 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, 15, 124,
+ 179, 49, 45, 69, 64, 249,
+ 216, 189, 135, 190, 71, 234,
+ 72, 20, 1, 0, 0, 0,
+ 240, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 64, 1, 0, 0, 200, 1,
+ 0, 0, 252, 1, 0, 0,
+ 116, 4, 0, 0, 82, 68,
+ 69, 70, 4, 1, 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, 54, 46, 51,
+ 46, 57, 54, 48, 48, 46,
+ 49, 54, 51, 56, 52, 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, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h
new file mode 100755
index 000000000..9de8b28a8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h
@@ -0,0 +1,270 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI2D texture uint4 2d 0 1
+// SwizzleProperties cbuffer NA NA 0 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, 165, 190,
+ 35, 188, 235, 202, 154, 237,
+ 226, 86, 223, 212, 34, 38,
+ 81, 252, 1, 0, 0, 0,
+ 164, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 60, 1, 0, 0, 148, 1,
+ 0, 0, 200, 1, 0, 0,
+ 40, 4, 0, 0, 82, 68,
+ 69, 70, 0, 1, 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, 54,
+ 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 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, 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/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h
new file mode 100755
index 000000000..c66821602
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h
@@ -0,0 +1,277 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// TextureUI3D texture uint4 3d 0 1
+// SwizzleProperties cbuffer NA NA 0 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, 186, 124,
+ 222, 110, 186, 145, 165, 56,
+ 152, 97, 247, 114, 115, 197,
+ 159, 190, 1, 0, 0, 0,
+ 200, 4, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 60, 1, 0, 0, 196, 1,
+ 0, 0, 248, 1, 0, 0,
+ 76, 4, 0, 0, 82, 68,
+ 69, 70, 0, 1, 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, 54,
+ 46, 51, 46, 57, 54, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 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, 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/src/libANGLE/renderer/d3d/d3d11/shaders/generate_shaders.bat b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/generate_shaders.bat
new file mode 100755
index 000000000..4c64b09a8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/shaders/generate_shaders.bat
@@ -0,0 +1,134 @@
+@ECHO OFF
+REM
+REM Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+REM Use of this source code is governed by a BSD-style license that can be
+REM found in the LICENSE file.
+REM
+
+PATH %PATH%;%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86;%DXSDK_DIR%\Utilities\bin\x86
+
+setlocal
+set errorCount=0
+set successCount=0
+set debug=0
+
+if "%1" == "debug" (
+ set debug=1
+)
+if "%1" == "release" (
+ set debug=0
+)
+
+:: Shaders for OpenGL ES 2.0 and OpenGL ES 3.0+
+:: | Input file | Entry point | Type | Output file | Debug |
+call:BuildShader Passthrough2D11.hlsl VS_Passthrough2D vs_4_0_level_9_3 compiled\passthrough2d11vs.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBA2D ps_4_0_level_9_3 compiled\passthroughrgba2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGB2D ps_4_0_level_9_3 compiled\passthroughrgb2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRG2D ps_4_0_level_9_3 compiled\passthroughrg2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughR2D ps_4_0_level_9_3 compiled\passthroughr2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughLum2D ps_4_0_level_9_3 compiled\passthroughlum2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughLumAlpha2D ps_4_0_level_9_3 compiled\passthroughlumalpha2d11ps.h %debug%
+
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBAPremultiply2D ps_4_0_level_9_3 compiled\passthroughrgbapremultiply2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBAUnmultiply2D ps_4_0_level_9_3 compiled\passthroughrgbaunmultiply2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBPremultiply2D ps_4_0_level_9_3 compiled\passthroughrgbpremultiply2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBUnmultiply2D ps_4_0_level_9_3 compiled\passthroughrgbunmultiply2d11ps.h %debug%
+
+call:BuildShader Clear11.hlsl VS_ClearFloat vs_4_0_level_9_3 compiled\clearfloat11vs.h %debug%
+call:BuildShader Clear11.hlsl PS_ClearFloat_FL9 ps_4_0_level_9_3 compiled\clearfloat11_fl9ps.h %debug%
+call:BuildShader Clear11.hlsl PS_ClearFloat ps_4_0 compiled\clearfloat11ps.h %debug%
+
+
+:: Shaders for OpenGL ES 3.0+ only
+:: | Input file | Entry point | Type | Output file | Debug |
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughDepth2D ps_4_0 compiled\passthroughdepth2d11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBA2DUI ps_4_0 compiled\passthroughrgba2dui11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGBA2DI ps_4_0 compiled\passthroughrgba2di11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGB2DUI ps_4_0 compiled\passthroughrgb2dui11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRGB2DI ps_4_0 compiled\passthroughrgb2di11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRG2DUI ps_4_0 compiled\passthroughrg2dui11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughRG2DI ps_4_0 compiled\passthroughrg2di11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughR2DUI ps_4_0 compiled\passthroughr2dui11ps.h %debug%
+call:BuildShader Passthrough2D11.hlsl PS_PassthroughR2DI ps_4_0 compiled\passthroughr2di11ps.h %debug%
+
+call:BuildShader Passthrough3D11.hlsl VS_Passthrough3D vs_4_0 compiled\passthrough3d11vs.h %debug%
+call:BuildShader Passthrough3D11.hlsl GS_Passthrough3D gs_4_0 compiled\passthrough3d11gs.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRGBA3D ps_4_0 compiled\passthroughrgba3d11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRGBA3DUI ps_4_0 compiled\passthroughrgba3dui11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRGBA3DI ps_4_0 compiled\passthroughrgba3di11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRGB3D ps_4_0 compiled\passthroughrgb3d11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRGB3DUI ps_4_0 compiled\passthroughrgb3dui11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRGB3DI ps_4_0 compiled\passthroughrgb3di11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRG3D ps_4_0 compiled\passthroughrg3d11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRG3DUI ps_4_0 compiled\passthroughrg3dui11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughRG3DI ps_4_0 compiled\passthroughrg3di11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughR3D ps_4_0 compiled\passthroughr3d11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughR3DUI ps_4_0 compiled\passthroughr3dui11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughR3DI ps_4_0 compiled\passthroughr3di11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughLum3D ps_4_0 compiled\passthroughlum3d11ps.h %debug%
+call:BuildShader Passthrough3D11.hlsl PS_PassthroughLumAlpha3D ps_4_0 compiled\passthroughlumalpha3d11ps.h %debug%
+
+call:BuildShader Swizzle11.hlsl PS_SwizzleF2D ps_4_0 compiled\swizzlef2dps.h %debug%
+call:BuildShader Swizzle11.hlsl PS_SwizzleI2D ps_4_0 compiled\swizzlei2dps.h %debug%
+call:BuildShader Swizzle11.hlsl PS_SwizzleUI2D ps_4_0 compiled\swizzleui2dps.h %debug%
+
+call:BuildShader Swizzle11.hlsl PS_SwizzleF3D ps_4_0 compiled\swizzlef3dps.h %debug%
+call:BuildShader Swizzle11.hlsl PS_SwizzleI3D ps_4_0 compiled\swizzlei3dps.h %debug%
+call:BuildShader Swizzle11.hlsl PS_SwizzleUI3D ps_4_0 compiled\swizzleui3dps.h %debug%
+
+call:BuildShader Swizzle11.hlsl PS_SwizzleF2DArray ps_4_0 compiled\swizzlef2darrayps.h %debug%
+call:BuildShader Swizzle11.hlsl PS_SwizzleI2DArray ps_4_0 compiled\swizzlei2darrayps.h %debug%
+call:BuildShader Swizzle11.hlsl PS_SwizzleUI2DArray ps_4_0 compiled\swizzleui2darrayps.h %debug%
+
+call:BuildShader Clear11.hlsl VS_ClearUint vs_4_0 compiled\clearuint11vs.h %debug%
+call:BuildShader Clear11.hlsl PS_ClearUint ps_4_0 compiled\clearuint11ps.h %debug%
+
+call:BuildShader Clear11.hlsl VS_ClearSint vs_4_0 compiled\clearsint11vs.h %debug%
+call:BuildShader Clear11.hlsl PS_ClearSint ps_4_0 compiled\clearsint11ps.h %debug%
+
+call:BuildShader BufferToTexture11.hlsl VS_BufferToTexture vs_4_0 compiled/buffertotexture11_vs.h %debug%
+call:BuildShader BufferToTexture11.hlsl GS_BufferToTexture gs_4_0 compiled/buffertotexture11_gs.h %debug%
+call:BuildShader BufferToTexture11.hlsl PS_BufferToTexture_4F ps_4_0 compiled/buffertotexture11_ps_4f.h %debug%
+call:BuildShader BufferToTexture11.hlsl PS_BufferToTexture_4I ps_4_0 compiled/buffertotexture11_ps_4i.h %debug%
+call:BuildShader BufferToTexture11.hlsl PS_BufferToTexture_4UI ps_4_0 compiled/buffertotexture11_ps_4ui.h %debug%
+
+call:BuildShader ResolveDepthStencil.hlsl VS_ResolveDepthStencil vs_4_1 compiled/resolvedepthstencil11_vs.h %debug%
+call:BuildShader ResolveDepthStencil.hlsl PS_ResolveDepth ps_4_1 compiled/resolvedepth11_ps.h %debug%
+call:BuildShader ResolveDepthStencil.hlsl PS_ResolveDepthStencil ps_4_1 compiled/resolvedepthstencil11_ps.h %debug%
+call:BuildShader ResolveDepthStencil.hlsl PS_ResolveStencil ps_4_1 compiled/resolvestencil11_ps.h %debug%
+
+echo.
+
+if %successCount% GTR 0 (
+ echo %successCount% shaders compiled successfully.
+)
+if %errorCount% GTR 0 (
+ echo There were %errorCount% shader compilation errors.
+)
+
+endlocal
+exit /b
+
+:BuildShader
+set input=%~1
+set entry=%~2
+set type=%~3
+set output=%~4
+set debug=%~5
+
+if %debug% == 0 (
+ set "buildCMD=fxc /nologo /E %entry% /T %type% /Fh %output% %input%"
+) else (
+ set "buildCMD=fxc /nologo /Zi /Od /E %entry% /T %type% /Fh %output% %input%"
+)
+
+set error=0
+%buildCMD% || set error=1
+
+if %error% == 0 (
+ set /a successCount=%successCount%+1
+) else (
+ set /a errorCount=%errorCount%+1
+)
+
+exit /b
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
new file mode 100755
index 000000000..06f7e2afd
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
@@ -0,0 +1,490 @@
+{
+ "NONE": {
+ },
+ "A8_UNORM": {
+ "texFormat": "DXGI_FORMAT_A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_A8_UNORM",
+ "channels": "a",
+ "componentType": "unorm",
+ "bits": { "alpha": 8 },
+ "supportTest": "OnlyFL10Plus(deviceCaps)",
+ "fallbackFormat": "R8G8B8A8_UNORM"
+ },
+ "R8G8B8A8_UNORM": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+ "glInternalFormat": "GL_RGBA8"
+ },
+ "R16G16B16A16_UNORM": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+ "glInternalFormat": "GL_RGBA16_EXT"
+ },
+ "R16G16B16A16_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "channels": "rgba",
+ "componentType": "float",
+ "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+ "glInternalFormat": "GL_RGBA16F"
+ },
+ "R32G32B32A32_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "channels": "rgba",
+ "componentType": "float",
+ "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 },
+ "glInternalFormat": "GL_RGBA32F"
+ },
+ "B8G8R8A8_UNORM": {
+ "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "channels": "bgra",
+ "componentType": "unorm",
+ "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+ "glInternalFormat": "GL_BGRA8_EXT"
+ },
+ "BC1_RGBA_UNORM_BLOCK": {
+ "texFormat": "DXGI_FORMAT_BC1_UNORM",
+ "srvFormat": "DXGI_FORMAT_BC1_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "swizzleFormat": "GL_RGBA8",
+ "glInternalFormat": "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"
+ },
+ "BC1_RGB_UNORM_BLOCK": {
+ "texFormat": "DXGI_FORMAT_BC1_UNORM",
+ "srvFormat": "DXGI_FORMAT_BC1_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "swizzleFormat": "GL_RGBA8",
+ "glInternalFormat": "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"
+ },
+ "BC2_RGBA_UNORM_BLOCK": {
+ "texFormat": "DXGI_FORMAT_BC2_UNORM",
+ "srvFormat": "DXGI_FORMAT_BC2_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "swizzleFormat": "GL_RGBA8",
+ "glInternalFormat": "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE"
+ },
+ "BC3_RGBA_UNORM_BLOCK": {
+ "texFormat": "DXGI_FORMAT_BC3_UNORM",
+ "srvFormat": "DXGI_FORMAT_BC3_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "swizzleFormat": "GL_RGBA8",
+ "glInternalFormat": "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE"
+ },
+ "D24_UNORM_S8_UINT": {
+ "FL10Plus": {
+ "texFormat": "DXGI_FORMAT_R24G8_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS"
+ },
+ "FL9_3": {
+ "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT"
+ },
+ "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "channels": "ds",
+ "bits": { "depth": 24, "stencil": 8 },
+ "glInternalFormat": "GL_DEPTH24_STENCIL8_OES"
+ },
+ "D32_FLOAT_S8X24_UINT": {
+ "texFormat": "DXGI_FORMAT_R32G8X24_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS",
+ "dsvFormat": "DXGI_FORMAT_D32_FLOAT_S8X24_UINT",
+ "channels": "ds",
+ "bits": { "depth": 32, "stencil": 8 },
+ "glInternalFormat": "GL_DEPTH32F_STENCIL8"
+ },
+ "D16_UNORM": {
+ "FL10Plus": {
+ "texFormat": "DXGI_FORMAT_R16_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_R16_UNORM"
+ },
+ "FL9_3": {
+ "texFormat": "DXGI_FORMAT_D16_UNORM"
+ },
+ "dsvFormat": "DXGI_FORMAT_D16_UNORM",
+ "channels": "d",
+ "componentType": "unorm",
+ "bits": { "depth": 16 },
+ "glInternalFormat": "GL_DEPTH_COMPONENT16"
+ },
+ "D32_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R32_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_R32_FLOAT",
+ "dsvFormat": "DXGI_FORMAT_D32_FLOAT",
+ "channels": "d",
+ "componentType": "float",
+ "bits": { "depth": 32 },
+ "glInternalFormat": "GL_DEPTH_COMPONENT32F"
+ },
+ "R11G11B10_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+ "channels": "rgb",
+ "componentType": "float",
+ "bits": { "red": 11, "green": 11, "blue": 10 },
+ "glInternalFormat": "GL_R11F_G11F_B10F"
+ },
+ "R16_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16_FLOAT",
+ "channels": "r",
+ "componentType": "float",
+ "bits": { "red": 16 },
+ "glInternalFormat": "GL_R16F"
+ },
+ "R16_SINT": {
+ "texFormat": "DXGI_FORMAT_R16_SINT",
+ "srvFormat": "DXGI_FORMAT_R16_SINT",
+ "rtvFormat": "DXGI_FORMAT_R16_SINT",
+ "channels": "r",
+ "componentType": "int",
+ "bits": { "red": 16 },
+ "glInternalFormat": "GL_R16I"
+ },
+ "R16_UINT": {
+ "texFormat": "DXGI_FORMAT_R16_UINT",
+ "srvFormat": "DXGI_FORMAT_R16_UINT",
+ "rtvFormat": "DXGI_FORMAT_R16_UINT",
+ "channels": "r",
+ "componentType": "uint",
+ "bits": { "red": 16 },
+ "glInternalFormat": "GL_R16UI"
+ },
+ "R32_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32_FLOAT",
+ "channels": "r",
+ "componentType": "float",
+ "bits": { "red": 32 },
+ "glInternalFormat": "GL_R32F"
+ },
+ "R32_SINT": {
+ "texFormat": "DXGI_FORMAT_R32_SINT",
+ "srvFormat": "DXGI_FORMAT_R32_SINT",
+ "rtvFormat": "DXGI_FORMAT_R32_SINT",
+ "channels": "r",
+ "componentType": "int",
+ "bits": { "red": 32 },
+ "glInternalFormat": "GL_R32I"
+ },
+ "R32_UINT": {
+ "texFormat": "DXGI_FORMAT_R32_UINT",
+ "srvFormat": "DXGI_FORMAT_R32_UINT",
+ "rtvFormat": "DXGI_FORMAT_R32_UINT",
+ "channels": "r",
+ "componentType": "uint",
+ "bits": { "red": 32 },
+ "glInternalFormat": "GL_R32UI"
+ },
+ "R8_UNORM": {
+ "texFormat": "DXGI_FORMAT_R8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8_UNORM",
+ "channels": "r",
+ "componentType": "unorm",
+ "bits": { "red": 8 },
+ "glInternalFormat": "GL_R8"
+ },
+ "R8_SINT": {
+ "texFormat": "DXGI_FORMAT_R8_SINT",
+ "srvFormat": "DXGI_FORMAT_R8_SINT",
+ "rtvFormat": "DXGI_FORMAT_R8_SINT",
+ "channels": "r",
+ "componentType": "int",
+ "bits": { "red": 8 },
+ "glInternalFormat": "GL_R8I"
+ },
+ "R8_UINT": {
+ "texFormat": "DXGI_FORMAT_R8_UINT",
+ "srvFormat": "DXGI_FORMAT_R8_UINT",
+ "rtvFormat": "DXGI_FORMAT_R8_UINT",
+ "channels": "r",
+ "componentType": "uint",
+ "bits": { "red": 8 },
+ "glInternalFormat": "GL_R8UI"
+ },
+ "R8_SNORM": {
+ "texFormat": "DXGI_FORMAT_R8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8_SNORM",
+ "channels": "r",
+ "componentType": "snorm",
+ "bits": { "red": 8 },
+ "glInternalFormat": "GL_R8_SNORM"
+ },
+ "R16G16_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R16G16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16G16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16G16_FLOAT",
+ "channels": "rg",
+ "componentType": "float",
+ "bits": { "red": 16, "green": 16 },
+ "glInternalFormat": "GL_RG16F"
+ },
+ "R16G16_SINT": {
+ "texFormat": "DXGI_FORMAT_R16G16_SINT",
+ "srvFormat": "DXGI_FORMAT_R16G16_SINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16_SINT",
+ "channels": "rg",
+ "componentType": "int",
+ "bits": { "red": 16, "green": 16 },
+ "glInternalFormat": "GL_RG16I"
+ },
+ "R16G16_UINT": {
+ "texFormat": "DXGI_FORMAT_R16G16_UINT",
+ "srvFormat": "DXGI_FORMAT_R16G16_UINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16_UINT",
+ "channels": "rg",
+ "componentType": "uint",
+ "bits": { "red": 16, "green": 16 },
+ "glInternalFormat": "GL_RG16UI"
+ },
+ "R32G32_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R32G32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32_FLOAT",
+ "channels": "rg",
+ "componentType": "float",
+ "bits": { "red": 32, "green": 32 },
+ "glInternalFormat": "GL_RG32F"
+ },
+ "R32G32_SINT": {
+ "texFormat": "DXGI_FORMAT_R32G32_SINT",
+ "srvFormat": "DXGI_FORMAT_R32G32_SINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32_SINT",
+ "channels": "rg",
+ "componentType": "int",
+ "bits": { "red": 32, "green": 32 },
+ "glInternalFormat": "GL_RG32I"
+ },
+ "R32G32_UINT": {
+ "texFormat": "DXGI_FORMAT_R32G32_UINT",
+ "srvFormat": "DXGI_FORMAT_R32G32_UINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32_UINT",
+ "channels": "rg",
+ "componentType": "uint",
+ "bits": { "red": 32, "green": 32 },
+ "glInternalFormat": "GL_RG32UI"
+ },
+ "R8G8_UNORM": {
+ "texFormat": "DXGI_FORMAT_R8G8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8_UNORM",
+ "channels": "rg",
+ "componentType": "unorm",
+ "bits": { "red": 8, "green": 8 },
+ "glInternalFormat": "GL_RG8"
+ },
+ "R8G8_SINT": {
+ "texFormat": "DXGI_FORMAT_R8G8_SINT",
+ "srvFormat": "DXGI_FORMAT_R8G8_SINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8_SINT",
+ "channels": "rg",
+ "componentType": "int",
+ "bits": { "red": 8, "green": 8 },
+ "glInternalFormat": "GL_RG8I"
+ },
+ "R8G8_UINT": {
+ "texFormat": "DXGI_FORMAT_R8G8_UINT",
+ "srvFormat": "DXGI_FORMAT_R8G8_UINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8_UINT",
+ "channels": "rg",
+ "componentType": "uint",
+ "bits": { "red": 8, "green": 8 },
+ "glInternalFormat": "GL_RG8UI"
+ },
+ "R8G8_SNORM": {
+ "texFormat": "DXGI_FORMAT_R8G8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8_SNORM",
+ "channels": "rg",
+ "componentType": "snorm",
+ "bits": { "red": 8, "green": 8 },
+ "glInternalFormat": "GL_RG8_SNORM"
+ },
+ "R10G10B10A2_UNORM": {
+ "texFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
+ "srvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "bits": { "red": 10, "green": 10, "blue": 10, "alpha": 2 },
+ "glInternalFormat": "GL_RGB10_A2"
+ },
+ "R10G10B10A2_UINT": {
+ "texFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
+ "srvFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
+ "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
+ "channels": "rgba",
+ "componentType": "uint",
+ "bits": { "red": 10, "green": 10, "blue": 10, "alpha": 2 },
+ "glInternalFormat": "GL_RGB10_A2UI"
+ },
+ "R16G16B16A16_SINT": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "channels": "rgba",
+ "componentType": "int",
+ "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+ "glInternalFormat": "GL_RGBA16I"
+ },
+ "R16G16B16A16_UINT": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "channels": "rgba",
+ "componentType": "uint",
+ "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+ "glInternalFormat": "GL_RGBA16UI"
+ },
+ "R32G32B32A32_SINT": {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "channels": "rgba",
+ "componentType": "int",
+ "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 },
+ "glInternalFormat": "GL_RGBA32I"
+ },
+ "R32G32B32A32_UINT": {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "channels": "rgba",
+ "componentType": "uint",
+ "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 },
+ "glInternalFormat": "GL_RGBA32UI"
+ },
+ "B5G6R5_UNORM": {
+ "texFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+ "srvFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+ "channels": "bgr",
+ "componentType": "unorm",
+ "bits": { "red": 5, "green": 6, "blue": 5 },
+ "supportTest": "SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)",
+ "fallbackFormat": "R8G8B8A8_UNORM"
+ },
+ "B5G5R5A1_UNORM": {
+ "texFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+ "srvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+ "channels": "bgra",
+ "componentType": "unorm",
+ "bits": { "red": 5, "green": 5, "blue": 5, "alpha": 1 },
+ "supportTest": "SupportsFormat(DXGI_FORMAT_B5G5R5A1_UNORM, deviceCaps)",
+ "fallbackFormat": "R8G8B8A8_UNORM"
+ },
+ "R8G8B8A8_SINT": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "channels": "rgba",
+ "componentType": "int",
+ "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+ "glInternalFormat": "GL_RGBA8I"
+ },
+ "R8G8B8A8_UINT": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "channels": "rgba",
+ "componentType": "uint",
+ "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+ "glInternalFormat": "GL_RGBA8UI"
+ },
+ "R8G8B8A8_SNORM": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
+ "channels": "rgba",
+ "componentType": "snorm",
+ "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+ "glInternalFormat": "GL_RGBA8_SNORM"
+ },
+ "R9G9B9E5_SHAREDEXP": {
+ "texFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+ "srvFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+ "channels": "rgb",
+ "componentType": "float",
+ "bits": { "red": 9, "green": 9, "blue": 9, "shared": 5 }
+ },
+ "B4G4R4A4_UNORM": {
+ "texFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+ "srvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+ "channels": "bgra",
+ "componentType": "unorm",
+ "bits": { "red": 4, "green": 4, "blue": 4, "alpha": 4 },
+ "supportTest": "SupportsFormat(DXGI_FORMAT_B4G4R4A4_UNORM, deviceCaps)",
+ "fallbackFormat": "R8G8B8A8_UNORM"
+ },
+ "R8G8B8A8_UNORM_SRGB": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+ "glInternalFormat": "GL_SRGB8_ALPHA8"
+ },
+ "R16_UNORM": {
+ "texFormat": "DXGI_FORMAT_R16_UNORM",
+ "srvFormat": "DXGI_FORMAT_R16_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R16_UNORM",
+ "channels": "r",
+ "componentType": "unorm",
+ "bits": { "red": 16 },
+ "glInternalFormat": "GL_R16_EXT"
+ },
+ "R16G16_UNORM": {
+ "texFormat": "DXGI_FORMAT_R16G16_UNORM",
+ "srvFormat": "DXGI_FORMAT_R16G16_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R16G16_UNORM",
+ "channels": "rg",
+ "componentType": "unorm",
+ "bits": { "red": 16, "green": 16 },
+ "glInternalFormat": "GL_RG16_EXT"
+ },
+ "R16_SNORM": {
+ "texFormat": "DXGI_FORMAT_R16_SNORM",
+ "srvFormat": "DXGI_FORMAT_R16_SNORM",
+ "channels": "r",
+ "componentType": "snorm",
+ "bits": { "red": 16 },
+ "glInternalFormat": "GL_R16_SNORM_EXT"
+ },
+ "R16G16_SNORM": {
+ "texFormat": "DXGI_FORMAT_R16G16_SNORM",
+ "srvFormat": "DXGI_FORMAT_R16G16_SNORM",
+ "channels": "rg",
+ "componentType": "snorm",
+ "bits": { "red": 16, "green": 16 },
+ "glInternalFormat": "GL_RG16_SNORM_EXT"
+ },
+ "R16G16B16A16_SNORM": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_SNORM",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_SNORM",
+ "channels": "rgba",
+ "componentType": "snorm",
+ "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+ "glInternalFormat": "GL_RGBA16_SNORM_EXT"
+ }
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json
new file mode 100755
index 000000000..9b2e8d9db
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json
@@ -0,0 +1,74 @@
+{
+ "GL_ALPHA16F_EXT": "R16G16B16A16_FLOAT",
+ "GL_ALPHA32F_EXT": "R32G32B32A32_FLOAT",
+ "GL_BGR5_A1_ANGLEX": "B8G8R8A8_UNORM",
+ "GL_BGRA4_ANGLEX": "B8G8R8A8_UNORM",
+ "GL_COMPRESSED_R11_EAC": "R8_UNORM",
+ "GL_COMPRESSED_RG11_EAC": "R8G8_UNORM",
+ "GL_COMPRESSED_RGB8_ETC2": "R8G8B8A8_UNORM",
+ "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": "R8G8B8A8_UNORM",
+ "GL_COMPRESSED_RGBA8_ETC2_EAC": "R8G8B8A8_UNORM",
+ "GL_COMPRESSED_RGBA_ASTC_4x4_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_5x4_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_5x5_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_6x5_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_6x6_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_8x5_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_8x6_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_8x8_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_10x5_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_10x6_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_10x8_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_10x10_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_12x10_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_12x12_KHR": "NONE",
+ "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": "BC1_RGB_UNORM_BLOCK",
+ "GL_COMPRESSED_SIGNED_R11_EAC": "R8_SNORM",
+ "GL_COMPRESSED_SIGNED_RG11_EAC": "R8G8_SNORM",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": "R8G8B8A8_UNORM_SRGB",
+ "GL_COMPRESSED_SRGB8_ETC2": "R8G8B8A8_UNORM_SRGB",
+ "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": "R8G8B8A8_UNORM_SRGB",
+ "GL_DEPTH_COMPONENT24": "D24_UNORM_S8_UINT",
+ "GL_DEPTH_COMPONENT32_OES": "D24_UNORM_S8_UINT",
+ "GL_ETC1_RGB8_OES": "R8G8B8A8_UNORM",
+ "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": "BC1_RGB_UNORM_BLOCK",
+ "GL_LUMINANCE16F_EXT": "R16G16B16A16_FLOAT",
+ "GL_LUMINANCE32F_EXT": "R32G32B32A32_FLOAT",
+ "GL_LUMINANCE8_ALPHA8_EXT": "R8G8B8A8_UNORM",
+ "GL_LUMINANCE8_EXT": "R8G8B8A8_UNORM",
+ "GL_LUMINANCE_ALPHA16F_EXT": "R16G16B16A16_FLOAT",
+ "GL_LUMINANCE_ALPHA32F_EXT": "R32G32B32A32_FLOAT",
+ "GL_RGB": "R8G8B8A8_UNORM",
+ "GL_RGB16F": "R16G16B16A16_FLOAT",
+ "GL_RGB16I": "R16G16B16A16_SINT",
+ "GL_RGB16UI": "R16G16B16A16_UINT",
+ "GL_RGB565": "B5G6R5_UNORM",
+ "GL_RGB5_A1": "B5G5R5A1_UNORM",
+ "GL_RGB8": "R8G8B8A8_UNORM",
+ "GL_RGB8I": "R8G8B8A8_SINT",
+ "GL_RGB8UI": "R8G8B8A8_UINT",
+ "GL_RGB8_SNORM": "R8G8B8A8_SNORM",
+ "GL_RGBA4": "B4G4R4A4_UNORM",
+ "GL_SRGB8": "R8G8B8A8_UNORM_SRGB",
+ "GL_STENCIL_INDEX8": "D24_UNORM_S8_UINT",
+ "GL_RGB16_EXT": "R16G16B16A16_UNORM",
+ "GL_RGBA16_EXT": "R16G16B16A16_UNORM",
+ "GL_RGB16_SNORM_EXT": "R16G16B16A16_SNORM",
+ "GL_RGB32F": "R32G32B32A32_FLOAT",
+ "GL_RGB32I": "R32G32B32A32_SINT",
+ "GL_RGB32UI": "R32G32B32A32_UINT"
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
new file mode 100755
index 000000000..a9dfec56b
--- /dev/null
+++ b/gfx/angle/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/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
new file mode 100755
index 000000000..3be759f19
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
@@ -0,0 +1,105 @@
+//
+// 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/renderer_utils.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.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 : angle::NonCopyable
+{
+ constexpr Format();
+ constexpr Format(GLenum internalFormat,
+ angle::Format::ID formatID,
+ DXGI_FORMAT texFormat,
+ DXGI_FORMAT srvFormat,
+ DXGI_FORMAT rtvFormat,
+ DXGI_FORMAT dsvFormat,
+ DXGI_FORMAT blitSRVFormat,
+ 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::Format::ID formatID;
+
+ DXGI_FORMAT texFormat;
+ DXGI_FORMAT srvFormat;
+ DXGI_FORMAT rtvFormat;
+ DXGI_FORMAT dsvFormat;
+
+ DXGI_FORMAT blitSRVFormat;
+
+ GLenum swizzleFormat;
+
+ InitializeTextureDataFunction dataInitializerFunction;
+};
+
+constexpr Format::Format()
+ : internalFormat(GL_NONE),
+ formatID(angle::Format::ID::NONE),
+ texFormat(DXGI_FORMAT_UNKNOWN),
+ srvFormat(DXGI_FORMAT_UNKNOWN),
+ rtvFormat(DXGI_FORMAT_UNKNOWN),
+ dsvFormat(DXGI_FORMAT_UNKNOWN),
+ blitSRVFormat(DXGI_FORMAT_UNKNOWN),
+ swizzleFormat(GL_NONE),
+ dataInitializerFunction(nullptr)
+{
+}
+
+constexpr Format::Format(GLenum internalFormat,
+ angle::Format::ID formatID,
+ DXGI_FORMAT texFormat,
+ DXGI_FORMAT srvFormat,
+ DXGI_FORMAT rtvFormat,
+ DXGI_FORMAT dsvFormat,
+ DXGI_FORMAT blitSRVFormat,
+ GLenum swizzleFormat,
+ InitializeTextureDataFunction internalFormatInitializer)
+ : internalFormat(internalFormat),
+ formatID(formatID),
+ texFormat(texFormat),
+ srvFormat(srvFormat),
+ rtvFormat(rtvFormat),
+ dsvFormat(dsvFormat),
+ blitSRVFormat(blitSRVFormat),
+ swizzleFormat(swizzleFormat),
+ dataInitializerFunction(internalFormatInitializer)
+{
+}
+
+} // namespace d3d11
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
new file mode 100755
index 000000000..dd9c8757f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
@@ -0,0 +1,1821 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_texture_format_table.py using data from texture_format_data.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.
+//
+// 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::Format::ID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ GL_RGBA16F,
+ nullptr);
+ return info;
+ }
+ case GL_ALPHA32F_EXT:
+ {
+ static constexpr Format info(GL_ALPHA32F_EXT,
+ angle::Format::ID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_ALPHA8_EXT:
+ {
+ if (OnlyFL10Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_ALPHA8_EXT,
+ angle::Format::ID::A8_UNORM,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_ALPHA8_EXT,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_BGR565_ANGLEX:
+ {
+ if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps))
+ {
+ static constexpr Format info(GL_BGR565_ANGLEX,
+ angle::Format::ID::B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_BGR565_ANGLEX,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_BGR5_A1_ANGLEX:
+ {
+ static constexpr Format info(GL_BGR5_A1_ANGLEX,
+ angle::Format::ID::B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ GL_BGRA8_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_BGRA4_ANGLEX:
+ {
+ static constexpr Format info(GL_BGRA4_ANGLEX,
+ angle::Format::ID::B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ GL_BGRA8_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_BGRA8_EXT:
+ {
+ static constexpr Format info(GL_BGRA8_EXT,
+ angle::Format::ID::B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ GL_BGRA8_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_R11_EAC:
+ {
+ static constexpr Format info(GL_COMPRESSED_R11_EAC,
+ angle::Format::ID::R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RG11_EAC:
+ {
+ static constexpr Format info(GL_COMPRESSED_RG11_EAC,
+ angle::Format::ID::R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGB8_ETC2:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB8_ETC2,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA8_ETC2_EAC,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x10_KHR,
+ angle::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::BC1_RGBA_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,
+ angle::Format::ID::BC2_RGBA_UNORM_BLOCK,
+ DXGI_FORMAT_BC2_UNORM,
+ DXGI_FORMAT_BC2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC2_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,
+ angle::Format::ID::BC3_RGBA_UNORM_BLOCK,
+ DXGI_FORMAT_BC3_UNORM,
+ DXGI_FORMAT_BC3_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC3_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+ angle::Format::ID::BC1_RGB_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ {
+ static constexpr Format info(GL_COMPRESSED_SIGNED_R11_EAC,
+ angle::Format::ID::R8_SNORM,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_SNORM,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ {
+ static constexpr Format info(GL_COMPRESSED_SIGNED_RG11_EAC,
+ angle::Format::ID::R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_SNORM,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
+ angle::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::NONE,
+ 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::Format::ID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ GL_SRGB8_ALPHA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ETC2:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ETC2,
+ angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ GL_SRGB8_ALPHA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ GL_SRGB8_ALPHA8,
+ nullptr);
+ return info;
+ }
+ case GL_DEPTH24_STENCIL8:
+ {
+ if (OnlyFL10Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_DEPTH24_STENCIL8,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_DEPTH24_STENCIL8,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_DEPTH32F_STENCIL8:
+ {
+ static constexpr Format info(GL_DEPTH32F_STENCIL8,
+ angle::Format::ID::D32_FLOAT_S8X24_UINT,
+ DXGI_FORMAT_R32G8X24_TYPELESS,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_DEPTH_COMPONENT16:
+ {
+ if (OnlyFL10Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT16,
+ angle::Format::ID::D16_UNORM,
+ DXGI_FORMAT_R16_TYPELESS,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT16,
+ angle::Format::ID::D16_UNORM,
+ DXGI_FORMAT_D16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_DEPTH_COMPONENT24:
+ {
+ if (OnlyFL10Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT24,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT24,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_DEPTH_COMPONENT32F:
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT32F,
+ angle::Format::ID::D32_FLOAT,
+ DXGI_FORMAT_R32_TYPELESS,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_DEPTH_COMPONENT32_OES:
+ {
+ if (OnlyFL10Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT32_OES,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT32_OES,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ 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::Format::ID::BC1_RGB_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_ETC1_RGB8_OES:
+ {
+ static constexpr Format info(GL_ETC1_RGB8_OES,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_LUMINANCE16F_EXT:
+ {
+ static constexpr Format info(GL_LUMINANCE16F_EXT,
+ angle::Format::ID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ GL_RGBA16F,
+ Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>);
+ return info;
+ }
+ case GL_LUMINANCE32F_EXT:
+ {
+ static constexpr Format info(GL_LUMINANCE32F_EXT,
+ angle::Format::ID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ 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::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_LUMINANCE8_EXT:
+ {
+ static constexpr Format info(GL_LUMINANCE8_EXT,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ {
+ static constexpr Format info(GL_LUMINANCE_ALPHA16F_EXT,
+ angle::Format::ID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ GL_RGBA16F,
+ nullptr);
+ return info;
+ }
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ {
+ static constexpr Format info(GL_LUMINANCE_ALPHA32F_EXT,
+ angle::Format::ID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_NONE:
+ {
+ static constexpr Format info(GL_NONE,
+ angle::Format::ID::NONE,
+ 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::Format::ID::R11G11B10_FLOAT,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ GL_RGBA16F_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_R16F:
+ {
+ static constexpr Format info(GL_R16F,
+ angle::Format::ID::R16_FLOAT,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_FLOAT,
+ GL_RGBA16F_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_R16I:
+ {
+ static constexpr Format info(GL_R16I,
+ angle::Format::ID::R16_SINT,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_SINT,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_R16UI:
+ {
+ static constexpr Format info(GL_R16UI,
+ angle::Format::ID::R16_UINT,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_UINT,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_R16_EXT:
+ {
+ static constexpr Format info(GL_R16_EXT,
+ angle::Format::ID::R16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_UNORM,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_R16_SNORM_EXT:
+ {
+ static constexpr Format info(GL_R16_SNORM_EXT,
+ angle::Format::ID::R16_SNORM,
+ DXGI_FORMAT_R16_SNORM,
+ DXGI_FORMAT_R16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_SNORM,
+ GL_RGBA16_SNORM_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_R32F:
+ {
+ static constexpr Format info(GL_R32F,
+ angle::Format::ID::R32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32_FLOAT,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_R32I:
+ {
+ static constexpr Format info(GL_R32I,
+ angle::Format::ID::R32_SINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32_SINT,
+ GL_RGBA32I,
+ nullptr);
+ return info;
+ }
+ case GL_R32UI:
+ {
+ static constexpr Format info(GL_R32UI,
+ angle::Format::ID::R32_UINT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32_UINT,
+ GL_RGBA32I,
+ nullptr);
+ return info;
+ }
+ case GL_R8:
+ {
+ static constexpr Format info(GL_R8,
+ angle::Format::ID::R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_R8I:
+ {
+ static constexpr Format info(GL_R8I,
+ angle::Format::ID::R8_SINT,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_SINT,
+ GL_RGBA8I,
+ nullptr);
+ return info;
+ }
+ case GL_R8UI:
+ {
+ static constexpr Format info(GL_R8UI,
+ angle::Format::ID::R8_UINT,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_UINT,
+ GL_RGBA8I,
+ nullptr);
+ return info;
+ }
+ case GL_R8_SNORM:
+ {
+ static constexpr Format info(GL_R8_SNORM,
+ angle::Format::ID::R8_SNORM,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_SNORM,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
+ }
+ case GL_RG16F:
+ {
+ static constexpr Format info(GL_RG16F,
+ angle::Format::ID::R16G16_FLOAT,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_FLOAT,
+ GL_RGBA16F_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RG16I:
+ {
+ static constexpr Format info(GL_RG16I,
+ angle::Format::ID::R16G16_SINT,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_SINT,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_RG16UI:
+ {
+ static constexpr Format info(GL_RG16UI,
+ angle::Format::ID::R16G16_UINT,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_UINT,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_RG16_EXT:
+ {
+ static constexpr Format info(GL_RG16_EXT,
+ angle::Format::ID::R16G16_UNORM,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_UNORM,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RG16_SNORM_EXT:
+ {
+ static constexpr Format info(GL_RG16_SNORM_EXT,
+ angle::Format::ID::R16G16_SNORM,
+ DXGI_FORMAT_R16G16_SNORM,
+ DXGI_FORMAT_R16G16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_SNORM,
+ GL_RGBA16_SNORM_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RG32F:
+ {
+ static constexpr Format info(GL_RG32F,
+ angle::Format::ID::R32G32_FLOAT,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_FLOAT,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_RG32I:
+ {
+ static constexpr Format info(GL_RG32I,
+ angle::Format::ID::R32G32_SINT,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_SINT,
+ GL_RGBA32I,
+ nullptr);
+ return info;
+ }
+ case GL_RG32UI:
+ {
+ static constexpr Format info(GL_RG32UI,
+ angle::Format::ID::R32G32_UINT,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_UINT,
+ GL_RGBA32I,
+ nullptr);
+ return info;
+ }
+ case GL_RG8:
+ {
+ static constexpr Format info(GL_RG8,
+ angle::Format::ID::R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_RG8I:
+ {
+ static constexpr Format info(GL_RG8I,
+ angle::Format::ID::R8G8_SINT,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_SINT,
+ GL_RGBA8I,
+ nullptr);
+ return info;
+ }
+ case GL_RG8UI:
+ {
+ static constexpr Format info(GL_RG8UI,
+ angle::Format::ID::R8G8_UINT,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_UINT,
+ GL_RGBA8I,
+ nullptr);
+ return info;
+ }
+ case GL_RG8_SNORM:
+ {
+ static constexpr Format info(GL_RG8_SNORM,
+ angle::Format::ID::R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_SNORM,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
+ }
+ case GL_RGB:
+ {
+ static constexpr Format info(GL_RGB,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_RGB10_A2:
+ {
+ static constexpr Format info(GL_RGB10_A2,
+ angle::Format::ID::R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RGB10_A2UI:
+ {
+ static constexpr Format info(GL_RGB10_A2UI,
+ angle::Format::ID::R10G10B10A2_UINT,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_RGB16F:
+ {
+ static constexpr Format info(GL_RGB16F,
+ angle::Format::ID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ GL_RGBA16F,
+ Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>);
+ return info;
+ }
+ case GL_RGB16I:
+ {
+ static constexpr Format info(GL_RGB16I,
+ angle::Format::ID::R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ GL_RGBA16I,
+ Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>);
+ return info;
+ }
+ case GL_RGB16UI:
+ {
+ static constexpr Format info(GL_RGB16UI,
+ angle::Format::ID::R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ GL_RGBA16UI,
+ Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>);
+ return info;
+ }
+ case GL_RGB16_EXT:
+ {
+ static constexpr Format info(GL_RGB16_EXT,
+ angle::Format::ID::R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ 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::Format::ID::R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ GL_RGBA16_SNORM_EXT,
+ Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x7FFF>);
+ return info;
+ }
+ case GL_RGB32F:
+ {
+ static constexpr Format info(GL_RGB32F,
+ angle::Format::ID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ GL_RGBA32F,
+ Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>);
+ return info;
+ }
+ case GL_RGB32I:
+ {
+ static constexpr Format info(GL_RGB32I,
+ angle::Format::ID::R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ GL_RGBA32I,
+ Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>);
+ return info;
+ }
+ case GL_RGB32UI:
+ {
+ static constexpr Format info(GL_RGB32UI,
+ angle::Format::ID::R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ 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::Format::ID::B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_RGB565,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ 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::Format::ID::B5G5R5A1_UNORM,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_RGB5_A1,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_RGB8:
+ {
+ static constexpr Format info(GL_RGB8,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_RGB8I:
+ {
+ static constexpr Format info(GL_RGB8I,
+ angle::Format::ID::R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ GL_RGBA8I,
+ Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>);
+ return info;
+ }
+ case GL_RGB8UI:
+ {
+ static constexpr Format info(GL_RGB8UI,
+ angle::Format::ID::R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ GL_RGBA8UI,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>);
+ return info;
+ }
+ case GL_RGB8_SNORM:
+ {
+ static constexpr Format info(GL_RGB8_SNORM,
+ angle::Format::ID::R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ GL_RGBA8_SNORM,
+ Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x7F>);
+ return info;
+ }
+ case GL_RGB9_E5:
+ {
+ static constexpr Format info(GL_RGB9_E5,
+ angle::Format::ID::R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+ GL_RGBA16F_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA:
+ {
+ static constexpr Format info(GL_RGBA,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA16F:
+ {
+ static constexpr Format info(GL_RGBA16F,
+ angle::Format::ID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ GL_RGBA16F,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA16I:
+ {
+ static constexpr Format info(GL_RGBA16I,
+ angle::Format::ID::R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA16UI:
+ {
+ static constexpr Format info(GL_RGBA16UI,
+ angle::Format::ID::R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ GL_RGBA16UI,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA16_EXT:
+ {
+ static constexpr Format info(GL_RGBA16_EXT,
+ angle::Format::ID::R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA16_SNORM_EXT:
+ {
+ static constexpr Format info(GL_RGBA16_SNORM_EXT,
+ angle::Format::ID::R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ GL_RGBA16_SNORM_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA32F:
+ {
+ static constexpr Format info(GL_RGBA32F,
+ angle::Format::ID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA32I:
+ {
+ static constexpr Format info(GL_RGBA32I,
+ angle::Format::ID::R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ GL_RGBA32I,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA32UI:
+ {
+ static constexpr Format info(GL_RGBA32UI,
+ angle::Format::ID::R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ GL_RGBA32UI,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA4:
+ {
+ if (SupportsFormat(DXGI_FORMAT_B4G4R4A4_UNORM, deviceCaps))
+ {
+ static constexpr Format info(GL_RGBA4,
+ angle::Format::ID::B4G4R4A4_UNORM,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ GL_RGBA4,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_RGBA4,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_RGBA8:
+ {
+ static constexpr Format info(GL_RGBA8,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA8I:
+ {
+ static constexpr Format info(GL_RGBA8I,
+ angle::Format::ID::R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ GL_RGBA8I,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA8UI:
+ {
+ static constexpr Format info(GL_RGBA8UI,
+ angle::Format::ID::R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ GL_RGBA8UI,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA8_SNORM:
+ {
+ static constexpr Format info(GL_RGBA8_SNORM,
+ angle::Format::ID::R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
+ }
+ case GL_SRGB8:
+ {
+ static constexpr Format info(GL_SRGB8,
+ angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ GL_SRGB8_ALPHA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_SRGB8_ALPHA8:
+ {
+ static constexpr Format info(GL_SRGB8_ALPHA8,
+ angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ GL_SRGB8_ALPHA8,
+ nullptr);
+ return info;
+ }
+ case GL_STENCIL_INDEX8:
+ {
+ if (OnlyFL10Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_STENCIL_INDEX8,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_STENCIL_INDEX8,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ 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/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h
new file mode 100755
index 000000000..bffea6af9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h
@@ -0,0 +1,77 @@
+//
+// 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 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;
+
+ if (d3d11_gl::GetMaximumClientVersion(deviceCaps.featureLevel) > 2)
+ {
+ mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
+ }
+
+ 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);
+ }
+ else if (format == DXGI_FORMAT_B4G4R4A4_UNORM)
+ {
+ fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport);
+ }
+ else if (format == DXGI_FORMAT_B5G5R5A1_UNORM)
+ {
+ fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport);
+ }
+ 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/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp
new file mode 100755
index 000000000..ddfd58c74
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp
@@ -0,0 +1,242 @@
+//
+// Copyright (c) 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"
+
+#include <initguid.h>
+
+#ifdef HAS_DIRECT_COMPOSITION
+#include <dcomp.h>
+#endif // HAS_DIRECT_COMPOSITION
+
+namespace rx
+{
+
+NativeWindow11Win32::NativeWindow11Win32(EGLNativeWindowType window,
+ bool hasAlpha,
+ bool directComposition)
+ : NativeWindow11(window),
+ mDirectComposition(directComposition),
+ mHasAlpha(hasAlpha)
+
+#ifdef HAS_DIRECT_COMPOSITION
+
+ , mDevice(nullptr),
+ mCompositionTarget(nullptr),
+ mVisual(nullptr)
+
+#endif // HAS_DIRECT_COMPOSITION
+
+{
+}
+
+NativeWindow11Win32::~NativeWindow11Win32()
+{
+
+#ifdef HAS_DIRECT_COMPOSITION
+
+ SafeRelease(mCompositionTarget);
+ SafeRelease(mDevice);
+ SafeRelease(mVisual);
+
+#endif // HAS_DIRECT_COMPOSITION
+
+}
+
+bool NativeWindow11Win32::initialize()
+{
+ return true;
+}
+
+bool NativeWindow11Win32::getClientRect(LPRECT rect) const
+{
+ return GetClientRect(getNativeWindow(), rect) == TRUE;
+}
+
+bool NativeWindow11Win32::isIconic() const
+{
+ return IsIconic(getNativeWindow()) == TRUE;
+}
+
+#ifdef ANGLE_ENABLE_D3D11
+HRESULT NativeWindow11Win32::createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ IDXGISwapChain **swapChain)
+{
+ if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ if (mDirectComposition)
+ {
+#ifdef HAS_DIRECT_COMPOSITION
+ 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 = {0};
+ 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;
+#else // HAS_DIRECT_COMPOSITION
+ return E_INVALIDARG;
+#endif // HAS_DIRECT_COMPOSITION
+ }
+
+ // 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 = {0};
+ 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_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 = 1;
+ 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;
+}
+#endif // ANGLE_ENABLE_D3D11
+
+void NativeWindow11Win32::commitChange()
+{
+
+#ifdef HAS_DIRECT_COMPOSITION
+
+ if (mDevice)
+ {
+ mDevice->Commit();
+ }
+
+#endif // HAS_DIRECT_COMPOSITION
+
+}
+
+// static
+bool NativeWindow11Win32::IsValidNativeWindow(EGLNativeWindowType window)
+{
+ return IsWindow(window) == TRUE;
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h
new file mode 100755
index 000000000..8a9ebe800
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 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,
+ 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/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
new file mode 100755
index 000000000..0211e6887
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
@@ -0,0 +1,229 @@
+//
+// Copyright (c) 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.
+//
+
+// CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types.
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
+
+#include <windows.graphics.display.h>
+
+using namespace ABI::Windows::Foundation::Collections;
+
+namespace rx
+{
+CoreWindowNativeWindow::~CoreWindowNativeWindow()
+{
+ unregisterForSizeChangeEvents();
+}
+
+bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
+{
+ ComPtr<IPropertySet> props = propertySet;
+ ComPtr<IInspectable> win = window;
+ SIZE swapChainSize = {};
+ HRESULT result = S_OK;
+
+ // IPropertySet is an optional parameter and can be null.
+ // If one is specified, cache as an IMap and read the properties
+ // used for initial host initialization.
+ if (propertySet)
+ {
+ result = props.As(&mPropertyMap);
+ if (FAILED(result))
+ {
+ return false;
+ }
+
+ // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet
+ // was prevalidated to contain the EGLNativeWindowType before being passed to
+ // this host.
+ result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &mSwapChainSizeSpecified);
+ if (FAILED(result))
+ {
+ return false;
+ }
+
+ // The EGLRenderResolutionScaleProperty is optional and may be missing. The IPropertySet
+ // was prevalidated to contain the EGLNativeWindowType before being passed to
+ // this host.
+ result = GetOptionalSinglePropertyValue(mPropertyMap, EGLRenderResolutionScaleProperty, &mSwapChainScale, &mSwapChainScaleSpecified);
+ if (FAILED(result))
+ {
+ return false;
+ }
+
+ if (!mSwapChainScaleSpecified)
+ {
+ // Default value for the scale is 1.0f
+ mSwapChainScale = 1.0f;
+ }
+
+ // A EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty can't both be specified
+ if (mSwapChainScaleSpecified && mSwapChainSizeSpecified)
+ {
+ ERR("It is invalid to specify both an EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty.");
+ return false;
+ }
+ }
+
+ if (SUCCEEDED(result))
+ {
+ result = win.As(&mCoreWindow);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ // If a swapchain size is specfied, then the automatic resize
+ // behaviors implemented by the host should be disabled. The swapchain
+ // will be still be scaled when being rendered to fit the bounds
+ // of the host.
+ // Scaling of the swapchain output occurs automatically because if
+ // the scaling mode setting DXGI_SCALING_STRETCH on the swapchain.
+ if (mSwapChainSizeSpecified)
+ {
+ mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy };
+ }
+ else
+ {
+ Size coreWindowSize;
+ result = GetCoreWindowSizeInPixels(mCoreWindow, &coreWindowSize);
+
+ if (SUCCEEDED(result))
+ {
+ mClientRect = clientRect(coreWindowSize);
+ }
+ }
+ }
+
+ if (SUCCEEDED(result))
+ {
+ mNewClientRect = mClientRect;
+ mClientRectChanged = false;
+ return registerForSizeChangeEvents();
+ }
+
+ return false;
+}
+
+bool CoreWindowNativeWindow::registerForSizeChangeEvents()
+{
+ ComPtr<IWindowSizeChangedEventHandler> sizeChangedHandler;
+ HRESULT result = Microsoft::WRL::MakeAndInitialize<CoreWindowSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this());
+ if (SUCCEEDED(result))
+ {
+ result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+void CoreWindowNativeWindow::unregisterForSizeChangeEvents()
+{
+ if (mCoreWindow)
+ {
+ (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken);
+ }
+ mSizeChangedEventToken.value = 0;
+}
+
+HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device,
+ IDXGIFactory2 *factory,
+ DXGI_FORMAT format,
+ unsigned int width,
+ unsigned int height,
+ bool containsAlpha,
+ IDXGISwapChain1 **swapChain)
+{
+ if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
+ swapChainDesc.Width = width;
+ swapChainDesc.Height = height;
+ swapChainDesc.Format = format;
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+ swapChainDesc.BufferCount = 2;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
+
+ *swapChain = nullptr;
+
+ ComPtr<IDXGISwapChain1> newSwapChain;
+ HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
+ if (SUCCEEDED(result))
+ {
+ result = newSwapChain.CopyTo(swapChain);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ // If automatic swapchain resize behaviors have been disabled, then
+ // unregister for the resize change events.
+ if (mSupportsSwapChainResize == false)
+ {
+ unregisterForSizeChangeEvents();
+ }
+ }
+
+ return result;
+}
+
+inline HRESULT CoreWindowNativeWindow::scaleSwapChain(const Size &windowSize,
+ const RECT &clientRect)
+{
+ // We don't need to do any additional work to scale CoreWindow swapchains.
+ // Using DXGI_SCALING_STRETCH to create the swapchain above does all the necessary work.
+ return S_OK;
+}
+
+HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow> &coreWindow,
+ Size *windowSize)
+{
+ ABI::Windows::Foundation::Rect bounds;
+ HRESULT result = coreWindow->get_Bounds(&bounds);
+ if (SUCCEEDED(result))
+ {
+ *windowSize = { ConvertDipsToPixels(bounds.Width), ConvertDipsToPixels(bounds.Height) };
+ }
+
+ return result;
+}
+
+static float GetLogicalDpi()
+{
+ ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
+
+ if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
+ {
+ float dpi = 96.0f;
+ if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
+ {
+ return dpi;
+ }
+ }
+
+ // Return 96 dpi as a default if display properties cannot be obtained.
+ return 96.0f;
+}
+
+float ConvertDipsToPixels(float dips)
+{
+ static const float dipsPerInch = 96.0f;
+ return dips * GetLogicalDpi() / dipsPerInch;
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
new file mode 100755
index 000000000..d43bf0ba5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 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.
+//
+
+// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
+
+#include <memory>
+
+#include <EGL/eglplatform.h>
+
+typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler;
+
+namespace rx
+{
+float ConvertDipsToPixels(float dips);
+
+class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
+{
+ public:
+ ~CoreWindowNativeWindow();
+
+ bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override;
+ HRESULT createSwapChain(ID3D11Device *device,
+ IDXGIFactory2 *factory,
+ DXGI_FORMAT format,
+ unsigned int width,
+ unsigned int height,
+ bool containsAlpha,
+ IDXGISwapChain1 **swapChain) override;
+
+ protected:
+ HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override;
+
+ bool registerForSizeChangeEvents();
+ void unregisterForSizeChangeEvents();
+
+ private:
+ ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
+ ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
+};
+
+[uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)]
+class CoreWindowSizeChangedHandler :
+ public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler>
+{
+ public:
+ CoreWindowSizeChangedHandler() { }
+ HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host)
+ {
+ if (!host)
+ {
+ return E_INVALIDARG;
+ }
+
+ mHost = host;
+ return S_OK;
+ }
+
+ // IWindowSizeChangedEventHandler
+ IFACEMETHOD(Invoke)(ABI::Windows::UI::Core::ICoreWindow *sender, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *sizeChangedEventArgs)
+ {
+ std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
+ if (host)
+ {
+ ABI::Windows::Foundation::Size windowSize;
+ if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize)))
+ {
+ Size windowSizeInPixels = {ConvertDipsToPixels(windowSize.Width),
+ ConvertDipsToPixels(windowSize.Height)};
+ host->setNewClientSize(windowSizeInPixels);
+ }
+ }
+
+ return S_OK;
+ }
+
+ private:
+ std::weak_ptr<InspectableNativeWindow> mHost;
+};
+
+HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow> &coreWindow,
+ Size *windowSize);
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp
new file mode 100755
index 000000000..6b5ae14c5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp
@@ -0,0 +1,356 @@
+//
+// Copyright (c) 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 "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+// WINAPI_FAMILY is required to be defined as WINAPI_FAMILY_PC_APP
+// to ensure that the proper defines are set when including additional
+// headers which rely on Windows Store specific configuration.
+// This would normally be defined already but this unittest exe is compiled
+// as a desktop application which results in WINAPI_FAMILY being
+// set to WINAPI_FAMILY_DESKTOP_APP
+#undef WINAPI_FAMILY
+#define WINAPI_FAMILY WINAPI_FAMILY_PC_APP
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
+#include <angle_windowsstore.h>
+
+using namespace rx;
+using namespace ABI::Windows::ApplicationModel::Core;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::UI::Core;
+using namespace ABI::Windows::System;
+
+namespace
+{
+
+// Mock Generic interfaces which are NOT ICoreWindow or
+// IPropertySet
+MIDL_INTERFACE("A4D67D0A-0E7F-4DF7-918B-7A1395413AF2")
+IAmInspectable : public IInspectable
+{
+};
+
+class GenericIInspectable : public RuntimeClass <
+ RuntimeClassFlags<WinRtClassicComMix>,
+ IAmInspectable >
+{
+};
+
+MIDL_INTERFACE("3CBCFE7A-E000-4094-B2D2-B7C9A4D67A2C")
+IAmUnknown : public IUnknown
+{
+};
+
+class GenericIUnknown : public RuntimeClass <
+ RuntimeClassFlags<ClassicCom>,
+ IAmUnknown >
+{
+};
+
+// Mock ICoreWindow
+class MockCoreWindow : public ABI::Windows::UI::Core::ICoreWindow
+{
+ public:
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
+ {
+ *ppvObject = NULL;
+
+ if (IsEqualIID(IID_IUnknown, riid))
+ {
+ *ppvObject = static_cast<IUnknown*>(this);
+ return S_OK;
+ }
+
+ if (IsEqualIID(IID_IInspectable, riid))
+ {
+ *ppvObject = static_cast<IInspectable*>(this);
+ return S_OK;
+ }
+
+ if (IsEqualIID(IID_ICoreWindow, riid))
+ {
+ *ppvObject = static_cast<ABI::Windows::UI::Core::ICoreWindow*>(this);
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+ }
+
+ STDMETHOD_(ULONG, AddRef)(){ return 1; }
+ STDMETHOD_(ULONG, Release)(){ return 1; }
+
+ // IInspectable
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, GetIids, HRESULT(ULONG *, IID**));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetRuntimeClassName, HRESULT(HSTRING *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTrustLevel, HRESULT(TrustLevel *));
+
+ // ICoreWindow
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_AutomationHostProvider, HRESULT(IInspectable **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Bounds, HRESULT(Rect *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_CustomProperties, HRESULT(IPropertySet **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Dispatcher, HRESULT(ICoreDispatcher **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_FlowDirection, HRESULT(CoreWindowFlowDirection *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_FlowDirection, HRESULT(CoreWindowFlowDirection));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsInputEnabled, HRESULT(boolean *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsInputEnabled, HRESULT(boolean));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_PointerCursor, HRESULT(ICoreCursor**));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_PointerCursor, HRESULT(ICoreCursor*));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_PointerPosition, HRESULT(Point*));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Visible, HRESULT(boolean *));
+ MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, Activate, HRESULT());
+ MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, Close , HRESULT());
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, GetAsyncKeyState, HRESULT(ABI::Windows::System::VirtualKey, ABI::Windows::UI::Core::CoreVirtualKeyStates*));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, GetKeyState, HRESULT(ABI::Windows::System::VirtualKey, ABI::Windows::UI::Core::CoreVirtualKeyStates*));
+ MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, ReleasePointerCapture, HRESULT());
+ MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, SetPointerCapture, HRESULT());
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Activated, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowActivatedEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Activated, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_AutomationProviderRequested, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CAutomationProviderRequestedEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_AutomationProviderRequested, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_CharacterReceived, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CCharacterReceivedEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_CharacterReceived, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Closed, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CCoreWindowEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Closed, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_InputEnabled, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CInputEnabledEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_InputEnabled, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_KeyDown, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CKeyEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_KeyDown, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_KeyUp, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CKeyEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_KeyUp, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerCaptureLost, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerCaptureLost, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerEntered, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerEntered, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerExited, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerExited, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerMoved, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerMoved, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerPressed, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerPressed, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerReleased, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerReleased, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_TouchHitTesting, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CTouchHitTestingEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_TouchHitTesting, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerWheelChanged, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CPointerEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerWheelChanged, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_SizeChanged, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_SizeChanged, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_VisibilityChanged, HRESULT(__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CVisibilityChangedEventArgs*, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_VisibilityChanged, HRESULT(EventRegistrationToken));
+};
+
+HRESULT CreatePropertyMap(IMap<HSTRING, IInspectable*>** propertyMap)
+{
+ HRESULT result = S_OK;
+ ComPtr<IPropertySet> propertySet;
+ ComPtr<IActivationFactory> propertySetFactory;
+ result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Collections_PropertySet).Get(), &propertySetFactory);
+ EXPECT_HRESULT_SUCCEEDED(result);
+
+ result = propertySetFactory->ActivateInstance(&propertySet);
+ EXPECT_HRESULT_SUCCEEDED(result);
+
+ result = propertySet.CopyTo(propertyMap);
+ EXPECT_HRESULT_SUCCEEDED(result);
+
+ return result;
+}
+
+HRESULT CreatePropertyValueStatics(IPropertyValueStatics** propertyStatics)
+{
+ ComPtr<IPropertyValueStatics> propertyValueStatics;
+ HRESULT result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), &propertyValueStatics);
+ EXPECT_HRESULT_SUCCEEDED(result);
+
+ result = propertyValueStatics.CopyTo(propertyStatics);
+ EXPECT_HRESULT_SUCCEEDED(result);
+
+ return result;
+}
+
+HRESULT SetInspectablePropertyValue(const ComPtr<IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t* propertyName, IInspectable* inspectable)
+{
+ boolean propertyReplaced = false;
+ return propertyMap->Insert(HStringReference(propertyName).Get(), inspectable, &propertyReplaced);
+}
+
+void expectNativeWindowInitCalls(MockCoreWindow &coreWindow, bool expectBounds)
+{
+ if (expectBounds)
+ {
+ EXPECT_CALL(coreWindow, get_Bounds(testing::_)).Times(1);
+ }
+
+ EXPECT_CALL(coreWindow, add_SizeChanged(testing::_, testing::_)).Times(1);
+ EXPECT_CALL(coreWindow, remove_SizeChanged(testing::_)).Times(1);
+}
+
+TEST(NativeWindowTest, NativeWindowNull)
+{
+ NativeWindow nativeWindow(nullptr);
+ EXPECT_FALSE(nativeWindow.initialize());
+}
+
+TEST(NativeWindowTest, NativeWindowBadInspectable)
+{
+ ComPtr<IAmInspectable> notCoreWindow = Make<GenericIInspectable>();
+ NativeWindow nativeWindow(notCoreWindow.Get());
+ EXPECT_FALSE(nativeWindow.initialize());
+}
+
+TEST(NativeWindowTest, NativeWindowNotInspectable)
+{
+ ComPtr<IAmUnknown> notIInspectable = Make<GenericIUnknown>();
+ NativeWindow nativeWindow((IInspectable*)notIInspectable.Get());
+ EXPECT_FALSE(nativeWindow.initialize());
+}
+
+TEST(NativeWindowTest, NativeWindowValidCoreWindow)
+{
+ MockCoreWindow mockCoreWindow;
+ expectNativeWindowInitCalls(mockCoreWindow, true);
+ NativeWindow nativeWindow(&mockCoreWindow);
+ EXPECT_TRUE(nativeWindow.initialize());
+}
+
+TEST(NativeWindowTest, NativeWindowValidCoreWindowInPropertySet)
+{
+ // COM is required to be initialized for creation of the property set
+ EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED));
+ {
+ MockCoreWindow mockCoreWindow;
+ ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+
+ // Add the CoreWindow to the property set
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, &mockCoreWindow));
+
+ expectNativeWindowInitCalls(mockCoreWindow, true);
+ NativeWindow nativeWindow(propertySet.Get());
+ EXPECT_TRUE(nativeWindow.initialize());
+ }
+ CoUninitialize();
+}
+
+TEST(NativeWindowTest, NativeWindowMissingCoreWindowInPropertySet)
+{
+ // COM is required to be initialized for creation of the property set
+ EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED));
+ {
+ MockCoreWindow mockCoreWindow;
+ ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+
+ NativeWindow nativeWindow(propertySet.Get());
+ EXPECT_FALSE(nativeWindow.initialize());
+ }
+ CoUninitialize();
+}
+
+// Tests that the scale property works as expected in a property set with a SwapChainPanel
+class CoreWindowScaleTest : public testing::TestWithParam<std::pair<float, bool>>
+{
+};
+
+TEST_P(CoreWindowScaleTest, ValidateScale)
+{
+ float scale = GetParam().first;
+ bool expectedResult = GetParam().second;
+
+ // COM is required to be initialized for creation of the property set
+ EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED));
+ {
+ MockCoreWindow mockCoreWindow;
+ ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+ ComPtr<IPropertyValueStatics> propertyValueStatics;
+ ComPtr<IPropertyValue> singleValue;
+
+ // Create a simple property set
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockCoreWindow)));
+
+ // Add a valid scale factor to the property set
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf()));
+ propertyValueStatics->CreateSingle(scale, reinterpret_cast<IInspectable**>(singleValue.GetAddressOf()));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderResolutionScaleProperty, reinterpret_cast<IInspectable*>(singleValue.Get())));
+
+ // Check native window init status and calls to the mock swapchainpanel
+ NativeWindow nativeWindow(propertySet.Get());
+ if (expectedResult)
+ {
+ expectNativeWindowInitCalls(mockCoreWindow, true);
+ }
+
+ EXPECT_EQ(nativeWindow.initialize(), expectedResult);
+ }
+ CoUninitialize();
+}
+
+typedef std::pair<float, bool> scaleValidPair;
+static const scaleValidPair scales[] = { scaleValidPair(1.0f, true),
+ scaleValidPair(0.5f, true),
+ scaleValidPair(0.0f, false),
+ scaleValidPair(0.01f, true),
+ scaleValidPair(2.00f, true) };
+
+INSTANTIATE_TEST_CASE_P(NativeWindowTest,
+ CoreWindowScaleTest,
+ testing::ValuesIn(scales));
+
+// Tests that the size property works as expected in a property set with a SwapChainPanel
+class CoreWindowSizeTest : public testing::TestWithParam<std::tuple<float, float, bool>>
+{
+};
+
+TEST_P(CoreWindowSizeTest, ValidateSize)
+{
+ Size renderSize = { std::get<0>(GetParam()), std::get<1>(GetParam()) };
+ bool expectedResult = std::get<2>(GetParam());
+
+ // COM is required to be initialized for creation of the property set
+ EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED));
+ {
+ MockCoreWindow mockCoreWindow;
+ ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+ ComPtr<IPropertyValueStatics> propertyValueStatics;
+ ComPtr<IPropertyValue> sizeValue;
+
+ // Create a simple property set
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockCoreWindow)));
+
+ // Add a valid size to the property set
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf()));
+ propertyValueStatics->CreateSize(renderSize, reinterpret_cast<IInspectable**>(sizeValue.GetAddressOf()));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderSurfaceSizeProperty, reinterpret_cast<IInspectable*>(sizeValue.Get())));
+
+ // Check native window init status and calls to the mock swapchainpanel
+ NativeWindow nativeWindow(propertySet.Get());
+ if (expectedResult)
+ {
+ expectNativeWindowInitCalls(mockCoreWindow, false);
+ }
+
+ EXPECT_EQ(nativeWindow.initialize(), expectedResult);
+ }
+ CoUninitialize();
+}
+
+typedef std::tuple<float, float, bool> sizeValidPair;
+static const sizeValidPair sizes[] = { sizeValidPair( 800, 480, true),
+ sizeValidPair( 0, 480, false),
+ sizeValidPair( 800, 0, false),
+ sizeValidPair( 0, 0, false) };
+
+INSTANTIATE_TEST_CASE_P(NativeWindowTest,
+ CoreWindowSizeTest,
+ testing::ValuesIn(sizes));
+
+} // namespace
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
new file mode 100755
index 000000000..c7fcf8634
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
@@ -0,0 +1,276 @@
+//
+// Copyright (c) 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.
+//
+
+// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types.
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h"
+
+namespace rx
+{
+
+bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow)
+{
+ if (!window)
+ {
+ return false;
+ }
+
+ ComPtr<IInspectable> win = window;
+ ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWin;
+ if (SUCCEEDED(win.As(&coreWin)))
+ {
+ if (coreWindow != nullptr)
+ {
+ *coreWindow = coreWin.Detach();
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel)
+{
+ if (!window)
+ {
+ return false;
+ }
+
+ ComPtr<IInspectable> win = window;
+ ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> panel;
+ if (SUCCEEDED(win.As(&panel)))
+ {
+ if (swapChainPanel != nullptr)
+ {
+ *swapChainPanel = panel.Detach();
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet, IInspectable **eglNativeWindow)
+{
+ if (!window)
+ {
+ return false;
+ }
+
+ ComPtr<IInspectable> props = window;
+ ComPtr<IPropertySet> propSet;
+ ComPtr<IInspectable> nativeWindow;
+ ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> propMap;
+ boolean hasEglNativeWindowPropertyKey = false;
+
+ HRESULT result = props.As(&propSet);
+ if (SUCCEEDED(result))
+ {
+ result = propSet.As(&propMap);
+ }
+
+ // Look for the presence of the EGLNativeWindowType in the property set
+ if (SUCCEEDED(result))
+ {
+ result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEglNativeWindowPropertyKey);
+ }
+
+ // If the IPropertySet does not contain the required EglNativeWindowType key, the property set is
+ // considered invalid.
+ if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey)
+ {
+ ERR("Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid EGLNativeWindowTypeProperty values include ICoreWindow");
+ return false;
+ }
+
+ // The EglNativeWindowType property exists, so retreive the IInspectable that represents the EGLNativeWindowType
+ if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey)
+ {
+ result = propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ if (propertySet != nullptr)
+ {
+ result = propSet.CopyTo(propertySet);
+ }
+ }
+
+ if (SUCCEEDED(result))
+ {
+ if (eglNativeWindow != nullptr)
+ {
+ result = nativeWindow.CopyTo(eglNativeWindow);
+ }
+ }
+
+ if (SUCCEEDED(result))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Retrieve an optional property from a property set
+HRESULT GetOptionalPropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
+ const wchar_t *propertyName,
+ boolean *hasKey,
+ ComPtr<ABI::Windows::Foundation::IPropertyValue> &propertyValue)
+{
+ if (!propertyMap || !hasKey)
+ {
+ return E_INVALIDARG;
+ }
+
+ // Assume that the value does not exist
+ *hasKey = false;
+
+ HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), hasKey);
+ if (SUCCEEDED(result) && !(*hasKey))
+ {
+ // Value does not exist, so return S_OK and set the exists parameter to false to indicate
+ // that a the optional property does not exist.
+ return S_OK;
+ }
+
+ if (SUCCEEDED(result))
+ {
+ result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue);
+ }
+
+ return result;
+}
+
+// Attempts to read an optional SIZE property value that is assumed to be in the form of
+// an ABI::Windows::Foundation::Size. This function validates the Size value before returning
+// it to the caller.
+//
+// Possible return values are:
+// S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated
+// S_OK, valueExists == false - optional SIZE value was not found
+// E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set.
+// * Incorrect property type ( must be PropertyType_Size)
+// * Invalid property value (width/height must be > 0)
+// Additional errors may be returned from IMap or IPropertyValue
+//
+HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
+ const wchar_t *propertyName, SIZE *value, bool *valueExists)
+{
+ ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue;
+ ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty;
+ Size sizeValue = { 0, 0 };
+ boolean hasKey = false;
+
+ if (!propertyMap || !value || !valueExists)
+ {
+ return E_INVALIDARG;
+ }
+
+ // Assume that the value does not exist
+ *valueExists = false;
+ *value = { 0, 0 };
+
+ HRESULT result = GetOptionalPropertyValue(propertyMap, propertyName, &hasKey, propertyValue);
+ if (SUCCEEDED(result) && hasKey)
+ {
+ result = propertyValue->get_Type(&propertyType);
+
+ // Check if the expected Size property is of PropertyType_Size type.
+ if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size)
+ {
+ if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0))
+ {
+ // A valid property value exists
+ *value = { static_cast<long>(sizeValue.Width), static_cast<long>(sizeValue.Height) };
+ *valueExists = true;
+ result = S_OK;
+ }
+ else
+ {
+ // An invalid Size property was detected. Width/Height values must > 0
+ result = E_INVALIDARG;
+ }
+ }
+ else
+ {
+ // An invalid property type was detected. Size property must be of PropertyType_Size
+ result = E_INVALIDARG;
+ }
+ }
+
+ return result;
+}
+
+// Attempts to read an optional float property value that is assumed to be in the form of
+// an ABI::Windows::Foundation::Single. This function validates the Single value before returning
+// it to the caller.
+//
+// Possible return values are:
+// S_OK, valueExists == true - optional Single value was successfully retrieved and validated
+// S_OK, valueExists == false - optional Single value was not found
+// E_INVALIDARG, valueExists = false - optional Single value was malformed in the property set.
+// * Incorrect property type ( must be PropertyType_Single)
+// * Invalid property value (must be > 0)
+// Additional errors may be returned from IMap or IPropertyValue
+//
+HRESULT GetOptionalSinglePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
+ const wchar_t *propertyName, float *value, bool *valueExists)
+{
+ ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue;
+ ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty;
+ float scaleValue = 0.0f;
+ boolean hasKey = false;
+
+ if (!propertyMap || !value || !valueExists)
+ {
+ return E_INVALIDARG;
+ }
+
+ // Assume that the value does not exist
+ *valueExists = false;
+ *value = 0.0f;
+
+ HRESULT result = GetOptionalPropertyValue(propertyMap, propertyName, &hasKey, propertyValue);
+ if (SUCCEEDED(result) && hasKey)
+ {
+ result = propertyValue->get_Type(&propertyType);
+
+ // Check if the expected Scale property is of PropertyType_Single type.
+ if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Single)
+ {
+ if (SUCCEEDED(propertyValue->GetSingle(&scaleValue)) && (scaleValue > 0.0f))
+ {
+ // A valid property value exists
+ *value = scaleValue;
+ *valueExists = true;
+ result = S_OK;
+ }
+ else
+ {
+ // An invalid scale was set
+ result = E_INVALIDARG;
+ }
+ }
+ else
+ {
+ // An invalid property type was detected. Size property must be of PropertyType_Single
+ result = E_INVALIDARG;
+ }
+ }
+
+ return result;
+}
+
+RECT InspectableNativeWindow::clientRect(const Size &size)
+{
+ // We don't have to check if a swapchain scale was specified here; the default value is 1.0f
+ // which will have no effect.
+ return {0, 0, lround(size.Width * mSwapChainScale), lround(size.Height * mSwapChainScale)};
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
new file mode 100755
index 000000000..3e67269f3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
@@ -0,0 +1,131 @@
+//
+// Copyright (c) 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.
+//
+
+// InspectableNativeWindow.h: Host specific implementation interface for
+// managing IInspectable native window types.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+#include "angle_windowsstore.h"
+
+#include <EGL/eglplatform.h>
+
+#include <windows.applicationmodel.core.h>
+#include <windows.ui.xaml.h>
+#include <windows.ui.xaml.media.dxinterop.h>
+#include <wrl.h>
+#include <wrl/wrappers/corewrappers.h>
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+
+namespace rx
+{
+class InspectableNativeWindow
+{
+ public:
+ InspectableNativeWindow() :
+ mSupportsSwapChainResize(true),
+ mSwapChainSizeSpecified(false),
+ mSwapChainScaleSpecified(false),
+ mSwapChainScale(1.0f),
+ mClientRectChanged(false),
+ mClientRect({0,0,0,0}),
+ mNewClientRect({0,0,0,0})
+ {
+ mSizeChangedEventToken.value = 0;
+ }
+ virtual ~InspectableNativeWindow(){}
+
+ virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0;
+ virtual HRESULT createSwapChain(ID3D11Device *device,
+ IDXGIFactory2 *factory,
+ DXGI_FORMAT format,
+ unsigned int width,
+ unsigned int height,
+ bool containsAlpha,
+ IDXGISwapChain1 **swapChain) = 0;
+
+ bool getClientRect(RECT *rect)
+ {
+ if (mClientRectChanged)
+ {
+ mClientRect = mNewClientRect;
+ }
+
+ *rect = mClientRect;
+
+ return true;
+ }
+
+ // setNewClientSize is used by the WinRT size change handler. It isn't used by the rest of ANGLE.
+ void setNewClientSize(const Size &newWindowSize)
+ {
+ // If the client doesn't support swapchain resizing then we should have already unregistered from size change handler
+ ASSERT(mSupportsSwapChainResize);
+
+ if (mSupportsSwapChainResize)
+ {
+ // If the swapchain size was specified then we should ignore this call too
+ if (!mSwapChainSizeSpecified)
+ {
+ mNewClientRect = clientRect(newWindowSize);
+ mClientRectChanged = true;
+
+ // If a scale was specified, then now is the time to apply the scale matrix for the new swapchain size and window size
+ if (mSwapChainScaleSpecified)
+ {
+ scaleSwapChain(newWindowSize, mNewClientRect);
+ }
+ }
+
+ // Even if the swapchain size was fixed, the window might have changed size.
+ // In this case, we should recalculate the scale matrix to account for the new window size
+ if (mSwapChainSizeSpecified)
+ {
+ scaleSwapChain(newWindowSize, mClientRect);
+ }
+ }
+ }
+
+ protected:
+ virtual HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) = 0;
+ RECT clientRect(const Size &size);
+
+ bool mSupportsSwapChainResize; // Support for IDXGISwapChain::ResizeBuffers method
+ bool mSwapChainSizeSpecified; // If an EGLRenderSurfaceSizeProperty was specified
+ bool mSwapChainScaleSpecified; // If an EGLRenderResolutionScaleProperty was specified
+ float mSwapChainScale; // The scale value specified by the EGLRenderResolutionScaleProperty property
+ RECT mClientRect;
+ RECT mNewClientRect;
+ bool mClientRectChanged;
+
+ EventRegistrationToken mSizeChangedEventToken;
+};
+
+bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow = nullptr);
+bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel = nullptr);
+bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr);
+
+HRESULT GetOptionalPropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
+ const wchar_t *propertyName,
+ boolean *hasKey,
+ ComPtr<ABI::Windows::Foundation::IPropertyValue> &propertyValue);
+
+HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
+ const wchar_t *propertyName, SIZE *value, bool *valueExists);
+
+HRESULT GetOptionalSinglePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
+ const wchar_t *propertyName, float *value, bool *valueExists);
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp
new file mode 100755
index 000000000..a5ce4ca68
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp
@@ -0,0 +1,126 @@
+//
+// Copyright (c) 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.
+//
+
+// NativeWindow11WinRT.cpp: NativeWindow base class for managing IInspectable native window types.
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h"
+
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h"
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+
+namespace rx
+{
+NativeWindow11WinRT::NativeWindow11WinRT(EGLNativeWindowType window, bool hasAlpha)
+ : NativeWindow11(window), mHasAlpha(hasAlpha)
+{
+}
+
+bool NativeWindow11WinRT::initialize()
+{
+ EGLNativeWindowType window = getNativeWindow();
+
+ // If the native window type is a IPropertySet, extract the
+ // EGLNativeWindowType (IInspectable) and initialize the
+ // proper host with this IPropertySet.
+ ComPtr<ABI::Windows::Foundation::Collections::IPropertySet> propertySet;
+ ComPtr<IInspectable> eglNativeWindow;
+ if (IsEGLConfiguredPropertySet(window, &propertySet, &eglNativeWindow))
+ {
+ // A property set was found and the EGLNativeWindowType was
+ // retrieved. The mWindow member of the host to must be updated
+ // to use the EGLNativeWindowType specified in the property set.
+ // mWindow is treated as a raw pointer not an AddRef'd interface, so
+ // the old mWindow does not need a Release() before this assignment.
+ window = eglNativeWindow.Get();
+ }
+
+ ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow;
+ ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
+ if (IsCoreWindow(window, &coreWindow))
+ {
+ mImpl = std::make_shared<CoreWindowNativeWindow>();
+ if (mImpl)
+ {
+ return mImpl->initialize(window, propertySet.Get());
+ }
+ }
+ else if (IsSwapChainPanel(window, &swapChainPanel))
+ {
+ mImpl = std::make_shared<SwapChainPanelNativeWindow>();
+ if (mImpl)
+ {
+ return mImpl->initialize(window, propertySet.Get());
+ }
+ }
+ else
+ {
+ ERR(
+ "Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include "
+ "ICoreWindow, ISwapChainPanel and IPropertySet");
+ }
+
+ return false;
+}
+
+bool NativeWindow11WinRT::getClientRect(LPRECT rect) const
+{
+ if (mImpl)
+ {
+ return mImpl->getClientRect(rect);
+ }
+
+ return false;
+}
+
+bool NativeWindow11WinRT::isIconic() const
+{
+ return false;
+}
+
+HRESULT NativeWindow11WinRT::createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ IDXGISwapChain **swapChain)
+{
+ if (mImpl)
+ {
+ IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
+ IDXGISwapChain1 *swapChain1 = nullptr;
+ HRESULT result =
+ mImpl->createSwapChain(device, factory2, format, width, height, mHasAlpha, &swapChain1);
+ SafeRelease(factory2);
+ *swapChain = static_cast<IDXGISwapChain *>(swapChain1);
+ return result;
+ }
+
+ return E_UNEXPECTED;
+}
+
+void NativeWindow11WinRT::commitChange()
+{
+}
+
+// static
+bool NativeWindow11WinRT::IsValidNativeWindow(EGLNativeWindowType window)
+{
+ // A Valid EGLNativeWindowType IInspectable can only be:
+ //
+ // ICoreWindow
+ // ISwapChainPanel
+ // IPropertySet
+ //
+ // Anything else will be rejected as an invalid IInspectable.
+ return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h
new file mode 100755
index 000000000..996fd3a10
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 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.
+//
+
+// NativeWindow11WinRT.h: NativeWindow base class for managing IInspectable native window types.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_
+
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h"
+
+#include <memory>
+#include <windows.applicationmodel.core.h>
+#include <wrl.h>
+#include <wrl/wrappers/corewrappers.h>
+
+namespace rx
+{
+class InspectableNativeWindow;
+
+class NativeWindow11WinRT : public NativeWindow11
+{
+ public:
+ NativeWindow11WinRT(EGLNativeWindowType window, bool hasAlpha);
+
+ 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,
+ IDXGISwapChain **swapChain) override;
+
+ void commitChange() override;
+
+ static bool IsValidNativeWindow(EGLNativeWindowType window);
+
+ private:
+ bool mHasAlpha;
+ std::shared_ptr<InspectableNativeWindow> mImpl;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
new file mode 100755
index 000000000..1dae1ad7d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
@@ -0,0 +1,355 @@
+//
+// Copyright (c) 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.
+//
+
+// SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types.
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h"
+
+#include <algorithm>
+#include <math.h>
+
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::UI::Core;
+using namespace ABI::Windows::UI::Xaml;
+using namespace Microsoft::WRL;
+
+namespace rx
+{
+SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow()
+{
+ unregisterForSizeChangeEvents();
+}
+
+template <typename T>
+struct AddFtmBase
+{
+ typedef Implements<RuntimeClassFlags<ClassicCom>, T, FtmBase> Type;
+};
+
+template <typename CODE>
+HRESULT RunOnUIThread(CODE &&code, const ComPtr<ICoreDispatcher> &dispatcher)
+{
+ ComPtr<IAsyncAction> asyncAction;
+ HRESULT result = S_OK;
+
+ boolean hasThreadAccess;
+ result = dispatcher->get_HasThreadAccess(&hasThreadAccess);
+ if (FAILED(result))
+ {
+ return result;
+ }
+
+ if (hasThreadAccess)
+ {
+ return code();
+ }
+ else
+ {
+ Event waitEvent(CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS));
+ if (!waitEvent.IsValid())
+ {
+ return E_FAIL;
+ }
+
+ HRESULT codeResult = E_FAIL;
+ auto handler =
+ Callback<AddFtmBase<IDispatchedHandler>::Type>([&codeResult, &code, &waitEvent]
+ {
+ codeResult = code();
+ SetEvent(waitEvent.Get());
+ return S_OK;
+ });
+
+ result = dispatcher->RunAsync(CoreDispatcherPriority_Normal, handler.Get(),
+ asyncAction.GetAddressOf());
+ if (FAILED(result))
+ {
+ return result;
+ }
+
+ auto waitResult = WaitForSingleObjectEx(waitEvent.Get(), 10 * 1000, true);
+ if (waitResult != WAIT_OBJECT_0)
+ {
+ // Wait 10 seconds before giving up. At this point, the application is in an
+ // unrecoverable state (probably deadlocked). We therefore terminate the application
+ // entirely. This also prevents stack corruption if the async operation is eventually
+ // run.
+ ERR("Timeout waiting for async action on UI thread. The UI thread might be blocked.");
+ std::terminate();
+ return E_FAIL;
+ }
+
+ return codeResult;
+ }
+}
+
+bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
+{
+ ComPtr<IPropertySet> props = propertySet;
+ ComPtr<IInspectable> win = window;
+ SIZE swapChainSize = {};
+ HRESULT result = S_OK;
+
+ // IPropertySet is an optional parameter and can be null.
+ // If one is specified, cache as an IMap and read the properties
+ // used for initial host initialization.
+ if (propertySet)
+ {
+ result = props.As(&mPropertyMap);
+ if (FAILED(result))
+ {
+ return false;
+ }
+
+ // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet
+ // was prevalidated to contain the EGLNativeWindowType before being passed to
+ // this host.
+ result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &mSwapChainSizeSpecified);
+ if (FAILED(result))
+ {
+ return false;
+ }
+
+ // The EGLRenderResolutionScaleProperty is optional and may be missing. The IPropertySet
+ // was prevalidated to contain the EGLNativeWindowType before being passed to
+ // this host.
+ result = GetOptionalSinglePropertyValue(mPropertyMap, EGLRenderResolutionScaleProperty, &mSwapChainScale, &mSwapChainScaleSpecified);
+ if (FAILED(result))
+ {
+ return false;
+ }
+
+ if (!mSwapChainScaleSpecified)
+ {
+ // Default value for the scale is 1.0f
+ mSwapChainScale = 1.0f;
+ }
+
+ // A EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty can't both be specified
+ if (mSwapChainScaleSpecified && mSwapChainSizeSpecified)
+ {
+ ERR("It is invalid to specify both an EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty.");
+ return false;
+ }
+ }
+
+ if (SUCCEEDED(result))
+ {
+ result = win.As(&mSwapChainPanel);
+ }
+
+ ComPtr<IDependencyObject> swapChainPanelDependencyObject;
+ if (SUCCEEDED(result))
+ {
+ result = mSwapChainPanel.As(&swapChainPanelDependencyObject);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ result = swapChainPanelDependencyObject->get_Dispatcher(
+ mSwapChainPanelDispatcher.GetAddressOf());
+ }
+
+ if (SUCCEEDED(result))
+ {
+ // If a swapchain size is specfied, then the automatic resize
+ // behaviors implemented by the host should be disabled. The swapchain
+ // will be still be scaled when being rendered to fit the bounds
+ // of the host.
+ // Scaling of the swapchain output needs to be handled by the
+ // host for swapchain panels even though the scaling mode setting
+ // DXGI_SCALING_STRETCH is configured on the swapchain.
+ if (mSwapChainSizeSpecified)
+ {
+ mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy };
+ }
+ else
+ {
+ Size swapChainPanelSize;
+ result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher,
+ &swapChainPanelSize);
+
+ if (SUCCEEDED(result))
+ {
+ // Update the client rect to account for any swapchain scale factor
+ mClientRect = clientRect(swapChainPanelSize);
+ }
+ }
+ }
+
+ if (SUCCEEDED(result))
+ {
+ mNewClientRect = mClientRect;
+ mClientRectChanged = false;
+ return registerForSizeChangeEvents();
+ }
+
+ return false;
+}
+
+bool SwapChainPanelNativeWindow::registerForSizeChangeEvents()
+{
+ ComPtr<ISizeChangedEventHandler> sizeChangedHandler;
+ ComPtr<IFrameworkElement> frameworkElement;
+ HRESULT result = Microsoft::WRL::MakeAndInitialize<SwapChainPanelSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this());
+
+ if (SUCCEEDED(result))
+ {
+ result = mSwapChainPanel.As(&frameworkElement);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ result = RunOnUIThread(
+ [this, frameworkElement, sizeChangedHandler]
+ {
+ return frameworkElement->add_SizeChanged(sizeChangedHandler.Get(),
+ &mSizeChangedEventToken);
+ },
+ mSwapChainPanelDispatcher);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents()
+{
+ ComPtr<IFrameworkElement> frameworkElement;
+ if (mSwapChainPanel && SUCCEEDED(mSwapChainPanel.As(&frameworkElement)))
+ {
+ RunOnUIThread(
+ [this, frameworkElement]
+ {
+ return frameworkElement->remove_SizeChanged(mSizeChangedEventToken);
+ },
+ mSwapChainPanelDispatcher);
+ }
+
+ mSizeChangedEventToken.value = 0;
+}
+
+HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device,
+ IDXGIFactory2 *factory,
+ DXGI_FORMAT format,
+ unsigned int width,
+ unsigned int height,
+ bool containsAlpha,
+ IDXGISwapChain1 **swapChain)
+{
+ if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
+ swapChainDesc.Width = width;
+ swapChainDesc.Height = height;
+ swapChainDesc.Format = format;
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+ swapChainDesc.BufferCount = 2;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.AlphaMode =
+ containsAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
+
+ *swapChain = nullptr;
+
+ ComPtr<IDXGISwapChain1> newSwapChain;
+ ComPtr<ISwapChainPanelNative> swapChainPanelNative;
+ Size currentPanelSize = {};
+
+ HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
+
+ if (SUCCEEDED(result))
+ {
+ result = mSwapChainPanel.As(&swapChainPanelNative);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ result = RunOnUIThread(
+ [swapChainPanelNative, newSwapChain]
+ {
+ return swapChainPanelNative->SetSwapChain(newSwapChain.Get());
+ },
+ mSwapChainPanelDispatcher);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ // The swapchain panel host requires an instance of the swapchain set on the SwapChainPanel
+ // to perform the runtime-scale behavior. This swapchain is cached here because there are
+ // no methods for retreiving the currently configured on from ISwapChainPanelNative.
+ mSwapChain = newSwapChain;
+ result = newSwapChain.CopyTo(swapChain);
+ }
+
+ // If the host is responsible for scaling the output of the swapchain, then
+ // scale it now before returning an instance to the caller. This is done by
+ // first reading the current size of the swapchain panel, then scaling
+ if (SUCCEEDED(result))
+ {
+ if (mSwapChainSizeSpecified || mSwapChainScaleSpecified)
+ {
+ result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher,
+ &currentPanelSize);
+
+ // Scale the swapchain to fit inside the contents of the panel.
+ if (SUCCEEDED(result))
+ {
+ result = scaleSwapChain(currentPanelSize, mClientRect);
+ }
+ }
+ }
+
+ return result;
+}
+
+HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &windowSize, const RECT &clientRect)
+{
+ Size renderScale = {windowSize.Width / (float)clientRect.right,
+ windowSize.Height / (float)clientRect.bottom};
+ // Setup a scale matrix for the swap chain
+ DXGI_MATRIX_3X2_F scaleMatrix = {};
+ scaleMatrix._11 = renderScale.Width;
+ scaleMatrix._22 = renderScale.Height;
+
+ ComPtr<IDXGISwapChain2> swapChain2;
+ HRESULT result = mSwapChain.As(&swapChain2);
+ if (SUCCEEDED(result))
+ {
+ result = swapChain2->SetMatrixTransform(&scaleMatrix);
+ }
+
+ return result;
+}
+
+HRESULT GetSwapChainPanelSize(
+ const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel,
+ const ComPtr<ICoreDispatcher> &dispatcher,
+ Size *windowSize)
+{
+ ComPtr<IUIElement> uiElement;
+ HRESULT result = swapChainPanel.As(&uiElement);
+ if (SUCCEEDED(result))
+ {
+ result = RunOnUIThread(
+ [uiElement, windowSize] { return uiElement->get_RenderSize(windowSize); }, dispatcher);
+ }
+
+ return result;
+}
+} \ No newline at end of file
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
new file mode 100755
index 000000000..f9a2fc0e4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 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.
+//
+
+// SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
+
+#include <memory>
+
+namespace rx
+{
+class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<SwapChainPanelNativeWindow>
+{
+ public:
+ ~SwapChainPanelNativeWindow();
+
+ bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override;
+ HRESULT createSwapChain(ID3D11Device *device,
+ IDXGIFactory2 *factory,
+ DXGI_FORMAT format,
+ unsigned int width,
+ unsigned int height,
+ bool containsAlpha,
+ IDXGISwapChain1 **swapChain) override;
+
+ protected:
+ HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override;
+
+ bool registerForSizeChangeEvents();
+ void unregisterForSizeChangeEvents();
+
+ private:
+ ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel;
+ ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> mSwapChainPanelDispatcher;
+ ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
+ ComPtr<IDXGISwapChain1> mSwapChain;
+};
+
+[uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)]
+class SwapChainPanelSizeChangedHandler :
+ public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::UI::Xaml::ISizeChangedEventHandler>
+{
+ public:
+ SwapChainPanelSizeChangedHandler() { }
+ HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host)
+ {
+ if (!host)
+ {
+ return E_INVALIDARG;
+ }
+
+ mHost = host;
+ return S_OK;
+ }
+
+ // ISizeChangedEventHandler
+ IFACEMETHOD(Invoke)(IInspectable *sender, ABI::Windows::UI::Xaml::ISizeChangedEventArgs *sizeChangedEventArgs)
+ {
+ std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
+ if (host)
+ {
+ // The size of the ISwapChainPanel control is returned in DIPs.
+ // We are keeping these in dips because the swapchain created for composition
+ // also uses dip units. This keeps dimensions, viewports, etc in the same unit.
+ // XAML Clients of the ISwapChainPanel are required to use dips to define their
+ // layout sizes as well.
+ ABI::Windows::Foundation::Size newSize;
+ HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize);
+ if (SUCCEEDED(result))
+ {
+ host->setNewClientSize(newSize);
+ }
+ }
+
+ return S_OK;
+ }
+
+ private:
+ std::weak_ptr<InspectableNativeWindow> mHost;
+};
+
+HRESULT GetSwapChainPanelSize(
+ const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel,
+ const ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> &dispatcher,
+ Size *windowSize);
+}
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp
new file mode 100755
index 000000000..026c42449
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp
@@ -0,0 +1,460 @@
+//
+// Copyright (c) 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 "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+// WINAPI_FAMILY is required to be defined as WINAPI_FAMILY_PC_APP
+// to ensure that the proper defines are set when including additional
+// headers which rely on Windows Store specific configuration.
+// This would normally be defined already but this unittest exe is compiled
+// as a desktop application which results in WINAPI_FAMILY being
+// set to WINAPI_FAMILY_DESKTOP_APP
+#undef WINAPI_FAMILY
+#define WINAPI_FAMILY WINAPI_FAMILY_PC_APP
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
+#include <angle_windowsstore.h>
+#include <windows.ui.xaml.h>
+#include <windows.ui.xaml.media.dxinterop.h>
+
+using namespace rx;
+using namespace ABI::Windows::ApplicationModel::Core;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::UI::Core;
+using namespace ABI::Windows::System;
+using namespace ABI::Windows::UI::Xaml::Controls;
+using namespace ABI::Windows::UI::Xaml::Data;
+using namespace ABI::Windows::UI::Xaml::Media;
+using namespace ABI::Windows::UI::Xaml::Input;
+using namespace ABI::Windows::UI::Xaml;
+
+namespace
+{
+
+// Mock ISwapChainPanel
+class MockSwapChainPanel : public ISwapChainPanel,
+ IFrameworkElement,
+ IUIElement,
+ ISwapChainPanelNative
+{
+ public:
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
+ {
+ *ppvObject = NULL;
+
+ if (IsEqualIID(IID_IUnknown, riid))
+ {
+ *ppvObject = reinterpret_cast<IUnknown*>(this);
+ return S_OK;
+ }
+
+ if (IsEqualIID(IID_IInspectable, riid))
+ {
+ *ppvObject = reinterpret_cast<IInspectable*>(this);
+ return S_OK;
+ }
+
+ if (IsEqualIID(IID_ISwapChainPanel, riid))
+ {
+ *ppvObject = static_cast<ISwapChainPanel*>(this);
+ return S_OK;
+ }
+
+ if (IsEqualIID(IID_IFrameworkElement, riid))
+ {
+ *ppvObject = static_cast<IFrameworkElement*>(this);
+ return S_OK;
+ }
+
+ if (IsEqualIID(IID_IUIElement, riid))
+ {
+ *ppvObject = static_cast<IUIElement*>(this);
+ return S_OK;
+ }
+
+ if (IsEqualIID(__uuidof(ISwapChainPanelNative), riid))
+ {
+ *ppvObject = static_cast<ISwapChainPanelNative*>(this);
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+ }
+
+ STDMETHOD_(ULONG, AddRef)(){ return 1; }
+ STDMETHOD_(ULONG, Release)(){ return 1; }
+
+ // IInspectable
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, GetIids, HRESULT(ULONG *, IID**));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetRuntimeClassName, HRESULT(HSTRING *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTrustLevel, HRESULT(TrustLevel *));
+
+ // ISwapChainPanelNative
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, SetSwapChain, HRESULT(IDXGISwapChain *));
+
+ // ISwapChainPanel
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_CompositionScaleX, HRESULT(FLOAT *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_CompositionScaleY, HRESULT(FLOAT *));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_CompositionScaleChanged, HRESULT(__FITypedEventHandler_2_Windows__CUI__CXaml__CControls__CSwapChainPanel_IInspectable*, EventRegistrationToken*));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_CompositionScaleChanged, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, CreateCoreIndependentInputSource, HRESULT(CoreInputDeviceTypes, ICoreInputSourceBase**));
+
+ // IFrameworkElement
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Triggers, HRESULT(__FIVector_1_Windows__CUI__CXaml__CTriggerBase **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Resources, HRESULT(IResourceDictionary **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Resources, HRESULT(IResourceDictionary *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Tag, HRESULT(IInspectable **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Tag, HRESULT(IInspectable *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Language, HRESULT(HSTRING *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Language, HRESULT(HSTRING));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_ActualWidth, HRESULT(DOUBLE *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_ActualHeight, HRESULT(DOUBLE *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Width, HRESULT(DOUBLE *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Width, HRESULT(DOUBLE));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Height, HRESULT(DOUBLE *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Height, HRESULT(DOUBLE));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_MinWidth, HRESULT(DOUBLE *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_MinWidth, HRESULT(DOUBLE));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_MaxWidth, HRESULT(DOUBLE *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_MaxWidth, HRESULT(DOUBLE));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_MinHeight, HRESULT(DOUBLE *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_MinHeight, HRESULT(DOUBLE));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_MaxHeight, HRESULT(DOUBLE *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_MaxHeight, HRESULT(DOUBLE));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_HorizontalAlignment, HRESULT(HorizontalAlignment *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_HorizontalAlignment, HRESULT(HorizontalAlignment));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_VerticalAlignment, HRESULT(VerticalAlignment *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_VerticalAlignment, HRESULT(VerticalAlignment));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Margin, HRESULT(Thickness *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Margin, HRESULT(Thickness));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Name, HRESULT(HSTRING*));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Name, HRESULT(HSTRING));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_BaseUri, HRESULT(IUriRuntimeClass **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_DataContext, HRESULT(IInspectable **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_DataContext, HRESULT(IInspectable *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Style, HRESULT(IStyle **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Style, HRESULT(IStyle *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Parent, HRESULT(IDependencyObject **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_FlowDirection, HRESULT(FlowDirection *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_FlowDirection, HRESULT(FlowDirection));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Loaded, HRESULT(IRoutedEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Loaded, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Unloaded, HRESULT(IRoutedEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Unloaded, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_SizeChanged, HRESULT(ISizeChangedEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_SizeChanged, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_LayoutUpdated, HRESULT(__FIEventHandler_1_IInspectable *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_LayoutUpdated, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, FindName, HRESULT(HSTRING, IInspectable **));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, SetBinding, HRESULT(IDependencyProperty *, IBindingBase *));
+
+ // IUIElement
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_DesiredSize, HRESULT(ABI::Windows::Foundation::Size *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_AllowDrop, HRESULT(boolean *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_AllowDrop, HRESULT(boolean));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Opacity, HRESULT(DOUBLE *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Opacity, HRESULT(DOUBLE));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Clip, HRESULT(IRectangleGeometry **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Clip, HRESULT(IRectangleGeometry *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_RenderTransform, HRESULT(ITransform **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_RenderTransform, HRESULT(ITransform *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Projection, HRESULT(IProjection **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Projection, HRESULT(IProjection *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_RenderTransformOrigin, HRESULT(Point *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_RenderTransformOrigin, HRESULT(Point));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsHitTestVisible, HRESULT(boolean *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsHitTestVisible, HRESULT(boolean));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Visibility, HRESULT(Visibility *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Visibility, HRESULT(Visibility));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_RenderSize, HRESULT(Size *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_UseLayoutRounding, HRESULT(boolean *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_UseLayoutRounding, HRESULT(boolean));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_Transitions, HRESULT(__FIVector_1_Windows__CUI__CXaml__CMedia__CAnimation__CTransition **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_Transitions, HRESULT(__FIVector_1_Windows__CUI__CXaml__CMedia__CAnimation__CTransition *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_CacheMode, HRESULT(ICacheMode **));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_CacheMode, HRESULT(ICacheMode *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsTapEnabled, HRESULT(boolean *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsTapEnabled, HRESULT(boolean));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsDoubleTapEnabled, HRESULT(boolean *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsDoubleTapEnabled, HRESULT(boolean));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsRightTapEnabled, HRESULT(boolean *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsRightTapEnabled, HRESULT(boolean));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_IsHoldingEnabled, HRESULT(boolean *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_IsHoldingEnabled, HRESULT(boolean));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_ManipulationMode, HRESULT(ManipulationModes *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, put_ManipulationMode, HRESULT(ManipulationModes));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, get_PointerCaptures, HRESULT(__FIVectorView_1_Windows__CUI__CXaml__CInput__CPointer **));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_KeyUp, HRESULT(IKeyEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_KeyUp, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_KeyDown, HRESULT(IKeyEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_KeyDown, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_GotFocus, HRESULT(IRoutedEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_GotFocus, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_LostFocus, HRESULT(IRoutedEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_LostFocus, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_DragEnter, HRESULT(IDragEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_DragEnter, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_DragLeave, HRESULT(IDragEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_DragLeave, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_DragOver, HRESULT(IDragEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_DragOver, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Drop, HRESULT(IDragEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Drop, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerPressed, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerPressed, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerMoved, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerMoved, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerReleased, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerReleased, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerExited, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerExited, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerCaptureLost, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerCaptureLost, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerCanceled, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerCanceled, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerWheelChanged, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerWheelChanged, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_PointerEntered, HRESULT(IPointerEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_PointerEntered, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Tapped, HRESULT(ITappedEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Tapped, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_DoubleTapped, HRESULT(IDoubleTappedEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_DoubleTapped, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_Holding, HRESULT(IHoldingEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_Holding, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_RightTapped, HRESULT(IRightTappedEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_RightTapped, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationStarting, HRESULT(IManipulationStartingEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationStarting, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationInertiaStarting, HRESULT(IManipulationInertiaStartingEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationInertiaStarting, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationStarted, HRESULT(IManipulationStartedEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationStarted, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationDelta, HRESULT(IManipulationDeltaEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationDelta, HRESULT(EventRegistrationToken));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, add_ManipulationCompleted, HRESULT(IManipulationCompletedEventHandler *, EventRegistrationToken *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, remove_ManipulationCompleted, HRESULT(EventRegistrationToken));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Measure, HRESULT(Size));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Arrange, HRESULT(Rect));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, CapturePointer, HRESULT(IPointer *, boolean *));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, ReleasePointerCapture, HRESULT(IPointer *));
+ MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, ReleasePointerCaptures, HRESULT());
+ MOCK_METHOD3_WITH_CALLTYPE(STDMETHODCALLTYPE, AddHandler, HRESULT(IRoutedEvent *, IInspectable *, boolean));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, RemoveHandler, HRESULT(IRoutedEvent *, IInspectable *));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, TransformToVisual, HRESULT(IUIElement *, IGeneralTransform **));
+ MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, InvalidateMeasure, HRESULT());
+ MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, InvalidateArrange, HRESULT());
+ MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, UpdateLayout, HRESULT());
+};
+
+HRESULT CreatePropertyMap(IMap<HSTRING, IInspectable*>** propertyMap)
+{
+ HRESULT result = S_OK;
+ ComPtr<IPropertySet> propertySet;
+ ComPtr<IActivationFactory> propertySetFactory;
+ result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Collections_PropertySet).Get(), &propertySetFactory);
+ EXPECT_HRESULT_SUCCEEDED(result);
+
+ result = propertySetFactory->ActivateInstance(&propertySet);
+ EXPECT_HRESULT_SUCCEEDED(result);
+
+ result = propertySet.CopyTo(propertyMap);
+ EXPECT_HRESULT_SUCCEEDED(result);
+
+ return result;
+}
+
+HRESULT CreatePropertyValueStatics(IPropertyValueStatics** propertyStatics)
+{
+ ComPtr<IPropertyValueStatics> propertyValueStatics;
+ HRESULT result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), &propertyValueStatics);
+ EXPECT_HRESULT_SUCCEEDED(result);
+
+ result = propertyValueStatics.CopyTo(propertyStatics);
+ EXPECT_HRESULT_SUCCEEDED(result);
+
+ return result;
+}
+
+HRESULT SetInspectablePropertyValue(const ComPtr<IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t* propertyName, IInspectable* inspectable)
+{
+ boolean propertyReplaced = false;
+ return propertyMap->Insert(HStringReference(propertyName).Get(), inspectable, &propertyReplaced);
+}
+
+void expectNativeWindowInitCalls(MockSwapChainPanel &panel, bool expectRenderSize)
+{
+ if (expectRenderSize)
+ {
+ EXPECT_CALL(panel, get_RenderSize(testing::_)).Times(1);
+ }
+
+ EXPECT_CALL(panel, add_SizeChanged(testing::_, testing::_)).Times(1);
+ EXPECT_CALL(panel, remove_SizeChanged(testing::_)).Times(1);
+}
+
+TEST(NativeWindowTest, SwapChainPanelByItself)
+{
+ MockSwapChainPanel mockSwapChainPanel;
+ NativeWindow nativeWindow(reinterpret_cast<IInspectable*>(&mockSwapChainPanel));
+ expectNativeWindowInitCalls(mockSwapChainPanel, true);
+ EXPECT_TRUE(nativeWindow.initialize());
+}
+
+TEST(NativeWindowTest, SwapChainPanelInPropertySet)
+{
+ // COM is required to be initialized for creation of the property set
+ EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED));
+ {
+ MockSwapChainPanel mockSwapChainPanel;
+ ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+
+ // Create a simple property set with the swapchainpanel
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockSwapChainPanel)));
+
+ // Check native window init calls
+ NativeWindow nativeWindow(propertySet.Get());
+ expectNativeWindowInitCalls(mockSwapChainPanel, true);
+ EXPECT_TRUE(nativeWindow.initialize());
+ }
+ CoUninitialize();
+}
+
+TEST(NativeWindowTest, SwapChainPanelInPropertySetWithSizeAndScale)
+{
+ // COM is required to be initialized for creation of the property set
+ EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED));
+ {
+ MockSwapChainPanel mockSwapChainPanel;
+ ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+ ComPtr<IPropertyValueStatics> propertyValueStatics;
+ ComPtr<IPropertyValue> singleValue;
+ ComPtr<IPropertyValue> sizeValue;
+
+ // Create a simple property set with the swapchainpanel
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockSwapChainPanel)));
+
+ // Add a valid scale factor to the property set
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf()));
+ propertyValueStatics->CreateSingle(0.5f, reinterpret_cast<IInspectable**>(singleValue.GetAddressOf()));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderResolutionScaleProperty, reinterpret_cast<IInspectable*>(singleValue.Get())));
+
+ // Add a valid size to the property set
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf()));
+ propertyValueStatics->CreateSize({ 480, 800 }, reinterpret_cast<IInspectable**>(sizeValue.GetAddressOf()));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderSurfaceSizeProperty, reinterpret_cast<IInspectable*>(sizeValue.Get())));
+
+ // Check native window init fails, since we shouldn't be able to set a size and a scale together
+ NativeWindow nativeWindow(propertySet.Get());
+ EXPECT_FALSE(nativeWindow.initialize());
+ }
+ CoUninitialize();
+}
+
+// Tests that the scale property works as expected in a property set with a SwapChainPanel
+class SwapChainPanelScaleTest : public testing::TestWithParam<std::pair<float, bool>>
+{
+};
+
+TEST_P(SwapChainPanelScaleTest, ValidateScale)
+{
+ float scale = GetParam().first;
+ bool expectedResult = GetParam().second;
+
+ // COM is required to be initialized for creation of the property set
+ EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED));
+ {
+ MockSwapChainPanel mockSwapChainPanel;
+ ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+ ComPtr<IPropertyValueStatics> propertyValueStatics;
+ ComPtr<IPropertyValue> singleValue;
+
+ // Create a simple property set
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockSwapChainPanel)));
+
+ // Add a valid scale factor to the property set
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf()));
+ propertyValueStatics->CreateSingle(scale, reinterpret_cast<IInspectable**>(singleValue.GetAddressOf()));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderResolutionScaleProperty, reinterpret_cast<IInspectable*>(singleValue.Get())));
+
+ // Check native window init status and calls to the mock swapchainpanel
+ NativeWindow nativeWindow(propertySet.Get());
+ if (expectedResult)
+ {
+ expectNativeWindowInitCalls(mockSwapChainPanel, true);
+ }
+
+ EXPECT_EQ(nativeWindow.initialize(), expectedResult);
+ }
+ CoUninitialize();
+}
+
+typedef std::pair<float, bool> scaleValidPair;
+static const scaleValidPair scales[] = { scaleValidPair(1.0f, true),
+ scaleValidPair(0.5f, true),
+ scaleValidPair(0.0f, false),
+ scaleValidPair(0.01f, true),
+ scaleValidPair(2.00f, true) };
+
+INSTANTIATE_TEST_CASE_P(NativeWindowTest,
+ SwapChainPanelScaleTest,
+ testing::ValuesIn(scales));
+
+// Tests that the size property works as expected in a property set with a SwapChainPanel
+class SwapChainPanelSizeTest : public testing::TestWithParam<std::tuple<float, float, bool>>
+{
+};
+
+TEST_P(SwapChainPanelSizeTest, ValidateSize)
+{
+ Size renderSize = { std::get<0>(GetParam()), std::get<1>(GetParam()) };
+ bool expectedResult = std::get<2>(GetParam());
+
+ // COM is required to be initialized for creation of the property set
+ EXPECT_HRESULT_SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED));
+ {
+ MockSwapChainPanel mockSwapChainPanel;
+ ComPtr<IMap<HSTRING, IInspectable*>> propertySet;
+ ComPtr<IPropertyValueStatics> propertyValueStatics;
+ ComPtr<IPropertyValue> sizeValue;
+
+ // Create a simple property set
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyMap(&propertySet));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLNativeWindowTypeProperty, reinterpret_cast<IInspectable*>(&mockSwapChainPanel)));
+
+ // Add a valid size to the property set
+ EXPECT_HRESULT_SUCCEEDED(CreatePropertyValueStatics(propertyValueStatics.GetAddressOf()));
+ propertyValueStatics->CreateSize(renderSize, reinterpret_cast<IInspectable**>(sizeValue.GetAddressOf()));
+ EXPECT_HRESULT_SUCCEEDED(SetInspectablePropertyValue(propertySet, EGLRenderSurfaceSizeProperty, reinterpret_cast<IInspectable*>(sizeValue.Get())));
+
+ // Check native window init status and calls to the mock swapchainpanel
+ NativeWindow nativeWindow(propertySet.Get());
+ if (expectedResult)
+ {
+ expectNativeWindowInitCalls(mockSwapChainPanel, false);
+ }
+
+ EXPECT_EQ(nativeWindow.initialize(), expectedResult);
+ }
+ CoUninitialize();
+}
+
+typedef std::tuple<float, float, bool> sizeValidPair;
+static const sizeValidPair sizes[] = { sizeValidPair( 800, 480, true),
+ sizeValidPair( 0, 480, false),
+ sizeValidPair( 800, 0, false),
+ sizeValidPair( 0, 0, false) };
+
+INSTANTIATE_TEST_CASE_P(NativeWindowTest,
+ SwapChainPanelSizeTest,
+ testing::ValuesIn(sizes));
+
+} // namespace
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
new file mode 100755
index 000000000..95320f228
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
@@ -0,0 +1,694 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// Blit9.cpp: Surface copy utility class.
+
+#include "libANGLE/renderer/d3d/d3d9/Blit9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+
+namespace
+{
+// Precompiled shaders
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h"
+
+const BYTE* const g_shaderCode[] =
+{
+ g_vs20_standardvs,
+ g_vs20_flipyvs,
+ g_ps20_passthroughps,
+ g_ps20_luminanceps,
+ g_ps20_componentmaskps
+};
+
+const size_t g_shaderSize[] =
+{
+ sizeof(g_vs20_standardvs),
+ sizeof(g_vs20_flipyvs),
+ sizeof(g_ps20_passthroughps),
+ sizeof(g_ps20_luminanceps),
+ sizeof(g_ps20_componentmaskps)
+};
+}
+
+namespace rx
+{
+
+Blit9::Blit9(Renderer9 *renderer)
+ : mRenderer(renderer),
+ mGeometryLoaded(false),
+ mQuadVertexBuffer(NULL),
+ mQuadVertexDeclaration(NULL),
+ mSavedStateBlock(NULL),
+ mSavedRenderTarget(NULL),
+ mSavedDepthStencil(NULL)
+{
+ memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
+}
+
+Blit9::~Blit9()
+{
+ SafeRelease(mSavedStateBlock);
+ SafeRelease(mQuadVertexBuffer);
+ SafeRelease(mQuadVertexDeclaration);
+
+ for (int i = 0; i < SHADER_COUNT; i++)
+ {
+ SafeRelease(mCompiledShaders[i]);
+ }
+}
+
+gl::Error Blit9::initialize()
+{
+ if (mGeometryLoaded)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ 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, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal blit vertex shader, result: 0x%X.", result);
+ }
+
+ void *lockPtr = NULL;
+ result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
+
+ if (FAILED(result) || lockPtr == NULL)
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ SafeRelease(mQuadVertexBuffer);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex shader, result: 0x%X.", result);
+ }
+
+ 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);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ SafeRelease(mQuadVertexBuffer);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex declaration, result: 0x%X.", result);
+ }
+
+ mGeometryLoaded = true;
+ return gl::Error(GL_NO_ERROR);
+}
+
+template <class D3DShaderType>
+gl::Error Blit9::setShader(ShaderId source, const char *profile,
+ gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader),
+ HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ D3DShaderType *shader = nullptr;
+
+ if (mCompiledShaders[source] != NULL)
+ {
+ shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
+ }
+ else
+ {
+ const BYTE* shaderCode = g_shaderCode[source];
+ size_t shaderSize = g_shaderSize[source];
+ ANGLE_TRY((mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize, &shader));
+ mCompiledShaders[source] = shader;
+ }
+
+ HRESULT hr = (device->*setShader)(shader);
+ if (FAILED(hr))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to set shader for blit operation, result: 0x%X.", hr);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Blit9::setVertexShader(ShaderId shader)
+{
+ return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader);
+}
+
+gl::Error Blit9::setPixelShader(ShaderId shader)
+{
+ return setShader<IDirect3DPixelShader9>(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::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
+{
+ ANGLE_TRY(initialize());
+
+ IDirect3DTexture9 *texture = NULL;
+ ANGLE_TRY(copySurfaceToTexture(source, getSurfaceRect(source), &texture));
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ saveState();
+
+ device->SetTexture(0, texture);
+ device->SetRenderTarget(0, dest);
+
+ setVertexShader(SHADER_VS_STANDARD);
+ setPixelShader(SHADER_PS_PASSTHROUGH);
+
+ setCommonBlitState();
+ device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+ device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
+ setViewport(getSurfaceRect(dest), gl::Offset(0, 0, 0));
+
+ render();
+
+ SafeRelease(texture);
+
+ restoreState();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level)
+{
+ ANGLE_TRY(initialize());
+
+ const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
+ ASSERT(colorbuffer);
+
+ RenderTarget9 *renderTarget9 = nullptr;
+ ANGLE_TRY(colorbuffer->getRenderTarget(&renderTarget9));
+ ASSERT(renderTarget9);
+
+ IDirect3DSurface9 *source = renderTarget9->getSurface();
+ ASSERT(source);
+
+ IDirect3DSurface9 *destSurface = NULL;
+ TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
+ gl::Error error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, true, &destSurface);
+ if (error.isError())
+ {
+ SafeRelease(source);
+ return error;
+ }
+ ASSERT(destSurface);
+
+ gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface);
+
+ SafeRelease(destSurface);
+ SafeRelease(source);
+
+ return result;
+}
+
+gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level)
+{
+ gl::Error error = initialize();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
+ ASSERT(colorbuffer);
+
+ RenderTarget9 *renderTarget9 = nullptr;
+ error = colorbuffer->getRenderTarget(&renderTarget9);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(renderTarget9);
+
+ IDirect3DSurface9 *source = renderTarget9->getSurface();
+ ASSERT(source);
+
+ IDirect3DSurface9 *destSurface = NULL;
+ TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
+ error = storage9->getSurfaceLevel(target, level, true, &destSurface);
+ if (error.isError())
+ {
+ SafeRelease(source);
+ return error;
+ }
+ ASSERT(destSurface);
+
+ gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface);
+
+ SafeRelease(destSurface);
+ SafeRelease(source);
+
+ return result;
+}
+
+gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest)
+{
+ ASSERT(source != NULL && dest != NULL);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ D3DSURFACE_DESC sourceDesc;
+ D3DSURFACE_DESC destDesc;
+ source->GetDesc(&sourceDesc);
+ dest->GetDesc(&destDesc);
+
+ if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET &&
+ d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect
+ {
+ 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);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit between textures, StretchRect result: 0x%X.", result);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ return formatConvert(source, sourceRect, destFormat, destOffset, dest);
+ }
+}
+
+gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest)
+{
+ gl::Error error = initialize();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IDirect3DTexture9 *texture = NULL;
+ error = copySurfaceToTexture(source, sourceRect, &texture);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ saveState();
+
+ device->SetTexture(0, texture);
+ device->SetRenderTarget(0, dest);
+
+ setViewport(sourceRect, destOffset);
+
+ setCommonBlitState();
+
+ error = setFormatConvertShaders(destFormat);
+ if (!error.isError())
+ {
+ render();
+ }
+
+ SafeRelease(texture);
+
+ restoreState();
+
+ return error;
+}
+
+gl::Error Blit9::setFormatConvertShaders(GLenum destFormat)
+{
+ gl::Error error = setVertexShader(SHADER_VS_STANDARD);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ switch (destFormat)
+ {
+ default: UNREACHABLE();
+ case GL_RGBA:
+ case GL_BGRA_EXT:
+ case GL_RGB:
+ case GL_RG_EXT:
+ case GL_RED_EXT:
+ case GL_ALPHA:
+ error = setPixelShader(SHADER_PS_COMPONENTMASK);
+ break;
+
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ error = setPixelShader(SHADER_PS_LUMINANCE);
+ break;
+ }
+
+ if (error.isError())
+ {
+ return error;
+ }
+
+ 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)
+ {
+ default: UNREACHABLE();
+ 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;
+ }
+
+ mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture)
+{
+ ASSERT(surface);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ D3DSURFACE_DESC sourceDesc;
+ surface->GetDesc(&sourceDesc);
+
+ const auto destWidth = sourceRect.right - sourceRect.left;
+ const auto destHeight = sourceRect.bottom - sourceRect.top;
+
+ // Copy the render target into a texture
+ IDirect3DTexture9 *texture;
+ HRESULT result = device->CreateTexture(destWidth, destHeight, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for blit, result: 0x%X.", result);
+ }
+
+ IDirect3DSurface9 *textureSurface;
+ result = texture->GetSurfaceLevel(0, &textureSurface);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ SafeRelease(texture);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to query surface of internal blit texture, result: 0x%X.", result);
+ }
+
+ mRenderer->endScene();
+
+ if (sourceRect.left < sourceDesc.Width && sourceRect.right > 0 &&
+ sourceRect.top < sourceDesc.Height && sourceRect.bottom > 0)
+ {
+ RECT validSourceRect = sourceRect;
+ RECT validDestRect = {0, 0, destWidth, destHeight};
+
+ if (sourceRect.left < 0) {
+ validSourceRect.left += 0 - sourceRect.left;
+ validDestRect.left += 0 - sourceRect.left;
+ }
+
+ if (sourceRect.right > sourceDesc.Width) {
+ validSourceRect.right -= sourceRect.right - sourceDesc.Width;
+ validDestRect.right -= sourceRect.right - sourceDesc.Width;
+ }
+
+ if (sourceRect.top < 0) {
+ validSourceRect.top += 0 - sourceRect.top;
+ validDestRect.top += 0 - sourceRect.top;
+ }
+
+ if (sourceRect.bottom > sourceDesc.Height) {
+ validSourceRect.bottom -= sourceRect.bottom - sourceDesc.Height;
+ validDestRect.bottom -= sourceRect.bottom - sourceDesc.Height;
+ }
+
+ ASSERT(validSourceRect.left < validSourceRect.right);
+ ASSERT(validSourceRect.top < validSourceRect.bottom);
+ ASSERT(validDestRect.left < validDestRect.right);
+ ASSERT(validDestRect.top < validDestRect.bottom);
+ result = device->StretchRect(surface, &validSourceRect, textureSurface,
+ &validDestRect, D3DTEXF_NONE);
+ }
+ SafeRelease(textureSurface);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ SafeRelease(texture);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy between internal blit textures, result: 0x%X.", result);
+ }
+
+ *outTexture = texture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Blit9::setViewport(const RECT &sourceRect, const gl::Offset &offset)
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ D3DVIEWPORT9 vp;
+ vp.X = offset.x;
+ vp.Y = offset.y;
+ vp.Width = sourceRect.right - sourceRect.left;
+ vp.Height = sourceRect.bottom - sourceRect.top;
+ vp.MinZ = 0.0f;
+ vp.MaxZ = 1.0f;
+ device->SetViewport(&vp);
+
+ float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
+ device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
+}
+
+void Blit9::setCommonBlitState()
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ device->SetDepthStencilSurface(NULL);
+
+ 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 = {0}; // 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();
+
+ HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
+ hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
+
+ mRenderer->startScene();
+ hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+}
+
+void Blit9::saveState()
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ HRESULT hr;
+
+ device->GetDepthStencilSurface(&mSavedDepthStencil);
+ device->GetRenderTarget(0, &mSavedRenderTarget);
+
+ if (mSavedStateBlock == NULL)
+ {
+ hr = device->BeginStateBlock();
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+
+ setCommonBlitState();
+
+ static const float dummyConst[8] = { 0 };
+
+ device->SetVertexShader(NULL);
+ device->SetVertexShaderConstantF(0, dummyConst, 2);
+ device->SetPixelShader(NULL);
+ device->SetPixelShaderConstantF(0, dummyConst, 2);
+
+ D3DVIEWPORT9 dummyVp;
+ dummyVp.X = 0;
+ dummyVp.Y = 0;
+ dummyVp.Width = 1;
+ dummyVp.Height = 1;
+ dummyVp.MinZ = 0;
+ dummyVp.MaxZ = 1;
+
+ device->SetViewport(&dummyVp);
+
+ device->SetTexture(0, NULL);
+
+ device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
+
+ device->SetVertexDeclaration(mQuadVertexDeclaration);
+
+ hr = device->EndStateBlock(&mSavedStateBlock);
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+ }
+
+ ASSERT(mSavedStateBlock != NULL);
+
+ if (mSavedStateBlock != NULL)
+ {
+ 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 != NULL);
+
+ if (mSavedStateBlock != NULL)
+ {
+ mSavedStateBlock->Apply();
+ }
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h
new file mode 100755
index 000000000..586abd258
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h
@@ -0,0 +1,97 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// Blit9.cpp: Surface copy utility class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+#include <GLES2/gl2.h>
+
+namespace gl
+{
+class Framebuffer;
+struct Offset;
+}
+
+namespace rx
+{
+class Renderer9;
+class TextureStorage;
+
+class Blit9 : angle::NonCopyable
+{
+ public:
+ explicit Blit9(Renderer9 *renderer);
+ ~Blit9();
+
+ gl::Error initialize();
+
+ // Copy from source surface to dest surface.
+ // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
+ gl::Error copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level);
+ gl::Error copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level);
+
+ // Copy from source surface 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.
+ gl::Error formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest);
+
+ // 2x2 box filter sample from source to dest.
+ // Requires that source is RGB(A) and dest has the same format as source.
+ gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
+
+ private:
+ Renderer9 *mRenderer;
+
+ bool mGeometryLoaded;
+ IDirect3DVertexBuffer9 *mQuadVertexBuffer;
+ IDirect3DVertexDeclaration9 *mQuadVertexDeclaration;
+
+ gl::Error setFormatConvertShaders(GLenum destFormat);
+
+ gl::Error copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest);
+ gl::Error copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture);
+ void setViewport(const RECT &sourceRect, const gl::Offset &offset);
+ void setCommonBlitState();
+ RECT getSurfaceRect(IDirect3DSurface9 *surface) const;
+
+ // This enum is used to index mCompiledShaders and mShaderSource.
+ enum ShaderId
+ {
+ SHADER_VS_STANDARD,
+ SHADER_VS_FLIPY,
+ SHADER_PS_PASSTHROUGH,
+ SHADER_PS_LUMINANCE,
+ SHADER_PS_COMPONENTMASK,
+ SHADER_COUNT
+ };
+
+ // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown.
+ IUnknown *mCompiledShaders[SHADER_COUNT];
+
+ template <class D3DShaderType>
+ gl::Error setShader(ShaderId source, const char *profile,
+ gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader),
+ HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*));
+
+ gl::Error setVertexShader(ShaderId shader);
+ gl::Error setPixelShader(ShaderId shader);
+ void render();
+
+ void saveState();
+ void restoreState();
+ IDirect3DStateBlock9 *mSavedStateBlock;
+ IDirect3DSurface9 *mSavedRenderTarget;
+ IDirect3DSurface9 *mSavedDepthStencil;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
new file mode 100755
index 000000000..b8abf3845
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
@@ -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.
+//
+
+// Buffer9.cpp Defines the Buffer9 class.
+
+#include "libANGLE/renderer/d3d/d3d9/Buffer9.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;
+}
+
+gl::Error Buffer9::setData(GLenum /*target*/, const void *data, size_t size, GLenum usage)
+{
+ if (size > mMemory.size())
+ {
+ if (!mMemory.resize(size))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer.");
+ }
+ }
+
+ mSize = size;
+ if (data && size > 0)
+ {
+ memcpy(mMemory.data(), data, size);
+ }
+
+ updateD3DBufferUsage(usage);
+
+ invalidateStaticData();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Buffer9::getData(const uint8_t **outData)
+{
+ *outData = mMemory.data();
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Buffer9::setSubData(GLenum /*target*/, const void *data, size_t size, size_t offset)
+{
+ if (offset + size > mMemory.size())
+ {
+ if (!mMemory.resize(offset + size))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer.");
+ }
+ }
+
+ mSize = std::max(mSize, offset + size);
+ if (data && size > 0)
+ {
+ memcpy(mMemory.data() + offset, data, size);
+ }
+
+ invalidateStaticData();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Buffer9::copySubData(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();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+// We do not support buffer mapping in D3D9
+gl::Error Buffer9::map(GLenum access, GLvoid **mapPtr)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Buffer9::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Buffer9::unmap(GLboolean *result)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Buffer9::markTransformFeedbackUsage()
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
new file mode 100755
index 000000000..dd7671827
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
@@ -0,0 +1,50 @@
+//
+// 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);
+ virtual ~Buffer9();
+
+ // BufferD3D implementation
+ virtual size_t getSize() const { return mSize; }
+ virtual bool supportsDirectBinding() const { return false; }
+ gl::Error getData(const uint8_t **outData) override;
+
+ // BufferImpl implementation
+ gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) override;
+ gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) override;
+ gl::Error copySubData(BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size) override;
+ gl::Error map(GLenum access, GLvoid **mapPtr) override;
+ gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override;
+ gl::Error unmap(GLboolean *result) override;
+ gl::Error markTransformFeedbackUsage() override;
+
+ private:
+ MemoryBuffer mMemory;
+ size_t mSize;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
new file mode 100755
index 000000000..c38bc1b11
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
@@ -0,0 +1,258 @@
+//
+// 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/string_utils.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/SamplerD3D.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::ContextState &state, Renderer9 *renderer)
+ : ContextImpl(state), mRenderer(renderer)
+{
+}
+
+Context9::~Context9()
+{
+}
+
+gl::Error Context9::initialize()
+{
+ return gl::NoError();
+}
+
+CompilerImpl *Context9::createCompiler()
+{
+ return new CompilerD3D(SH_HLSL_3_0_OUTPUT);
+}
+
+ShaderImpl *Context9::createShader(const gl::ShaderState &data)
+{
+ return new ShaderD3D(data, mRenderer->getWorkarounds());
+}
+
+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.getTarget())
+ {
+ case GL_TEXTURE_2D:
+ return new TextureD3D_2D(state, mRenderer);
+ case GL_TEXTURE_CUBE_MAP:
+ return new TextureD3D_Cube(state, mRenderer);
+ case GL_TEXTURE_EXTERNAL_OES:
+ return new TextureD3D_External(state, mRenderer);
+ default:
+ UNREACHABLE();
+ }
+ return nullptr;
+}
+
+RenderbufferImpl *Context9::createRenderbuffer()
+{
+ return new RenderbufferD3D(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(GLenum type)
+{
+ return new Query9(mRenderer, type);
+}
+
+FenceNVImpl *Context9::createFenceNV()
+{
+ return new FenceNV9(mRenderer);
+}
+
+FenceSyncImpl *Context9::createFenceSync()
+{
+ // 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()
+{
+ return new SamplerD3D();
+}
+
+std::vector<PathImpl *> Context9::createPaths(GLsizei)
+{
+ return std::vector<PathImpl *>();
+}
+
+gl::Error Context9::flush()
+{
+ return mRenderer->flush();
+}
+
+gl::Error Context9::finish()
+{
+ return mRenderer->finish();
+}
+
+gl::Error Context9::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ return mRenderer->genericDrawArrays(this, mode, first, count, 1);
+}
+
+gl::Error Context9::drawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ return mRenderer->genericDrawArrays(this, mode, first, count, instanceCount);
+}
+
+gl::Error Context9::drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange)
+{
+ return mRenderer->genericDrawElements(this, mode, count, type, indices, 1, indexRange);
+}
+
+gl::Error Context9::drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange)
+{
+ return mRenderer->genericDrawElements(this, mode, count, type, indices, instances, indexRange);
+}
+
+gl::Error Context9::drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange)
+{
+ return mRenderer->genericDrawElements(this, mode, count, type, indices, 1, indexRange);
+}
+
+GLenum Context9::getResetStatus()
+{
+ return mRenderer->getResetStatus();
+}
+
+std::string Context9::getVendorString() const
+{
+ return mRenderer->getVendorString();
+}
+
+std::string Context9::getRendererDescription() const
+{
+ return mRenderer->getRendererDescription();
+}
+
+void Context9::insertEventMarker(GLsizei length, const char *marker)
+{
+ auto optionalString = angle::WidenString(static_cast<size_t>(length), marker);
+ if (optionalString.valid())
+ {
+ mRenderer->getAnnotator()->setMarker(optionalString.value().data());
+ }
+}
+
+void Context9::pushGroupMarker(GLsizei length, const char *marker)
+{
+ auto optionalString = angle::WidenString(static_cast<size_t>(length), marker);
+ if (optionalString.valid())
+ {
+ mRenderer->getAnnotator()->beginEvent(optionalString.value().data());
+ }
+}
+
+void Context9::popGroupMarker()
+{
+ mRenderer->getAnnotator()->endEvent();
+}
+
+void Context9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
+{
+ mRenderer->getStateManager()->syncState(state, dirtyBits);
+}
+
+GLint Context9::getGPUDisjoint()
+{
+ return mRenderer->getGPUDisjoint();
+}
+
+GLint64 Context9::getTimestamp()
+{
+ return mRenderer->getTimestamp();
+}
+
+void Context9::onMakeCurrent(const gl::ContextState &data)
+{
+}
+
+const 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();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h
new file mode 100755
index 000000000..aeb18ff5e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h
@@ -0,0 +1,126 @@
+//
+// 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 "libANGLE/renderer/ContextImpl.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Context9 : public ContextImpl
+{
+ public:
+ Context9(const gl::ContextState &state, Renderer9 *renderer);
+ ~Context9() override;
+
+ gl::Error initialize() 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() 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(GLenum type) override;
+ FenceNVImpl *createFenceNV() override;
+ FenceSyncImpl *createFenceSync() override;
+
+ // Transform Feedback creation
+ TransformFeedbackImpl *createTransformFeedback(
+ const gl::TransformFeedbackState &state) override;
+
+ // Sampler object creation
+ SamplerImpl *createSampler() override;
+
+ // Path object creation
+ std::vector<PathImpl *> createPaths(GLsizei) override;
+
+ // Flush and finish.
+ gl::Error flush() override;
+ gl::Error finish() override;
+
+ // Drawing methods.
+ gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override;
+ gl::Error drawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) override;
+
+ gl::Error drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange) override;
+ gl::Error drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange) override;
+ gl::Error drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange) override;
+
+ // Device loss
+ GLenum getResetStatus() override;
+
+ // Vendor and description strings.
+ std::string getVendorString() const override;
+ std::string getRendererDescription() const override;
+
+ // Debug markers.
+ void insertEventMarker(GLsizei length, const char *marker) override;
+ void pushGroupMarker(GLsizei length, const char *marker) override;
+ void popGroupMarker() override;
+
+ // State sync with dirty bits.
+ void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) override;
+
+ // Disjoint timer queries
+ GLint getGPUDisjoint() override;
+ GLint64 getTimestamp() override;
+
+ // Context switching
+ void onMakeCurrent(const gl::ContextState &data) override;
+
+ // Caps queries
+ const gl::Caps &getNativeCaps() const override;
+ const gl::TextureCapsMap &getNativeTextureCaps() const override;
+ const gl::Extensions &getNativeExtensions() const override;
+ const gl::Limitations &getNativeLimitations() const override;
+
+ private:
+ Renderer9 *mRenderer;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp
new file mode 100755
index 000000000..6ec35e16a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp
@@ -0,0 +1,36 @@
+//
+// 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(const wchar_t *eventName)
+{
+ D3DPERF_BeginEvent(0, eventName);
+}
+
+void DebugAnnotator9::endEvent()
+{
+ D3DPERF_EndEvent();
+}
+
+void DebugAnnotator9::setMarker(const wchar_t *markerName)
+{
+ D3DPERF_SetMarker(0, markerName);
+}
+
+bool DebugAnnotator9::getStatus()
+{
+ return !!D3DPERF_GetStatus();
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h
new file mode 100755
index 000000000..54e3bb949
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h
@@ -0,0 +1,29 @@
+//
+// 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 "common/debug.h"
+
+namespace rx
+{
+
+class DebugAnnotator9 : public gl::DebugAnnotator
+{
+ public:
+ DebugAnnotator9() {}
+ void beginEvent(const wchar_t *eventName) override;
+ void endEvent() override;
+ void setMarker(const wchar_t *markerName) override;
+ bool getStatus() override;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp
new file mode 100755
index 000000000..330068127
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 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/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+FenceNV9::FenceNV9(Renderer9 *renderer)
+ : FenceNVImpl(),
+ mRenderer(renderer),
+ mQuery(NULL)
+{
+}
+
+FenceNV9::~FenceNV9()
+{
+ SafeRelease(mQuery);
+}
+
+gl::Error FenceNV9::set(GLenum condition)
+{
+ if (!mQuery)
+ {
+ gl::Error error = mRenderer->allocateEventQuery(&mQuery);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ HRESULT result = mQuery->Issue(D3DISSUE_END);
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ SafeRelease(mQuery);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to end event query, result: 0x%X.", result);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FenceNV9::test(GLboolean *outFinished)
+{
+ return testHelper(true, outFinished);
+}
+
+gl::Error FenceNV9::finish()
+{
+ GLboolean finished = GL_FALSE;
+ while (finished != GL_TRUE)
+ {
+ gl::Error error = testHelper(true, &finished);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ Sleep(0);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FenceNV9::testHelper(bool flushCommandBuffer, GLboolean *outFinished)
+{
+ ASSERT(mQuery);
+
+ DWORD getDataFlags = (flushCommandBuffer ? D3DGETDATA_FLUSH : 0);
+ HRESULT result = mQuery->GetData(NULL, 0, getDataFlags);
+
+ if (d3d9::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query.");
+ }
+ else if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result);
+ }
+
+ ASSERT(result == S_OK || result == S_FALSE);
+ *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
+ return gl::Error(GL_NO_ERROR);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h
new file mode 100755
index 000000000..200ac68d2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 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/FenceSyncImpl.h"
+
+namespace rx
+{
+class Renderer9;
+
+class FenceNV9 : public FenceNVImpl
+{
+ public:
+ explicit FenceNV9(Renderer9 *renderer);
+ ~FenceNV9() override;
+
+ gl::Error set(GLenum condition) override;
+ gl::Error test(GLboolean *outFinished) override;
+ gl::Error finish() override;
+
+ private:
+ gl::Error testHelper(bool flushCommandBuffer, GLboolean *outFinished);
+
+ Renderer9 *mRenderer;
+ IDirect3DQuery9 *mQuery;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
new file mode 100755
index 000000000..18e1b3da4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
@@ -0,0 +1,410 @@
+//
+// 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/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.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
+{
+
+Framebuffer9::Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer)
+ : FramebufferD3D(data, renderer), mRenderer(renderer)
+{
+ ASSERT(mRenderer != nullptr);
+}
+
+Framebuffer9::~Framebuffer9()
+{
+}
+
+gl::Error Framebuffer9::discard(size_t, const GLenum *)
+{
+ // Extension not implemented in D3D9 renderer
+ UNREACHABLE();
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Framebuffer9::invalidate(size_t, const GLenum *)
+{
+ // Shouldn't ever reach here in D3D9
+ UNREACHABLE();
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Framebuffer9::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
+{
+ // Shouldn't ever reach here in D3D9
+ UNREACHABLE();
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Framebuffer9::clearImpl(ContextImpl *context, const ClearParameters &clearParams)
+{
+ const gl::FramebufferAttachment *colorAttachment = mState.getColorAttachment(0);
+ const gl::FramebufferAttachment *depthStencilAttachment = mState.getDepthOrStencilAttachment();
+
+ gl::Error error =
+ mRenderer->applyRenderTarget(context, colorAttachment, depthStencilAttachment);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ const gl::State &glState = context->getGLState();
+ float nearZ = glState.getNearPlane();
+ float farZ = glState.getFarPlane();
+ mRenderer->setViewport(glState.getViewport(), nearZ, farZ, GL_TRIANGLES,
+ glState.getRasterizerState().frontFace, true);
+
+ mRenderer->setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
+
+ return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment);
+}
+
+gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixels) const
+{
+ ASSERT(pack.pixelBuffer.get() == nullptr);
+
+ const gl::FramebufferAttachment *colorbuffer = mState.getColorAttachment(0);
+ ASSERT(colorbuffer);
+
+ RenderTarget9 *renderTarget = nullptr;
+ gl::Error error = colorbuffer->getRenderTarget(&renderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(renderTarget);
+
+ IDirect3DSurface9 *surface = renderTarget->getSurface();
+ ASSERT(surface);
+
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+
+ if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
+ {
+ UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
+ SafeRelease(surface);
+ return gl::Error(GL_OUT_OF_MEMORY, "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);
+ return gl::Error(GL_OUT_OF_MEMORY, "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();
+ }
+
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data.");
+ }
+
+ if (directToPixels)
+ {
+ SafeRelease(systemSurface);
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ 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);
+
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target.");
+ }
+
+ uint8_t *source = reinterpret_cast<uint8_t *>(lock.pBits);
+ int inputPitch = lock.Pitch;
+
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+ gl::FormatType formatType(format, type);
+
+ // TODO(jmadill): Maybe we can avoid a copy of pack parameters here?
+ 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.format = format;
+ packParams.type = type;
+ packParams.outputPitch = static_cast<GLuint>(outputPitch);
+ packParams.pack = pack;
+
+ PackPixels(packParams, d3dFormatInfo.info(), inputPitch, source, pixels);
+
+ systemSurface->UnlockRect();
+ SafeRelease(systemSurface);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Framebuffer9::blitImpl(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();
+
+ if (blitRenderTarget)
+ {
+ const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getColorbuffer(0);
+ ASSERT(readBuffer);
+
+ RenderTarget9 *readRenderTarget = nullptr;
+ gl::Error error = readBuffer->getRenderTarget(&readRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(readRenderTarget);
+
+ const gl::FramebufferAttachment *drawBuffer = mState.getColorAttachment(0);
+ ASSERT(drawBuffer);
+
+ RenderTarget9 *drawRenderTarget = nullptr;
+ error = drawBuffer->getRenderTarget(&drawRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+ 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);
+
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
+ }
+ }
+
+ if (blitDepth || blitStencil)
+ {
+ const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer();
+ ASSERT(readBuffer);
+
+ RenderTarget9 *readDepthStencil = nullptr;
+ gl::Error error = readBuffer->getRenderTarget(&readDepthStencil);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(readDepthStencil);
+
+ const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
+ ASSERT(drawBuffer);
+
+ RenderTarget9 *drawDepthStencil = nullptr;
+ error = drawBuffer->getRenderTarget(&drawDepthStencil);
+ if (error.isError())
+ {
+ return error;
+ }
+ 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);
+
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+GLenum Framebuffer9::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
+{
+ RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTarget);
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(renderTarget9->getD3DFormat());
+ return d3dFormatInfo.info().glInternalFormat;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
new file mode 100755
index 000000000..8401350b3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
@@ -0,0 +1,54 @@
+//
+// 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/d3d/FramebufferD3D.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Framebuffer9 : public FramebufferD3D
+{
+ public:
+ Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer);
+ virtual ~Framebuffer9();
+
+ gl::Error discard(size_t count, const GLenum *attachments) override;
+ gl::Error invalidate(size_t count, const GLenum *attachments) override;
+ gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
+
+ private:
+ gl::Error clearImpl(ContextImpl *context, const ClearParameters &clearParams) override;
+
+ gl::Error readPixelsImpl(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixels) const override;
+
+ gl::Error blitImpl(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;
+
+ GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
+
+ Renderer9 *const mRenderer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
new file mode 100755
index 000000000..ad2c41584
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
@@ -0,0 +1,822 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Renderbuffer.h"
+#include "common/utilities.h"
+
+namespace rx
+{
+
+Image9::Image9(Renderer9 *renderer)
+{
+ mSurface = NULL;
+ mRenderer = NULL;
+
+ mD3DPool = D3DPOOL_SYSTEMMEM;
+ mD3DFormat = D3DFMT_UNKNOWN;
+
+ mRenderer = renderer;
+}
+
+Image9::~Image9()
+{
+ SafeRelease(mSurface);
+}
+
+gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface)
+{
+ D3DSURFACE_DESC destDesc;
+ HRESULT result = destSurface->GetDesc(&destDesc);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the source surface description for mipmap generation, result: 0x%X.", result);
+ }
+
+ D3DSURFACE_DESC sourceDesc;
+ result = sourceSurface->GetDesc(&sourceDesc);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the destination surface description for mipmap generation, result: 0x%X.", result);
+ }
+
+ 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 != NULL);
+
+ D3DLOCKED_RECT sourceLocked = {0};
+ result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface for mipmap generation, result: 0x%X.", result);
+ }
+
+ D3DLOCKED_RECT destLocked = {0};
+ result = destSurface->LockRect(&destLocked, NULL, 0);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ sourceSurface->UnlockRect();
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the destination surface for mipmap generation, result: 0x%X.", result);
+ }
+
+ const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(sourceLocked.pBits);
+ uint8_t *destData = reinterpret_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 gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Image9::generateMipmap(Image9 *dest, Image9 *source)
+{
+ IDirect3DSurface9 *sourceSurface = NULL;
+ gl::Error error = source->getSurface(&sourceSurface);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IDirect3DSurface9 *destSurface = NULL;
+ error = dest->getSurface(&destSurface);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = generateMip(destSurface, sourceSurface);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ dest->markDirty();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source)
+{
+ D3DLOCKED_RECT sourceLock = {0};
+ D3DLOCKED_RECT destLock = {0};
+
+ HRESULT result;
+
+ result = source->LockRect(&sourceLock, NULL, 0);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result);
+ }
+
+ result = dest->LockRect(&destLock, NULL, 0);
+ if (FAILED(result))
+ {
+ source->UnlockRect();
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result);
+ }
+
+ 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 gl::Error(GL_NO_ERROR);
+}
+
+bool Image9::redefine(GLenum target, 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(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
+
+ if (mWidth != size.width ||
+ mHeight != size.height ||
+ mDepth != size.depth ||
+ mInternalFormat != internalformat ||
+ forceRelease)
+ {
+ mWidth = size.width;
+ mHeight = size.height;
+ mDepth = size.depth;
+ 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 != NULL);
+
+ return true;
+ }
+
+ return false;
+}
+
+gl::Error Image9::createSurface()
+{
+ if (mSurface)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ IDirect3DTexture9 *newTexture = NULL;
+ IDirect3DSurface9 *newSurface = NULL;
+ 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, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create image surface, result: 0x%X.", result);
+ }
+
+ newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
+ SafeRelease(newTexture);
+
+ const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
+ if (d3dFormatInfo.dataInitializerFunction != NULL)
+ {
+ 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));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result);
+ }
+
+ d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast<uint8_t*>(lockedRect.pBits),
+ lockedRect.Pitch, 0);
+
+ result = newSurface->UnlockRect();
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock image surface, result: 0x%X.", result);
+ }
+ }
+ }
+
+ mSurface = newSurface;
+ mDirty = false;
+ mD3DPool = poolToUse;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT &rect)
+{
+ gl::Error error = createSurface();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (mSurface)
+ {
+ HRESULT result = mSurface->LockRect(lockedRect, &rect, 0);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result);
+ }
+
+ mDirty = true;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+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 != NULL) && mDirty;
+}
+
+gl::Error Image9::getSurface(IDirect3DSurface9 **outSurface)
+{
+ gl::Error error = createSurface();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *outSurface = mSurface;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level)
+{
+ IDirect3DSurface9 *surface = NULL;
+ TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
+ gl::Error error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, false, &surface);
+ if (error.isError())
+ {
+ return error;
+ }
+ return setManagedSurface(surface);
+}
+
+gl::Error Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level)
+{
+ IDirect3DSurface9 *surface = NULL;
+ TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
+ gl::Error error =
+ storage9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false, &surface);
+ if (error.isError())
+ {
+ return error;
+ }
+ return setManagedSurface(surface);
+}
+
+gl::Error Image9::setManagedSurface(IDirect3DSurface9 *surface)
+{
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+ ASSERT(desc.Pool == D3DPOOL_MANAGED);
+
+ if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight)
+ {
+ if (mSurface)
+ {
+ gl::Error error = copyLockableSurfaces(surface, mSurface);
+ SafeRelease(mSurface);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ mSurface = surface;
+ mD3DPool = desc.Pool;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
+{
+ gl::Error error = createSurface();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
+
+ IDirect3DSurface9 *destSurface = NULL;
+
+ if (index.type == GL_TEXTURE_2D)
+ {
+ error = storage9->getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, true, &destSurface);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ else
+ {
+ ASSERT(gl::IsCubeMapTextureTarget(index.type));
+ error = storage9->getSurfaceLevel(index.type, index.mipIndex, true, &destSurface);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ error = copyToSurface(destSurface, region);
+ SafeRelease(destSurface);
+ return error;
+}
+
+gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &area)
+{
+ ASSERT(area.width > 0 && area.height > 0 && area.depth == 1);
+ ASSERT(destSurface);
+
+ IDirect3DSurface9 *sourceSurface = NULL;
+ gl::Error error = getSurface(&sourceSurface);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ 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, NULL);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal CreateOffscreenPlainSurface call failed, result: 0x%X.", result);
+ }
+
+ copyLockableSurfaces(surf, sourceSurface);
+ result = device->UpdateSurface(surf, &rect, destSurface, &point);
+ SafeRelease(surf);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result);
+ }
+ }
+ else
+ {
+ // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
+ HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result);
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
+// into the target pixel rectangle.
+gl::Error Image9::loadData(const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum inputType,
+ const void *input,
+ bool applySkipImages)
+{
+ // 3D textures are not supported by the D3D9 backend.
+ ASSERT(area.z == 0 && area.depth == 1);
+ ASSERT(getSizedInputFormat(inputType) == mInternalFormat);
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+ GLuint inputRowPitch = 0;
+ ANGLE_TRY_RESULT(
+ formatInfo.computeRowPitch(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 != NULL);
+
+ RECT lockRect =
+ {
+ area.x, area.y,
+ area.x + area.width, area.y + area.height
+ };
+
+ D3DLOCKED_RECT locked;
+ gl::Error error = lock(&locked, lockRect);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ d3dFormatInfo.loadFunction(area.width, area.height, area.depth,
+ reinterpret_cast<const uint8_t *>(input), inputRowPitch, 0,
+ reinterpret_cast<uint8_t *>(locked.pBits), locked.Pitch, 0);
+
+ unlock();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input)
+{
+ // 3D textures are not supported by the D3D9 backend.
+ ASSERT(area.z == 0 && area.depth == 1);
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+ GLsizei inputRowPitch = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeRowPitch(area.width, 1, 0), inputRowPitch);
+ GLsizei inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, 0, inputDepthPitch),
+ 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 != NULL);
+
+ RECT lockRect =
+ {
+ area.x, area.y,
+ area.x + area.width, area.y + area.height
+ };
+
+ D3DLOCKED_RECT locked;
+ gl::Error error = lock(&locked, lockRect);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ d3d9FormatInfo.loadFunction(area.width, area.height, area.depth,
+ reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
+ reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0);
+
+ unlock();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
+gl::Error Image9::copyFromRTInternal(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);
+
+ IDirect3DSurface9 *surface = renderTarget->getSurface();
+ ASSERT(surface);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ IDirect3DSurface9 *renderTargetData = NULL;
+ D3DSURFACE_DESC description;
+ surface->GetDesc(&description);
+
+ HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
+
+ if (FAILED(result))
+ {
+ SafeRelease(surface);
+ return gl::Error(GL_OUT_OF_MEMORY, "Could not create matching destination surface, result: 0x%X.", result);
+ }
+
+ result = device->GetRenderTargetData(surface, renderTargetData);
+
+ if (FAILED(result))
+ {
+ SafeRelease(renderTargetData);
+ SafeRelease(surface);
+ return gl::Error(GL_OUT_OF_MEMORY, "GetRenderTargetData unexpectedly failed, result: 0x%X.", result);
+ }
+
+ 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 = {0};
+ result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
+
+ if (FAILED(result))
+ {
+ SafeRelease(renderTargetData);
+ SafeRelease(surface);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface (rectangle might be invalid), result: 0x%X.", result);
+ }
+
+ D3DLOCKED_RECT destLock = {0};
+ gl::Error error = lock(&destLock, destRect);
+ if (error.isError())
+ {
+ renderTargetData->UnlockRect();
+ SafeRelease(renderTargetData);
+ SafeRelease(surface);
+ return error;
+ }
+
+ 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;
+ default:
+ UNREACHABLE();
+ }
+
+ unlock();
+ renderTargetData->UnlockRect();
+
+ SafeRelease(renderTargetData);
+ SafeRelease(surface);
+
+ mDirty = true;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Image9::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source)
+{
+ RenderTargetD3D *renderTarget = nullptr;
+ gl::Error error = source->getRenderTarget(imageIndex, &renderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ gl::Rectangle sourceArea(0, 0, mWidth, mHeight);
+ return copyFromRTInternal(gl::Offset(), sourceArea, renderTarget);
+}
+
+gl::Error Image9::copyFromFramebuffer(const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ const gl::FramebufferAttachment *srcAttachment = source->getReadColorbuffer();
+ ASSERT(srcAttachment);
+
+ RenderTargetD3D *renderTarget = NULL;
+ gl::Error error = srcAttachment->getRenderTarget(&renderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(renderTarget);
+ return copyFromRTInternal(destOffset, sourceArea, renderTarget);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h
new file mode 100755
index 000000000..068a67fc9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h
@@ -0,0 +1,80 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 "libANGLE/renderer/d3d/ImageD3D.h"
+#include "common/debug.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Renderer9;
+
+class Image9 : public ImageD3D
+{
+ public:
+ Image9(Renderer9 *renderer);
+ ~Image9();
+
+ static gl::Error generateMipmap(Image9 *dest, Image9 *source);
+ static gl::Error generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface);
+ static gl::Error copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source);
+
+ bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override;
+
+ D3DFORMAT getD3DFormat() const;
+
+ virtual bool isDirty() const;
+
+ virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level);
+ virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level);
+ virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+
+ gl::Error loadData(const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages) override;
+ gl::Error loadCompressedData(const gl::Box &area, const void *input) override;
+
+ gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override;
+ gl::Error copyFromFramebuffer(const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ private:
+ gl::Error getSurface(IDirect3DSurface9 **outSurface);
+
+ gl::Error createSurface();
+ gl::Error setManagedSurface(IDirect3DSurface9 *surface);
+ gl::Error copyToSurface(IDirect3DSurface9 *dest, const gl::Box &area);
+
+ gl::Error lock(D3DLOCKED_RECT *lockedRect, const RECT &rect);
+ void unlock();
+
+ gl::Error copyFromRTInternal(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;
+};
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp
new file mode 100755
index 000000000..40152df25
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp
@@ -0,0 +1,167 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation.
+
+#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer)
+{
+ mIndexBuffer = NULL;
+ mBufferSize = 0;
+ mIndexType = 0;
+ mDynamic = false;
+}
+
+IndexBuffer9::~IndexBuffer9()
+{
+ SafeRelease(mIndexBuffer);
+}
+
+gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
+{
+ SafeRelease(mIndexBuffer);
+
+ updateSerial();
+
+ if (bufferSize > 0)
+ {
+ D3DFORMAT format = D3DFMT_UNKNOWN;
+ if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE)
+ {
+ format = D3DFMT_INDEX16;
+ }
+ else if (indexType == GL_UNSIGNED_INT)
+ {
+ ASSERT(mRenderer->getNativeExtensions().elementIndexUint);
+ format = D3DFMT_INDEX32;
+ }
+ else UNREACHABLE();
+
+ DWORD usageFlags = D3DUSAGE_WRITEONLY;
+ if (dynamic)
+ {
+ usageFlags |= D3DUSAGE_DYNAMIC;
+ }
+
+ HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize);
+ }
+ }
+
+ mBufferSize = bufferSize;
+ mIndexType = indexType;
+ mDynamic = dynamic;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
+{
+ if (!mIndexBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+ }
+
+ DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0;
+
+ void *mapPtr = NULL;
+ HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result);
+ }
+
+ *outMappedMemory = mapPtr;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error IndexBuffer9::unmapBuffer()
+{
+ if (!mIndexBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+ }
+
+ HRESULT result = mIndexBuffer->Unlock();
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+GLenum IndexBuffer9::getIndexType() const
+{
+ return mIndexType;
+}
+
+unsigned int IndexBuffer9::getBufferSize() const
+{
+ return mBufferSize;
+}
+
+gl::Error IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType)
+{
+ if (bufferSize > mBufferSize || indexType != mIndexType)
+ {
+ return initialize(bufferSize, indexType, mDynamic);
+ }
+ else
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+gl::Error IndexBuffer9::discard()
+{
+ if (!mIndexBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+ }
+
+ void *dummy;
+ HRESULT result;
+
+ result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result);
+ }
+
+ result = mIndexBuffer->Unlock();
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+D3DFORMAT IndexBuffer9::getIndexFormat() const
+{
+ switch (mIndexType)
+ {
+ case GL_UNSIGNED_BYTE: return D3DFMT_INDEX16;
+ case GL_UNSIGNED_SHORT: return D3DFMT_INDEX16;
+ case GL_UNSIGNED_INT: return D3DFMT_INDEX32;
+ default: UNREACHABLE(); return D3DFMT_UNKNOWN;
+ }
+}
+
+IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const
+{
+ return mIndexBuffer;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h
new file mode 100755
index 000000000..ba03ba703
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h
@@ -0,0 +1,49 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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);
+ virtual ~IndexBuffer9();
+
+ virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
+
+ virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory);
+ virtual gl::Error unmapBuffer();
+
+ virtual GLenum getIndexType() const;
+ virtual unsigned int getBufferSize() const;
+ virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType);
+
+ virtual gl::Error discard();
+
+ D3DFORMAT getIndexFormat() const;
+ IDirect3DIndexBuffer9 *getBuffer() const;
+
+ private:
+ Renderer9 *const mRenderer;
+
+ IDirect3DIndexBuffer9 *mIndexBuffer;
+ unsigned int mBufferSize;
+ GLenum mIndexType;
+ bool mDynamic;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp
new file mode 100755
index 000000000..388b8aa16
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 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/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h
new file mode 100755
index 000000000..a56b08dc8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 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/src/libANGLE/renderer/d3d/d3d9/Query9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp
new file mode 100755
index 000000000..9e5a90a2f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp
@@ -0,0 +1,189 @@
+//
+// Copyright (c) 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/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+#include <GLES2/gl2ext.h>
+
+namespace rx
+{
+Query9::Query9(Renderer9 *renderer, GLenum type)
+ : QueryImpl(type),
+ mResult(GL_FALSE),
+ mQueryFinished(false),
+ mRenderer(renderer),
+ mQuery(NULL)
+{
+}
+
+Query9::~Query9()
+{
+ SafeRelease(mQuery);
+}
+
+gl::Error Query9::begin()
+{
+ D3DQUERYTYPE d3dQueryType = gl_d3d9::ConvertQueryType(getType());
+ if (mQuery == nullptr)
+ {
+ HRESULT result = mRenderer->getDevice()->CreateQuery(d3dQueryType, &mQuery);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result);
+ }
+ }
+
+ if (d3dQueryType != D3DQUERYTYPE_EVENT)
+ {
+ HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to begin internal query, result: 0x%X.",
+ result);
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Query9::end()
+{
+ ASSERT(mQuery);
+
+ HRESULT result = mQuery->Issue(D3DISSUE_END);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to end internal query, result: 0x%X.", result);
+ }
+
+ mQueryFinished = false;
+ mResult = GL_FALSE;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Query9::queryCounter()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION, "Unimplemented");
+}
+
+template <typename T>
+gl::Error Query9::getResultBase(T *params)
+{
+ while (!mQueryFinished)
+ {
+ gl::Error error = testQuery();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!mQueryFinished)
+ {
+ Sleep(0);
+ }
+ }
+
+ ASSERT(mQueryFinished);
+ *params = static_cast<T>(mResult);
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Query9::getResult(GLint *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error Query9::getResult(GLuint *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error Query9::getResult(GLint64 *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error Query9::getResult(GLuint64 *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error Query9::isResultAvailable(bool *available)
+{
+ gl::Error error = testQuery();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *available = mQueryFinished;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Query9::testQuery()
+{
+ if (!mQueryFinished)
+ {
+ ASSERT(mQuery);
+
+ HRESULT result = S_OK;
+ switch (getType())
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ {
+ 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_COMMANDS_COMPLETED_CHROMIUM:
+ {
+ 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 (d3d9::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
+ }
+ else if (mRenderer->testDeviceLost())
+ {
+ mRenderer->notifyDeviceLost();
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h
new file mode 100755
index 000000000..9d17711a0
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 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 Renderer9;
+
+class Query9 : public QueryImpl
+{
+ public:
+ Query9(Renderer9 *renderer, GLenum type);
+ virtual ~Query9();
+
+ virtual gl::Error begin();
+ virtual gl::Error end();
+ virtual gl::Error queryCounter();
+ virtual gl::Error getResult(GLint *params);
+ virtual gl::Error getResult(GLuint *params);
+ virtual gl::Error getResult(GLint64 *params);
+ virtual gl::Error getResult(GLuint64 *params);
+ virtual gl::Error isResultAvailable(bool *available);
+
+ private:
+ gl::Error testQuery();
+
+ template <typename T>
+ gl::Error getResultBase(T *params);
+
+ GLuint64 mResult;
+ bool mQueryFinished;
+
+ Renderer9 *mRenderer;
+ IDirect3DQuery9 *mQuery;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp
new file mode 100755
index 000000000..3e54c27f4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp
@@ -0,0 +1,163 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.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;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h
new file mode 100755
index 000000000..f19c54de7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 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() { }
+ virtual ~RenderTarget9() { }
+ // 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);
+ virtual ~TextureRenderTarget9();
+
+ 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);
+ virtual ~SurfaceRenderTarget9();
+
+ 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;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
new file mode 100755
index 000000000..d578d4075
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -0,0 +1,3032 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
+
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+#include <sstream>
+#include <EGL/eglext.h>
+
+#include "common/utilities.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/features.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Renderbuffer.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/formatutils9.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/renderer9_utils.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/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.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/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "third_party/trace_event/trace_event.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
+{
+
+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
+};
+
+Renderer9::Renderer9(egl::Display *display) : RendererD3D(display), mStateManager(this)
+{
+ mD3d9Module = NULL;
+
+ mD3d9 = NULL;
+ mD3d9Ex = NULL;
+ mDevice = NULL;
+ mDeviceEx = NULL;
+ mDeviceWindow = NULL;
+ mBlit = NULL;
+
+ 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_REFERENCE_ANGLE:
+ mDeviceType = D3DDEVTYPE_REF;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+ mDeviceType = D3DDEVTYPE_NULLREF;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ mMaskedClearSavedState = NULL;
+
+ mVertexDataManager = NULL;
+ mIndexDataManager = NULL;
+ mLineLoopIB = NULL;
+ mCountingIB = NULL;
+
+ mMaxNullColorbufferLRU = 0;
+ for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+ {
+ mNullColorbufferCache[i].lruCount = 0;
+ mNullColorbufferCache[i].width = 0;
+ mNullColorbufferCache[i].height = 0;
+ mNullColorbufferCache[i].buffer = NULL;
+ }
+
+ mAppliedVertexShader = NULL;
+ mAppliedPixelShader = NULL;
+ mAppliedProgramSerial = 0;
+
+ gl::InitializeDebugAnnotations(&mAnnotator);
+
+ mEGLDevice = nullptr;
+}
+
+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()
+{
+ RendererD3D::cleanup();
+
+ gl::UninitializeDebugAnnotations();
+
+ mTranslatedAttribCache.clear();
+
+ releaseDeviceResources();
+
+ SafeDelete(mEGLDevice);
+ SafeRelease(mDevice);
+ SafeRelease(mDeviceEx);
+ SafeRelease(mD3d9);
+ SafeRelease(mD3d9Ex);
+
+ mCompiler.release();
+
+ if (mDeviceWindow)
+ {
+ DestroyWindow(mDeviceWindow);
+ mDeviceWindow = NULL;
+ }
+
+ mD3d9Module = NULL;
+}
+
+egl::Error Renderer9::initialize()
+{
+ TRACE_EVENT0("gpu.angle", "GetModuleHandle_d3d9");
+ mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
+
+ if (mD3d9Module == NULL)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, 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)))
+ {
+ TRACE_EVENT0("gpu.angle", "D3d9Ex_QueryInterface");
+ ASSERT(mD3d9Ex);
+ mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void**>(&mD3d9));
+ ASSERT(mD3d9);
+ }
+ else
+ {
+ TRACE_EVENT0("gpu.angle", "Direct3DCreate9");
+ mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+ }
+
+ if (!mD3d9)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, 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.
+ {
+ 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::Error(EGL_NOT_INITIALIZED,
+ D3D9_INIT_OTHER_ERROR,
+ "Failed to get device caps: Error code 0x%x\n", 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::Error(EGL_NOT_INITIALIZED,
+ D3D9_INIT_UNSUPPORTED_VERSION,
+ "Renderer does not support PS %u.%u.aborting!", minShaderModel, 0);
+ }
+
+ // 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::Error(EGL_NOT_INITIALIZED,
+ D3D9_INIT_UNSUPPORTED_STRETCHRECT,
+ "Renderer does not support StretctRect from textures.");
+ }
+
+ {
+ TRACE_EVENT0("gpu.angle", "GetAdapterIdentifier");
+ mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
+ }
+
+ static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
+ static const TCHAR className[] = TEXT("STATIC");
+
+ {
+ TRACE_EVENT0("gpu.angle", "CreateWindowEx");
+ mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
+ }
+
+ D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+ DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED;
+
+ {
+ TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice");
+ result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
+ }
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
+ {
+ return egl::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY,
+ "CreateDevice failed: device lost of out of memory");
+ }
+
+ if (FAILED(result))
+ {
+ 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::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY,
+ "CreateDevice2 failed: device lost, not available, or of out of memory");
+ }
+ }
+
+ if (mD3d9Ex)
+ {
+ TRACE_EVENT0("gpu.angle", "mDevice_QueryInterface");
+ result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void**)&mDeviceEx);
+ ASSERT(SUCCEEDED(result));
+ }
+
+ {
+ 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));
+
+ initializeDevice();
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+// 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.
+void 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.maxVertexTextureImageUnits);
+ mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
+
+ mCurVertexTextures.resize(rendererCaps.maxVertexTextureImageUnits);
+ mCurPixelTextures.resize(rendererCaps.maxTextureImageUnits);
+
+ markAllStateDirty();
+
+ mSceneStarted = false;
+
+ ASSERT(!mBlit);
+ mBlit = new Blit9(this);
+ mBlit->initialize();
+
+ ASSERT(!mVertexDataManager && !mIndexDataManager);
+ mVertexDataManager = new VertexDataManager(this);
+ mIndexDataManager = new IndexDataManager(this, getRendererClass());
+
+ mTranslatedAttribCache.resize(getNativeCaps().maxVertexAttributes);
+
+ mStateManager.initialize();
+}
+
+D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
+{
+ D3DPRESENT_PARAMETERS presentParameters = {0};
+
+ // 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.renderable)
+ {
+ for (size_t depthStencilIndex = 0; depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++)
+ {
+ GLenum depthStencilBufferInternalFormat = depthStencilBufferFormats[depthStencilIndex];
+ const gl::TextureCaps &depthStencilBufferFormatCaps = rendererTextureCaps.get(depthStencilBufferInternalFormat);
+ if (depthStencilBufferFormatCaps.renderable || depthStencilBufferInternalFormat == GL_NONE)
+ {
+ const gl::InternalFormat &colorBufferFormatInfo = gl::GetInternalFormatInfo(colorBufferInternalFormat);
+ const gl::InternalFormat &depthStencilBufferFormatInfo = gl::GetInternalFormatInfo(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;
+
+ 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->deviceQuery = true;
+
+ outExtensions->image = true;
+ outExtensions->imageBase = true;
+ outExtensions->glTexture2DImage = true;
+ outExtensions->glRenderbufferImage = true;
+
+ outExtensions->flexibleSurfaceCompatibility = 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;
+ }
+}
+
+gl::Error Renderer9::flush()
+{
+ IDirect3DQuery9* query = NULL;
+ gl::Error error = allocateEventQuery(&query);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ HRESULT result = query->Issue(D3DISSUE_END);
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result);
+ }
+
+ // Grab the query data once
+ result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
+ freeEventQuery(query);
+ if (FAILED(result))
+ {
+ if (d3d9::isDeviceLostError(result))
+ {
+ notifyDeviceLost();
+ }
+
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::finish()
+{
+ IDirect3DQuery9* query = NULL;
+ gl::Error error = allocateEventQuery(&query);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ HRESULT result = query->Issue(D3DISSUE_END);
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result);
+ }
+
+ // Grab the query data once
+ result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
+ if (FAILED(result))
+ {
+ if (d3d9::isDeviceLostError(result))
+ {
+ notifyDeviceLost();
+ }
+
+ freeEventQuery(query);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+ }
+
+ // Loop until the query completes
+ while (result == S_FALSE)
+ {
+ // Keep polling, but allow other threads to do something useful first
+ ScheduleYield();
+
+ result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
+
+ // 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
+ if (result == S_FALSE && testDeviceLost())
+ {
+ result = D3DERR_DEVICELOST;
+ }
+
+ if (FAILED(result))
+ {
+ if (d3d9::isDeviceLostError(result))
+ {
+ notifyDeviceLost();
+ }
+
+ freeEventQuery(query);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+ }
+
+ }
+
+ freeEventQuery(query);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+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)
+{
+ return new SwapChain9(this, GetAs<NativeWindow9>(nativeWindow), shareHandle, d3dTexture,
+ backBufferFormat, depthBufferFormat, orientation);
+}
+
+egl::Error Renderer9::getD3DTextureInfo(IUnknown *d3dTexture,
+ EGLint *width,
+ EGLint *height,
+ GLenum *fboFormat) const
+{
+ IDirect3DTexture9 *texture = nullptr;
+ if (FAILED(d3dTexture->QueryInterface(&texture)))
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "client buffer is not a IDirect3DTexture9");
+ }
+
+ IDirect3DDevice9 *textureDevice = nullptr;
+ texture->GetDevice(&textureDevice);
+ if (textureDevice != mDevice)
+ {
+ SafeRelease(texture);
+ return egl::Error(EGL_BAD_PARAMETER, "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);
+ }
+
+ // 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::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
+ desc.Format);
+ }
+
+ if (fboFormat)
+ {
+ const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+ ASSERT(d3dFormatInfo.info().id != angle::Format::ID::NONE);
+ *fboFormat = d3dFormatInfo.info().fboImplementationInternalFormat;
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error Renderer9::validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const
+{
+ if (shareHandle == nullptr)
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "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::Error(EGL_BAD_PARAMETER, "Failed to open share handle, result: 0x%X.", 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::Error(EGL_BAD_PARAMETER, "Invalid texture parameters in share handle texture.");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+ContextImpl *Renderer9::createContext(const gl::ContextState &state)
+{
+ return new Context9(state, this);
+}
+
+void *Renderer9::getD3DDevice()
+{
+ return reinterpret_cast<void*>(mDevice);
+}
+
+gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery)
+{
+ if (mEventQueryPool.empty())
+ {
+ HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, outQuery);
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate event query, result: 0x%X.", result);
+ }
+ }
+ else
+ {
+ *outQuery = mEventQueryPool.back();
+ mEventQueryPool.pop_back();
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Renderer9::freeEventQuery(IDirect3DQuery9* query)
+{
+ if (mEventQueryPool.size() > 1000)
+ {
+ SafeRelease(query);
+ }
+ else
+ {
+ mEventQueryPool.push_back(query);
+ }
+}
+
+gl::Error Renderer9::createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader)
+{
+ return mVertexShaderCache.create(function, length, outShader);
+}
+
+gl::Error Renderer9::createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader)
+{
+ return mPixelShaderCache.create(function, length, outShader);
+}
+
+HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer)
+{
+ D3DPOOL Pool = getBufferPool(Usage);
+ return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL);
+}
+
+VertexBuffer *Renderer9::createVertexBuffer()
+{
+ return new VertexBuffer9(this);
+}
+
+HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer)
+{
+ D3DPOOL Pool = getBufferPool(Usage);
+ return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL);
+}
+
+IndexBuffer *Renderer9::createIndexBuffer()
+{
+ return new IndexBuffer9(this);
+}
+
+StreamProducerImpl *Renderer9::createStreamProducerD3DTextureNV12(
+ 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;
+}
+
+gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, 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.
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerState)
+{
+ CurSamplerState &appliedSampler = (type == gl::SAMPLER_PIXEL) ? 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;
+ gl::Error error = textureD3D->getNativeTexture(&storage);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // 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::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
+ int d3dSampler = index + d3dSamplerOffset;
+
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS));
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT));
+
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy));
+
+ D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
+ float lodBias;
+ gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, &lodBias,
+ samplerState.maxAnisotropy, 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().textureFilterAnisotropic)
+ {
+ DWORD maxAnisotropy =
+ std::min(mDeviceCaps.MaxAnisotropy, static_cast<DWORD>(samplerState.maxAnisotropy));
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, maxAnisotropy);
+ }
+ }
+
+ appliedSampler.forceSet = false;
+ appliedSampler.samplerState = samplerState;
+ appliedSampler.baseLevel = baseLevel;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
+{
+ int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
+ int d3dSampler = index + d3dSamplerOffset;
+ IDirect3DBaseTexture9 *d3dTexture = NULL;
+ bool forceSetTexture = false;
+
+ std::vector<uintptr_t> &appliedTextures = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextures : mCurVertexTextures;
+
+ if (texture)
+ {
+ TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
+
+ TextureStorage *texStorage = nullptr;
+ gl::Error error = textureImpl->getNativeTexture(&texStorage);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // Texture should be complete and have a storage
+ ASSERT(texStorage);
+
+ TextureStorage9 *storage9 = GetAs<TextureStorage9>(texStorage);
+ error = storage9->getBaseTexture(&d3dTexture);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // 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 != NULL);
+
+ 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 gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::setUniformBuffers(const gl::ContextState & /*data*/,
+ const std::vector<GLint> & /*vertexUniformBuffers*/,
+ const std::vector<GLint> & /*fragmentUniformBuffers*/)
+{
+ // No effect in ES2/D3D9
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::updateState(Context9 *context, GLenum drawMode)
+{
+ const auto &data = context->getContextState();
+ const auto &glState = data.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() && framebuffer->complete(data));
+
+ ANGLE_TRY(applyRenderTarget(context, framebuffer));
+
+ // 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;
+ auto firstColorAttachment = framebuffer->getFirstColorbuffer();
+ if (firstColorAttachment)
+ {
+ ASSERT(firstColorAttachment->isAttached());
+ RenderTarget9 *renderTarget = nullptr;
+ ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
+ samples = renderTarget->getSamples();
+ }
+ gl::RasterizerState rasterizer = glState.getRasterizerState();
+ rasterizer.pointDrawMode = (drawMode == GL_POINTS);
+ rasterizer.multiSample = (samples != 0);
+
+ unsigned int mask = GetBlendSampleMask(data, samples);
+ ANGLE_TRY(setBlendDepthRasterStates(data, mask));
+
+ mStateManager.resetDirtyBits();
+
+ return gl::NoError();
+}
+
+void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
+{
+ mStateManager.setScissorState(scissor, enabled);
+}
+
+gl::Error Renderer9::setBlendDepthRasterStates(const gl::ContextState &glData, GLenum drawMode)
+{
+ const auto &glState = glData.getState();
+ auto 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;
+ auto firstColorAttachment = drawFramebuffer->getFirstColorbuffer();
+ if (firstColorAttachment)
+ {
+ ASSERT(firstColorAttachment->isAttached());
+ RenderTarget9 *renderTarget = nullptr;
+ ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
+ samples = renderTarget->getSamples();
+ }
+ gl::RasterizerState rasterizer = glState.getRasterizerState();
+ rasterizer.pointDrawMode = (drawMode == GL_POINTS);
+ rasterizer.multiSample = (samples != 0);
+
+ unsigned int mask = GetBlendSampleMask(glData, samples);
+ return mStateManager.setBlendDepthRasterStates(glState, mask);
+}
+
+void Renderer9::setViewport(const gl::Rectangle &viewport,
+ float zNear,
+ float zFar,
+ GLenum drawMode,
+ GLenum frontFace,
+ bool ignoreViewport)
+{
+ mStateManager.setViewportState(viewport, zNear, zFar, drawMode, frontFace, ignoreViewport);
+}
+
+bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
+{
+ switch (mode)
+ {
+ case GL_POINTS:
+ mPrimitiveType = D3DPT_POINTLIST;
+ mPrimitiveCount = count;
+ break;
+ case GL_LINES:
+ mPrimitiveType = D3DPT_LINELIST;
+ mPrimitiveCount = count / 2;
+ break;
+ case GL_LINE_LOOP:
+ mPrimitiveType = D3DPT_LINESTRIP;
+ mPrimitiveCount = count - 1; // D3D doesn't support line loops, so we draw the last line separately
+ break;
+ case GL_LINE_STRIP:
+ mPrimitiveType = D3DPT_LINESTRIP;
+ mPrimitiveCount = count - 1;
+ break;
+ case GL_TRIANGLES:
+ mPrimitiveType = D3DPT_TRIANGLELIST;
+ mPrimitiveCount = count / 3;
+ break;
+ case GL_TRIANGLE_STRIP:
+ mPrimitiveType = D3DPT_TRIANGLESTRIP;
+ mPrimitiveCount = count - 2;
+ break;
+ case GL_TRIANGLE_FAN:
+ mPrimitiveType = D3DPT_TRIANGLEFAN;
+ mPrimitiveCount = count - 2;
+ break;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+
+ return mPrimitiveCount > 0;
+}
+
+gl::Error Renderer9::getNullColorbuffer(GLImplFactory *implFactory,
+ const gl::FramebufferAttachment *depthbuffer,
+ const gl::FramebufferAttachment **outColorBuffer)
+{
+ ASSERT(depthbuffer);
+
+ const gl::Extents &size = depthbuffer->getSize();
+
+ // search cached nullcolorbuffers
+ for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+ {
+ if (mNullColorbufferCache[i].buffer != NULL &&
+ mNullColorbufferCache[i].width == size.width &&
+ mNullColorbufferCache[i].height == size.height)
+ {
+ mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
+ *outColorBuffer = mNullColorbufferCache[i].buffer;
+ return gl::Error(GL_NO_ERROR);
+ }
+ }
+
+ gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(implFactory->createRenderbuffer(), 0);
+ gl::Error error = nullRenderbuffer->setStorage(GL_NONE, size.width, size.height);
+ if (error.isError())
+ {
+ SafeDelete(nullRenderbuffer);
+ return error;
+ }
+
+ gl::FramebufferAttachment *nullbuffer = new gl::FramebufferAttachment(GL_RENDERBUFFER, GL_NONE, gl::ImageIndex::MakeInvalid(), nullRenderbuffer);
+
+ // add nullbuffer to the cache
+ NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0];
+ for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+ {
+ if (mNullColorbufferCache[i].lruCount < oldest->lruCount)
+ {
+ oldest = &mNullColorbufferCache[i];
+ }
+ }
+
+ delete oldest->buffer;
+ oldest->buffer = nullbuffer;
+ oldest->lruCount = ++mMaxNullColorbufferLRU;
+ oldest->width = size.width;
+ oldest->height = size.height;
+
+ *outColorBuffer = nullbuffer;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::applyRenderTarget(GLImplFactory *implFactory,
+ const gl::FramebufferAttachment *colorAttachment,
+ const gl::FramebufferAttachment *depthStencilAttachment)
+{
+ const gl::FramebufferAttachment *renderAttachment = colorAttachment;
+ gl::Error error(GL_NO_ERROR);
+
+ // 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.
+ if (renderAttachment == nullptr)
+ {
+ error = getNullColorbuffer(implFactory, depthStencilAttachment, &renderAttachment);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ ASSERT(renderAttachment != nullptr);
+
+ size_t renderTargetWidth = 0;
+ size_t renderTargetHeight = 0;
+ D3DFORMAT renderTargetFormat = D3DFMT_UNKNOWN;
+
+ RenderTarget9 *renderTarget = nullptr;
+ error = renderAttachment->getRenderTarget(&renderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(renderTarget);
+
+ bool renderTargetChanged = false;
+ unsigned int renderTargetSerial = renderTarget->getSerial();
+ if (renderTargetSerial != mAppliedRenderTargetSerial)
+ {
+ // Apply the render target on the device
+ IDirect3DSurface9 *renderTargetSurface = renderTarget->getSurface();
+ ASSERT(renderTargetSurface);
+
+ mDevice->SetRenderTarget(0, renderTargetSurface);
+ SafeRelease(renderTargetSurface);
+
+ renderTargetWidth = renderTarget->getWidth();
+ renderTargetHeight = renderTarget->getHeight();
+ renderTargetFormat = renderTarget->getD3DFormat();
+
+ mAppliedRenderTargetSerial = renderTargetSerial;
+ renderTargetChanged = true;
+ }
+
+ RenderTarget9 *depthStencilRenderTarget = nullptr;
+ unsigned int depthStencilSerial = 0;
+
+ if (depthStencilAttachment != nullptr)
+ {
+ error = depthStencilAttachment->getRenderTarget(&depthStencilRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(depthStencilRenderTarget);
+
+ 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);
+
+ depthSize = depthStencilAttachment->getDepthSize();
+ stencilSize = depthStencilAttachment->getStencilSize();
+ }
+ else
+ {
+ mDevice->SetDepthStencilSurface(NULL);
+ }
+
+ 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 gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::applyRenderTarget(GLImplFactory *implFactory,
+ const gl::Framebuffer *framebuffer)
+{
+ return applyRenderTarget(implFactory, framebuffer->getColorbuffer(0),
+ framebuffer->getDepthOrStencilbuffer());
+}
+
+gl::Error Renderer9::applyVertexBuffer(const gl::State &state,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances,
+ TranslatedIndexData * /*indexInfo*/)
+{
+ gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return mVertexDeclarationCache.applyDeclaration(
+ mDevice, mTranslatedAttribCache, state.getProgram(), first, instances, &mRepeatDraw);
+}
+
+// Applies the indices and element array bindings to the Direct3D 9 device
+gl::Error Renderer9::applyIndexBuffer(const gl::ContextState &data,
+ const GLvoid *indices,
+ GLsizei count,
+ GLenum mode,
+ GLenum type,
+ TranslatedIndexData *indexInfo)
+{
+ gl::VertexArray *vao = data.getState().getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+ gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices,
+ indexInfo, false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // Directly binding the storage buffer is not supported for d3d9
+ ASSERT(indexInfo->storage == NULL);
+
+ if (indexInfo->serial != mAppliedIBSerial)
+ {
+ IndexBuffer9* indexBuffer = GetAs<IndexBuffer9>(indexInfo->indexBuffer);
+
+ mDevice->SetIndices(indexBuffer->getBuffer());
+ mAppliedIBSerial = indexInfo->serial;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::applyTransformFeedbackBuffers(const gl::State &state)
+{
+ ASSERT(!state.isTransformFeedbackActiveUnpaused());
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::drawArraysImpl(const gl::ContextState &data,
+ GLenum mode,
+ GLint startVertex,
+ GLsizei count,
+ GLsizei instances)
+{
+ ASSERT(!data.getState().isTransformFeedbackActiveUnpaused());
+
+ startScene();
+
+ if (mode == GL_LINE_LOOP)
+ {
+ return drawLineLoop(count, GL_NONE, NULL, 0, NULL);
+ }
+ else if (instances > 0)
+ {
+ StaticIndexBufferInterface *countingIB = NULL;
+ gl::Error error = getCountingIB(count, &countingIB);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ 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 gl::Error(GL_NO_ERROR);
+ }
+ else // Regular case
+ {
+ mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount);
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+gl::Error Renderer9::drawElementsImpl(const gl::ContextState &data,
+ const TranslatedIndexData &indexInfo,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei /*instances*/)
+{
+ startScene();
+
+ int minIndex = static_cast<int>(indexInfo.indexRange.start);
+
+ gl::VertexArray *vao = data.getState().getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
+ if (mode == GL_POINTS)
+ {
+ return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer);
+ }
+ else if (mode == GL_LINE_LOOP)
+ {
+ return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer);
+ }
+ else
+ {
+ size_t vertexCount = indexInfo.indexRange.vertexCount();
+ for (int i = 0; i < mRepeatDraw; i++)
+ {
+ mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex,
+ static_cast<UINT>(vertexCount), indexInfo.startIndex,
+ mPrimitiveCount);
+ }
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
+{
+ // Get the raw indices for an indexed draw
+ if (type != GL_NONE && elementArrayBuffer)
+ {
+ BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ const uint8_t *bufferData = NULL;
+ gl::Error error = storage->getData(&bufferData);
+ if (error.isError())
+ {
+ return error;
+ }
+ indices = bufferData + offset;
+ }
+
+ unsigned int startIndex = 0;
+
+ if (getNativeExtensions().elementIndexUint)
+ {
+ if (!mLineLoopIB)
+ {
+ mLineLoopIB = new StreamingIndexBufferInterface(this);
+ gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+ if (error.isError())
+ {
+ SafeDelete(mLineLoopIB);
+ return error;
+ }
+ }
+
+ // Checked by Renderer9::applyPrimitiveType
+ ASSERT(count >= 0);
+
+ if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
+ }
+
+ const unsigned int spaceNeeded = (static_cast<unsigned int>(count)+1) * sizeof(unsigned int);
+ gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ void* mappedMemory = NULL;
+ unsigned int offset = 0;
+ error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ startIndex = static_cast<unsigned int>(offset) / 4;
+ unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
+
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ 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_UNSIGNED_SHORT:
+ 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_UNSIGNED_INT:
+ 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();
+ }
+
+ error = mLineLoopIB->unmapBuffer();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ else
+ {
+ if (!mLineLoopIB)
+ {
+ mLineLoopIB = new StreamingIndexBufferInterface(this);
+ gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT);
+ if (error.isError())
+ {
+ SafeDelete(mLineLoopIB);
+ return error;
+ }
+ }
+
+ // Checked by Renderer9::applyPrimitiveType
+ ASSERT(count >= 0);
+
+ if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
+ }
+
+ const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short);
+ gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ void* mappedMemory = NULL;
+ unsigned int offset;
+ error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ startIndex = static_cast<unsigned int>(offset) / 2;
+ unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
+
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<unsigned short>(i);
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ 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_UNSIGNED_SHORT:
+ 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_UNSIGNED_INT:
+ 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();
+ }
+
+ error = mLineLoopIB->unmapBuffer();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ 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 gl::Error(GL_NO_ERROR);
+}
+
+template <typename T>
+static gl::Error drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *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);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *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 = NULL;
+ gl::Error error = storage->getData(&bufferData);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ indices = bufferData + offset;
+ }
+
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE: return drawPoints<GLubyte>(mDevice, count, indices, minIndex);
+ case GL_UNSIGNED_SHORT: return drawPoints<GLushort>(mDevice, count, indices, minIndex);
+ case GL_UNSIGNED_INT: return drawPoints<GLuint>(mDevice, count, indices, minIndex);
+ default: UNREACHABLE(); return gl::Error(GL_INVALID_OPERATION);
+ }
+}
+
+gl::Error Renderer9::getCountingIB(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);
+ mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+
+ void *mappedMemory = NULL;
+ gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
+ for (size_t i = 0; i < count; i++)
+ {
+ data[i] = static_cast<unsigned short>(i);
+ }
+
+ error = mCountingIB->unmapBuffer();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+ else if (getNativeExtensions().elementIndexUint)
+ {
+ const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned int);
+
+ if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded)
+ {
+ SafeDelete(mCountingIB);
+ mCountingIB = new StaticIndexBufferInterface(this);
+ mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
+
+ void *mappedMemory = NULL;
+ gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
+ for (unsigned int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+
+ error = mCountingIB->unmapBuffer();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+ else
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Could not create a counting index buffer for glDrawArraysInstanced.");
+ }
+
+ *outIB = mCountingIB;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::applyShaders(const gl::ContextState &data, GLenum drawMode)
+{
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.getState().getProgram());
+ programD3D->updateCachedInputLayout(data.getState());
+
+ const auto &inputLayout = programD3D->getCachedInputLayout();
+
+ ShaderExecutableD3D *vertexExe = NULL;
+ ANGLE_TRY(programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr));
+
+ const gl::Framebuffer *drawFramebuffer = data.getState().getDrawFramebuffer();
+ ShaderExecutableD3D *pixelExe = NULL;
+ ANGLE_TRY(programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe));
+
+ 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;
+ }
+
+ return programD3D->applyUniforms(drawMode);
+}
+
+gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
+ GLenum /*drawMode*/,
+ const std::vector<D3DUniform *> &uniformArray)
+{
+ for (const D3DUniform *targetUniform : uniformArray)
+ {
+ if (!targetUniform->dirty)
+ continue;
+
+ GLfloat *f = (GLfloat *)targetUniform->data;
+ GLint *i = (GLint *)targetUniform->data;
+
+ switch (targetUniform->type)
+ {
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_EXTERNAL_OES:
+ 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();
+ }
+ }
+
+ // Driver uniforms
+ mStateManager.setShaderConstants();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Renderer9::applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v)
+{
+ if (targetUniform->isReferencedByFragmentShader())
+ {
+ mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount);
+ }
+
+ if (targetUniform->isReferencedByVertexShader())
+ {
+ mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, 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);
+}
+
+gl::Error Renderer9::clear(const ClearParameters &clearParams,
+ const gl::FramebufferAttachment *colorBuffer,
+ const gl::FramebufferAttachment *depthStencilBuffer)
+{
+ if (clearParams.colorClearType != GL_FLOAT)
+ {
+ // Clearing buffers with non-float values is not supported by Renderer9 and ES 2.0
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+ }
+
+ bool clearColor = clearParams.clearColor[0];
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ if (clearParams.clearColor[i] != clearColor)
+ {
+ // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+ }
+ }
+
+ float depth = gl::clamp01(clearParams.depthClearValue);
+ DWORD stencil = clearParams.stencilClearValue & 0x000000FF;
+
+ unsigned int stencilUnmasked = 0x0;
+ if (clearParams.clearStencil && depthStencilBuffer->getStencilSize() > 0)
+ {
+ ASSERT(depthStencilBuffer != nullptr);
+
+ RenderTargetD3D *stencilRenderTarget = nullptr;
+ gl::Error error = depthStencilBuffer->getRenderTarget(&stencilRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ RenderTarget9 *stencilRenderTarget9 = GetAs<RenderTarget9>(stencilRenderTarget);
+ ASSERT(stencilRenderTarget9);
+
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(stencilRenderTarget9->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(colorBuffer != nullptr);
+
+ RenderTargetD3D *colorRenderTarget = NULL;
+ gl::Error error = colorBuffer->getRenderTarget(&colorRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ RenderTarget9 *colorRenderTarget9 = GetAs<RenderTarget9>(colorRenderTarget);
+ ASSERT(colorRenderTarget9);
+
+ const gl::InternalFormat &formatInfo = *colorBuffer->getFormat().info;
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(colorRenderTarget9->getD3DFormat());
+
+ color =
+ D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && d3dFormatInfo.alphaBits > 0)
+ ? 1.0f
+ : clearParams.colorFClearValue.alpha),
+ gl::unorm<8>((formatInfo.redBits == 0 && d3dFormatInfo.redBits > 0)
+ ? 0.0f
+ : clearParams.colorFClearValue.red),
+ gl::unorm<8>((formatInfo.greenBits == 0 && d3dFormatInfo.greenBits > 0)
+ ? 0.0f
+ : clearParams.colorFClearValue.green),
+ gl::unorm<8>((formatInfo.blueBits == 0 && d3dFormatInfo.blueBits > 0)
+ ? 0.0f
+ : clearParams.colorFClearValue.blue));
+
+ if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
+ (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
+ (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
+ (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
+ {
+ 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 == NULL)
+ {
+ 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(NULL);
+ mDevice->SetVertexShader(NULL);
+ mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
+ mDevice->SetStreamSource(0, NULL, 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 != NULL);
+
+ if (mMaskedClearSavedState != NULL)
+ {
+ 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)
+ {
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
+ gl_d3d9::ConvertColorMask(clearParams.colorMaskRed,
+ clearParams.colorMaskGreen,
+ clearParams.colorMaskBlue,
+ clearParams.colorMaskAlpha));
+ }
+ 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(NULL);
+ mDevice->SetVertexShader(NULL);
+ 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, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
+ }
+
+ if (mMaskedClearSavedState != NULL)
+ {
+ 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, NULL, dxClearFlags, color, depth, stencil);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+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 = NULL;
+ mAppliedPixelShader = NULL;
+ 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(mNullColorbufferCache[i].buffer);
+ }
+}
+
+// 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(NULL);
+ }
+ 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 != NULL);
+ case D3DERR_DEVICEREMOVED:
+ ASSERT(mDeviceEx != NULL);
+ 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 != NULL || !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, NULL);
+ 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: 0x%08X", 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
+ initializeDevice();
+ }
+
+ return true;
+}
+
+bool Renderer9::isRemovedDeviceResettable() const
+{
+ bool success = false;
+
+#if ANGLE_D3D9EX == ANGLE_ENABLED
+ IDirect3D9Ex *d3d9Ex = NULL;
+ 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
+ ASSERT(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 = { 0 };
+ 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();
+}
+
+unsigned int Renderer9::getReservedVertexUniformBuffers() const
+{
+ return 0;
+}
+
+unsigned int Renderer9::getReservedFragmentUniformBuffers() const
+{
+ return 0;
+}
+
+bool Renderer9::getShareHandleSupport() const
+{
+ // PIX doesn't seem to support using share handles, so disable them.
+ return (mD3d9Ex != NULL) && !gl::DebugAnnotationsActive();
+}
+
+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 != NULL)
+ {
+ return D3DPOOL_DEFAULT;
+ }
+ else
+ {
+ if (!(usage & D3DUSAGE_DYNAMIC))
+ {
+ return D3DPOOL_MANAGED;
+ }
+ }
+
+ return D3DPOOL_DEFAULT;
+}
+
+gl::Error Renderer9::copyImage2D(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(framebuffer, rect, destFormat, destOffset, storage, level);
+}
+
+gl::Error Renderer9::copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLenum 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(framebuffer, rect, destFormat, destOffset, storage, target, level);
+}
+
+gl::Error Renderer9::copyImage3D(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.
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Renderer9::copyImage2DArray(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.
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Renderer9::copyTexture(const gl::Texture *source,
+ GLint sourceLevel,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Renderer9::copyCompressedTexture(const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Renderer9::createRenderTarget(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 = NULL;
+ if (width > 0 && height > 0)
+ {
+ bool requiresInitialization = false;
+ HRESULT result = D3DERR_INVALIDCALL;
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
+ if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+ {
+ result = mDevice->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat,
+ gl_d3d9::GetMultisampleType(supportedSamples),
+ 0, FALSE, &renderTarget, NULL);
+ }
+ 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);
+ }
+ }
+ }
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == E_INVALIDARG);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target, result: 0x%X.", result);
+ }
+
+ 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 = NULL;
+ mDevice->GetRenderTarget(0, &prevRenderTarget);
+ mDevice->SetRenderTarget(0, renderTarget);
+ mDevice->Clear(0, NULL, 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 gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT)
+{
+ ASSERT(source != nullptr);
+
+ RenderTargetD3D *newRT = nullptr;
+ gl::Error error = createRenderTarget(source->getWidth(), source->getHeight(),
+ source->getInternalFormat(), source->getSamples(), &newRT);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ RenderTarget9 *source9 = GetAs<RenderTarget9>(source);
+ RenderTarget9 *dest9 = GetAs<RenderTarget9>(newRT);
+
+ HRESULT result = mDevice->StretchRect(source9->getSurface(), nullptr, dest9->getSurface(),
+ nullptr, D3DTEXF_NONE);
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy render target, result: 0x%X.", result);
+ }
+
+ *outRT = newRT;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::loadExecutable(const void *function,
+ size_t length,
+ 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 SHADER_VERTEX:
+ {
+ IDirect3DVertexShader9 *vshader = NULL;
+ gl::Error error = createVertexShader((DWORD*)function, length, &vshader);
+ if (error.isError())
+ {
+ return error;
+ }
+ *outExecutable = new ShaderExecutable9(function, length, vshader);
+ }
+ break;
+ case SHADER_PIXEL:
+ {
+ IDirect3DPixelShader9 *pshader = NULL;
+ gl::Error error = createPixelShader((DWORD*)function, length, &pshader);
+ if (error.isError())
+ {
+ return error;
+ }
+ *outExecutable = new ShaderExecutable9(function, length, pshader);
+ }
+ break;
+ default:
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const D3DCompilerWorkarounds &workarounds,
+ ShaderExecutableD3D **outExectuable)
+{
+ // Transform feedback is not supported in ES2 or D3D9
+ ASSERT(streamOutVaryings.empty());
+
+ const char *profileType = NULL;
+ switch (type)
+ {
+ case SHADER_VERTEX:
+ profileType = "vs";
+ break;
+ case SHADER_PIXEL:
+ profileType = "ps";
+ break;
+ default:
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+ }
+ unsigned int profileMajorVersion = (getMajorShaderModel() >= 3) ? 3 : 2;
+ unsigned int profileMinorVersion = 0;
+ std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
+
+ UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL;
+
+ if (workarounds.skipOptimization)
+ {
+ flags = D3DCOMPILE_SKIP_OPTIMIZATION;
+ }
+ else if (workarounds.useMaxOptimization)
+ {
+ flags = D3DCOMPILE_OPTIMIZATION_LEVEL3;
+ }
+
+ if (gl::DebugAnnotationsActive())
+ {
+#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 = NULL;
+ std::string debugInfo;
+ gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, NULL, &binary, &debugInfo);
+ if (error.isError())
+ {
+ return 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 = NULL;
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
+ streamOutVaryings, separatedOutputBuffers, outExectuable);
+
+ SafeRelease(binary);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!debugInfo.empty())
+ {
+ (*outExectuable)->appendDebugInfo(debugInfo);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+UniformStorageD3D *Renderer9::createUniformStorage(size_t storageSize)
+{
+ return new UniformStorageD3D(storageSize);
+}
+
+gl::Error Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
+{
+ return mBlit->boxFilter(source, dest);
+}
+
+D3DPOOL Renderer9::getTexturePool(DWORD usage) const
+{
+ // Always use DEFAULT pool for textures, as there is a bug
+ // on XP (non-D3D9Ex) where we select MANAGED here,
+ // but trigger a crash in Image9::copyToSurface where the
+ // source pool is SYSTEMMEM, but the destination pool is
+ // MANAGED. It expects the dest pool to be DEFAULT
+ // if the source is SYSTEMMEM.
+ return D3DPOOL_DEFAULT;
+}
+
+gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
+{
+ ASSERT(source && dest);
+
+ 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, NULL);
+
+ if (SUCCEEDED(result))
+ {
+ Image9::copyLockableSurfaces(surf, source);
+ result = mDevice->UpdateSurface(surf, NULL, dest, NULL);
+ SafeRelease(surf);
+ }
+ }
+ else
+ {
+ endScene();
+ result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
+ }
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit internal texture, result: 0x%X.", result);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+ImageD3D *Renderer9::createImage()
+{
+ return new Image9(this);
+}
+
+gl::Error Renderer9::generateMipmap(ImageD3D *dest, ImageD3D *src)
+{
+ Image9 *src9 = GetAs<Image9>(src);
+ Image9 *dst9 = GetAs<Image9>(dest);
+ return Image9::generateMipmap(dst9, src9);
+}
+
+gl::Error Renderer9::generateMipmapUsingD3D(TextureStorage *storage,
+ const gl::TextureState &textureState)
+{
+ UNREACHABLE();
+ return gl::Error(GL_NO_ERROR);
+}
+
+TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain)
+{
+ SwapChain9 *swapChain9 = GetAs<SwapChain9>(swapChain);
+ return new TextureStorage9_2D(this, swapChain9);
+}
+
+TextureStorage *Renderer9::createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D)
+{
+ return new TextureStorage9_EGLImage(this, eglImage, GetAs<RenderTarget9>(renderTargetD3D));
+}
+
+TextureStorage *Renderer9::createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly)
+{
+ return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels);
+}
+
+TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
+{
+ return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly);
+}
+
+TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels)
+{
+ // 3D textures are not supported by the D3D9 backend.
+ UNREACHABLE();
+
+ return NULL;
+}
+
+TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels)
+{
+ // 2D array textures are not supported by the D3D9 backend.
+ UNREACHABLE();
+
+ return NULL;
+}
+
+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(gl::VertexFormatType vertexFormatType) const
+{
+ return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType).conversionType;
+}
+
+GLenum Renderer9::getVertexComponentType(gl::VertexFormatType vertexFormatType) const
+{
+ return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType).componentType;
+}
+
+gl::ErrorOrResult<unsigned int> Renderer9::getVertexSpaceRequired(const gl::VertexAttribute &attrib,
+ GLsizei count,
+ GLsizei instances) const
+{
+ gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, GL_FLOAT);
+ const d3d9::VertexFormat &d3d9VertexInfo =
+ d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType);
+
+ if (!attrib.enabled)
+ {
+ return 16u;
+ }
+
+ unsigned int elementCount = 0;
+ if (instances == 0 || attrib.divisor == 0)
+ {
+ elementCount = static_cast<unsigned int>(count);
+ }
+ else
+ {
+ // Round up to divisor, if possible
+ elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
+ }
+
+ if (d3d9VertexInfo.outputElementSize > std::numeric_limits<unsigned int>::max() / elementCount)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
+ }
+
+ return static_cast<unsigned int>(d3d9VertexInfo.outputElementSize) * elementCount;
+}
+
+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);
+}
+
+WorkaroundsD3D Renderer9::generateWorkarounds() const
+{
+ return d3d9::GenerateWorkarounds();
+}
+
+gl::Error Renderer9::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd)
+{
+ // TODO(jmadill): faster way?
+ for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; samplerIndex++)
+ {
+ gl::Error error = setTexture(samplerType, static_cast<int>(samplerIndex), nullptr);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+egl::Error Renderer9::getEGLDevice(DeviceImpl **device)
+{
+ if (mEGLDevice == nullptr)
+ {
+ ASSERT(mDevice != nullptr);
+ mEGLDevice = new DeviceD3D();
+ egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice),
+ EGL_D3D9_DEVICE_ANGLE, EGL_FALSE);
+
+ if (error.isError())
+ {
+ SafeDelete(mEGLDevice);
+ return error;
+ }
+ }
+
+ *device = static_cast<DeviceImpl *>(mEGLDevice);
+ return egl::Error(EGL_SUCCESS);
+}
+
+Renderer9::CurSamplerState::CurSamplerState()
+ : forceSet(true),
+ baseLevel(std::numeric_limits<size_t>::max()),
+ samplerState()
+{
+}
+
+gl::Error Renderer9::genericDrawElements(Context9 *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange)
+{
+ const auto &data = context->getContextState();
+ gl::Program *program = context->getGLState().getProgram();
+ ASSERT(program != nullptr);
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ bool usesPointSize = programD3D->usesPointSize();
+
+ programD3D->updateSamplerMapping();
+
+ if (!applyPrimitiveType(mode, count, usesPointSize))
+ {
+ return gl::NoError();
+ }
+
+ ANGLE_TRY(updateState(context, mode));
+
+ TranslatedIndexData indexInfo;
+ indexInfo.indexRange = indexRange;
+
+ ANGLE_TRY(applyIndexBuffer(data, indices, count, mode, type, &indexInfo));
+
+ applyTransformFeedbackBuffers(data.getState());
+ // Transform feedback is not allowed for DrawElements, this error should have been caught at the
+ // API validation
+ // layer.
+ ASSERT(!data.getState().isTransformFeedbackActiveUnpaused());
+
+ size_t vertexCount = indexInfo.indexRange.vertexCount();
+ ANGLE_TRY(applyVertexBuffer(data.getState(), mode,
+ static_cast<GLsizei>(indexInfo.indexRange.start),
+ static_cast<GLsizei>(vertexCount), instances, &indexInfo));
+ ANGLE_TRY(applyTextures(context, data));
+ ANGLE_TRY(applyShaders(data, mode));
+ ANGLE_TRY(programD3D->applyUniformBuffers(data));
+
+ if (!skipDraw(data, mode))
+ {
+ ANGLE_TRY(drawElementsImpl(data, indexInfo, mode, count, type, indices, instances));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Renderer9::genericDrawArrays(Context9 *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances)
+{
+ const auto &data = context->getContextState();
+ gl::Program *program = context->getGLState().getProgram();
+ ASSERT(program != nullptr);
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ bool usesPointSize = programD3D->usesPointSize();
+
+ programD3D->updateSamplerMapping();
+
+ if (!applyPrimitiveType(mode, count, usesPointSize))
+ {
+ return gl::NoError();
+ }
+
+ ANGLE_TRY(updateState(context, mode));
+ ANGLE_TRY(applyTransformFeedbackBuffers(data.getState()));
+ ANGLE_TRY(applyVertexBuffer(data.getState(), mode, first, count, instances, nullptr));
+ ANGLE_TRY(applyTextures(context, data));
+ ANGLE_TRY(applyShaders(data, mode));
+ ANGLE_TRY(programD3D->applyUniformBuffers(data));
+
+ if (!skipDraw(data, mode))
+ {
+ ANGLE_TRY(drawArraysImpl(data, mode, first, count, instances));
+
+ if (data.getState().isTransformFeedbackActiveUnpaused())
+ {
+ ANGLE_TRY(markTransformFeedbackUsage(data));
+ }
+ }
+
+ return gl::NoError();
+}
+
+FramebufferImpl *Renderer9::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+ return new Framebuffer9(state, this);
+}
+
+gl::Version Renderer9::getMaxSupportedESVersion() const
+{
+ return gl::Version(2, 0);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
new file mode 100755
index 000000000..9c3ae8b04
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
@@ -0,0 +1,487 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
+#include "libANGLE/renderer/d3d/d3d9/ShaderCache.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h"
+#include "libANGLE/renderer/d3d/d3d9/StateManager9.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 StreamingIndexBufferInterface;
+class StaticIndexBufferInterface;
+class VertexDataManager;
+struct ClearParameters;
+struct D3DUniform;
+struct TranslatedAttribute;
+
+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
+};
+
+class Renderer9 : public RendererD3D
+{
+ public:
+ explicit Renderer9(egl::Display *display);
+ virtual ~Renderer9();
+
+ egl::Error initialize() override;
+ bool resetDevice() override;
+
+ egl::ConfigSet generateConfigs() override;
+ void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override;
+
+ void startScene();
+ void endScene();
+
+ gl::Error flush();
+ gl::Error finish();
+
+ 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) override;
+ egl::Error getD3DTextureInfo(IUnknown *d3dTexture,
+ EGLint *width,
+ EGLint *height,
+ GLenum *fboFormat) const override;
+ egl::Error validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const override;
+
+ ContextImpl *createContext(const gl::ContextState &state) override;
+
+ gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery);
+ void freeEventQuery(IDirect3DQuery9* query);
+
+ // resource creation
+ gl::Error createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader);
+ gl::Error createPixelShader(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);
+ gl::Error setSamplerState(gl::SamplerType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &sampler) override;
+ gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) override;
+
+ gl::Error setUniformBuffers(const gl::ContextState &data,
+ const std::vector<GLint> &vertexUniformBuffers,
+ const std::vector<GLint> &fragmentUniformBuffers) override;
+
+ gl::Error updateState(Context9 *context, GLenum drawMode);
+
+ void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+ void setViewport(const gl::Rectangle &viewport,
+ float zNear,
+ float zFar,
+ GLenum drawMode,
+ GLenum frontFace,
+ bool ignoreViewport);
+
+ gl::Error applyRenderTarget(GLImplFactory *implFactory, const gl::Framebuffer *frameBuffer);
+ gl::Error applyRenderTarget(GLImplFactory *implFactory,
+ const gl::FramebufferAttachment *colorAttachment,
+ const gl::FramebufferAttachment *depthStencilAttachment);
+ gl::Error applyUniforms(const ProgramD3D &programD3D,
+ GLenum drawMode,
+ const std::vector<D3DUniform *> &uniformArray) override;
+ bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize);
+ gl::Error applyVertexBuffer(const gl::State &state,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances,
+ TranslatedIndexData *indexInfo);
+ gl::Error applyIndexBuffer(const gl::ContextState &data,
+ const GLvoid *indices,
+ GLsizei count,
+ GLenum mode,
+ GLenum type,
+ TranslatedIndexData *indexInfo);
+
+ gl::Error applyTransformFeedbackBuffers(const gl::State &state);
+
+ gl::Error clear(const ClearParameters &clearParams,
+ const gl::FramebufferAttachment *colorBuffer,
+ const gl::FramebufferAttachment *depthStencilBuffer);
+
+ void markAllStateDirty();
+
+ // lost device
+ bool testDeviceLost() override;
+ bool testDeviceResettable();
+
+ VendorID getVendorId() const;
+ std::string getRendererDescription() const;
+ DeviceIdentifier getAdapterIdentifier() const override;
+
+ IDirect3DDevice9 *getDevice() { return mDevice; }
+ void *getD3DDevice() override;
+
+ unsigned int getReservedVertexUniformVectors() const;
+ unsigned int getReservedFragmentUniformVectors() const;
+ unsigned int getReservedVertexUniformBuffers() const override;
+ unsigned int getReservedFragmentUniformBuffers() const override;
+
+ bool getShareHandleSupport() const;
+
+ int getMajorShaderModel() const override;
+ int getMinorShaderModel() const override;
+ std::string getShaderModelSuffix() const override;
+
+ DWORD getCapsDeclTypes() const;
+
+ // Pixel operations
+ gl::Error copyImage2D(const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+ gl::Error copyImageCube(const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum target,
+ GLint level) override;
+ gl::Error copyImage3D(const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+ gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+
+ gl::Error copyTexture(const gl::Texture *source,
+ GLint sourceLevel,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) override;
+ gl::Error copyCompressedTexture(const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel) override;
+
+ // RenderTarget creation
+ gl::Error createRenderTarget(int width,
+ int height,
+ GLenum format,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+ gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override;
+
+ // Shader operations
+ gl::Error loadExecutable(const void *function,
+ size_t length,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable) override;
+ gl::Error compileToExecutable(gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const D3DCompilerWorkarounds &workarounds,
+ ShaderExecutableD3D **outExectuable) override;
+ UniformStorageD3D *createUniformStorage(size_t storageSize) override;
+
+ // Image operations
+ ImageD3D *createImage() override;
+ gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
+ gl::Error generateMipmapUsingD3D(TextureStorage *storage,
+ const gl::TextureState &textureState) override;
+ TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) override;
+ TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D) override;
+ TextureStorage *createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+ TextureStorage *createTextureStorage2D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ bool hintLevelZeroOnly) override;
+ TextureStorage *createTextureStorageCube(GLenum internalformat,
+ bool renderTarget,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly) override;
+ TextureStorage *createTextureStorage3D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels) override;
+ TextureStorage *createTextureStorage2DArray(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels) override;
+
+ // Buffer creation
+ VertexBuffer *createVertexBuffer() override;
+ IndexBuffer *createIndexBuffer() override;
+
+ // Stream Creation
+ StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) override;
+
+ // Buffer-to-texture and Texture-to-buffer copies
+ bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override;
+ gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea) override;
+
+ // D3D9-renderer specific methods
+ gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
+
+ D3DPOOL getTexturePool(DWORD usage) const;
+
+ bool getLUID(LUID *adapterLuid) const override;
+ VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const override;
+ GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override;
+ gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(const gl::VertexAttribute &attrib,
+ GLsizei count,
+ GLsizei instances) const override;
+
+ gl::Error copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
+
+ RendererClass getRendererClass() const override { return RENDERER_D3D9; }
+
+ D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; }
+
+ egl::Error getEGLDevice(DeviceImpl **device) override;
+
+ StateManager9 *getStateManager() { return &mStateManager; }
+
+ gl::Error genericDrawArrays(Context9 *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances);
+
+ gl::Error genericDrawElements(Context9 *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange);
+
+ // Necessary hack for default framebuffers in D3D.
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+ DebugAnnotator9 *getAnnotator() { return &mAnnotator; }
+
+ gl::Version getMaxSupportedESVersion() const override;
+
+ protected:
+ gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override;
+
+ private:
+ gl::Error drawArraysImpl(const gl::ContextState &data,
+ GLenum mode,
+ GLint startVertex,
+ GLsizei count,
+ GLsizei instances);
+ gl::Error drawElementsImpl(const gl::ContextState &data,
+ const TranslatedIndexData &indexInfo,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances);
+
+ gl::Error applyShaders(const gl::ContextState &data, GLenum drawMode);
+
+ void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations *outLimitations) const override;
+
+ WorkaroundsD3D generateWorkarounds() const override;
+
+ gl::Error setBlendDepthRasterStates(const gl::ContextState &glData, GLenum 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);
+
+ gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
+ gl::Error drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
+
+ gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB);
+
+ gl::Error getNullColorbuffer(GLImplFactory *implFactory,
+ const gl::FramebufferAttachment *depthbuffer,
+ const gl::FramebufferAttachment **outColorBuffer);
+
+ D3DPOOL getBufferPool(DWORD usage) const;
+
+ HMODULE mD3d9Module;
+
+ void 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 NullColorbufferCacheEntry
+ {
+ UINT lruCount;
+ int width;
+ int height;
+ gl::FramebufferAttachment *buffer;
+ } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES];
+ UINT mMaxNullColorbufferLRU;
+
+ DeviceD3D *mEGLDevice;
+ std::vector<TranslatedAttribute> mTranslatedAttribCache;
+
+ DebugAnnotator9 mAnnotator;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h
new file mode 100755
index 000000000..cf831c62f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h
@@ -0,0 +1,108 @@
+//
+// Copyright (c) 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 <cstddef>
+#include <unordered_map>
+#include <string>
+
+namespace rx
+{
+template <typename ShaderObject>
+class ShaderCache : angle::NonCopyable
+{
+ public:
+ ShaderCache() : mDevice(NULL)
+ {
+ }
+
+ ~ShaderCache()
+ {
+ // Call clear while the device is still valid.
+ ASSERT(mMap.empty());
+ }
+
+ void initialize(IDirect3DDevice9* device)
+ {
+ mDevice = device;
+ }
+
+ gl::Error create(const DWORD *function, size_t length, ShaderObject **outShaderObject)
+ {
+ 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 gl::Error(GL_NO_ERROR);
+ }
+
+ ShaderObject *shader;
+ HRESULT result = createShader(function, &shader);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader, result: 0x%X.", result);
+ }
+
+ // Random eviction policy.
+ if (mMap.size() >= kMaxMapSize)
+ {
+ SafeRelease(mMap.begin()->second);
+ mMap.erase(mMap.begin());
+ }
+
+ shader->AddRef();
+ mMap[key] = shader;
+
+ *outShaderObject = shader;
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ void clear()
+ {
+ 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 std::unordered_map<std::string, ShaderObject*> Map;
+ Map mMap;
+
+ IDirect3DDevice9 *mDevice;
+};
+
+typedef ShaderCache<IDirect3DVertexShader9> VertexShaderCache;
+typedef ShaderCache<IDirect3DPixelShader9> PixelShaderCache;
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp
new file mode 100755
index 000000000..dcce8fd2f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp
@@ -0,0 +1,47 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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 = NULL;
+}
+
+ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable)
+ : ShaderExecutableD3D(function, length)
+{
+ mVertexExecutable = executable;
+ mPixelExecutable = NULL;
+}
+
+ShaderExecutable9::~ShaderExecutable9()
+{
+ SafeRelease(mVertexExecutable);
+ SafeRelease(mPixelExecutable);
+}
+
+IDirect3DVertexShader9 *ShaderExecutable9::getVertexShader() const
+{
+ return mVertexExecutable;
+}
+
+IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const
+{
+ return mPixelExecutable;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h
new file mode 100755
index 000000000..382a68c82
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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);
+ virtual ~ShaderExecutable9();
+
+ IDirect3DPixelShader9 *getPixelShader() const;
+ IDirect3DVertexShader9 *getVertexShader() const;
+
+ private:
+ IDirect3DPixelShader9 *mPixelExecutable;
+ IDirect3DVertexShader9 *mVertexExecutable;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp
new file mode 100755
index 000000000..54885bf81
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp
@@ -0,0 +1,945 @@
+//
+// Copyright (c) 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/BitSetIterator.h"
+#include "common/utilities.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+StateManager9::StateManager9(Renderer9 *renderer9)
+ : mUsingZeroColorMaskWorkaround(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 : angle::IterateBitSet(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.getBlendState().sampleAlphaToCoverage !=
+ mCurBlendState.sampleAlphaToCoverage)
+ {
+ 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.getBlendState().dither != mCurBlendState.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);
+ }
+ }
+ 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:
+ if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_FUNC:
+ if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
+ if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest)
+ {
+ 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:
+ {
+ const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+ if (depthStencilState.stencilFunc != mCurDepthStencilState.stencilFunc ||
+ depthStencilState.stencilMask != mCurDepthStencilState.stencilMask ||
+ state.getStencilRef() != mCurStencilRef)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
+ {
+ const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+ if (depthStencilState.stencilBackFunc != mCurDepthStencilState.stencilBackFunc ||
+ depthStencilState.stencilBackMask != mCurDepthStencilState.stencilBackMask ||
+ state.getStencilBackRef() != mCurStencilBackRef)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+ if (state.getDepthStencilState().stencilWritemask !=
+ mCurDepthStencilState.stencilWritemask)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+ if (state.getDepthStencilState().stencilBackWritemask !=
+ mCurDepthStencilState.stencilBackWritemask)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
+ {
+ const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+ if (depthStencilState.stencilFail != mCurDepthStencilState.stencilFail ||
+ depthStencilState.stencilPassDepthFail !=
+ mCurDepthStencilState.stencilPassDepthFail ||
+ depthStencilState.stencilPassDepthPass !=
+ mCurDepthStencilState.stencilPassDepthPass)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
+ {
+ const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+ if (depthStencilState.stencilBackFail != mCurDepthStencilState.stencilBackFail ||
+ depthStencilState.stencilBackPassDepthFail !=
+ mCurDepthStencilState.stencilBackPassDepthFail ||
+ depthStencilState.stencilBackPassDepthPass !=
+ mCurDepthStencilState.stencilBackPassDepthPass)
+ {
+ 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:
+ if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar)
+ {
+ mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+ }
+ break;
+ case gl::State::DIRTY_BIT_VIEWPORT:
+ if (state.getViewport() != mCurViewport)
+ {
+ mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+gl::Error 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 : angle::IterateBitSet(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(blendState.sampleAlphaToCoverage);
+ break;
+ case DIRTY_BIT_COLOR_MASK:
+ setColorMask(framebuffer, blendState.colorMaskRed, blendState.colorMaskBlue,
+ blendState.colorMaskGreen, blendState.colorMaskAlpha);
+ break;
+ case DIRTY_BIT_DITHER:
+ setDither(blendState.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);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void StateManager9::setViewportState(const gl::Rectangle &viewport,
+ float zNear,
+ float zFar,
+ GLenum 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)
+ {
+ FIXME("Sample alpha to coverage is 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);
+ mCurBlendState.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->getFirstColorbuffer();
+ 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, GLenum 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/src/libANGLE/renderer/d3d/d3d9/StateManager9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h
new file mode 100755
index 000000000..bd2cef2e5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h
@@ -0,0 +1,209 @@
+//
+// Copyright (c) 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/angletypes.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/State.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);
+
+ gl::Error 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,
+ GLenum 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 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, GLenum 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
+ };
+
+ typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
+
+ bool mUsingZeroColorMaskWorkaround;
+
+ // 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/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
new file mode 100755
index 000000000..7e6948ebb
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
@@ -0,0 +1,442 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain.
+
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/features.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 = NULL;
+ }
+}
+
+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(int backbufferWidth, int backbufferHeight)
+{
+ // D3D9 does not support resizing swap chains without recreating them
+ return reset(backbufferWidth, backbufferHeight, mSwapInterval);
+}
+
+EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ if (device == NULL)
+ {
+ 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 = NULL;
+ 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: %08lX", 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 = {0};
+ 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: %08lX", 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, NULL, FALSE);
+ }
+
+ if (mDepthBufferFormat != GL_NONE)
+ {
+ result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight,
+ depthBufferd3dFormatInfo.renderFormat,
+ D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
+
+ ERR("Could not create depthstencil surface for new swap chain: 0x%08X", 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(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(NULL);
+ device->SetVertexShader(NULL);
+
+ device->SetRenderTarget(0, mBackBuffer);
+ device->SetDepthStencilSurface(NULL);
+
+ 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, NULL);
+
+ 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, NULL, NULL, 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))
+ {
+ 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;
+}
+
+void SwapChain9::recreate()
+{
+ if (!mSwapChain)
+ {
+ return;
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ if (device == NULL)
+ {
+ return;
+ }
+
+ D3DPRESENT_PARAMETERS presentParameters;
+ HRESULT result = mSwapChain->GetPresentParameters(&presentParameters);
+ ASSERT(SUCCEEDED(result));
+
+ IDirect3DSwapChain9* newSwapChain = NULL;
+ 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));
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
new file mode 100755
index 000000000..2e5cce1db
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
@@ -0,0 +1,71 @@
+//
+// Copyright (c) 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);
+ virtual ~SwapChain9();
+
+ EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
+ virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
+ virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
+ virtual void recreate();
+
+ RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; }
+ RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; }
+
+ virtual IDirect3DSurface9 *getRenderTarget();
+ virtual IDirect3DSurface9 *getDepthStencil();
+ virtual IDirect3DTexture9 *getOffscreenTexture();
+
+ EGLint getWidth() const { return mWidth; }
+ EGLint getHeight() const { return mHeight; }
+
+ void *getKeyedMutex() 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;
+};
+
+}
+#endif // LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
new file mode 100755
index 000000000..db8765218
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
@@ -0,0 +1,617 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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 "libANGLE/formatutils.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+
+namespace rx
+{
+TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage)
+ : 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::GetInternalFormatInfo(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;
+}
+
+gl::Error TextureStorage9::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixelData)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain)
+ : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET)
+{
+ 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)
+ : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
+{
+ mTexture = NULL;
+
+ 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 (auto &renderTarget : mRenderTargets)
+ {
+ SafeDelete(renderTarget);
+ }
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+gl::Error TextureStorage9_2D::getSurfaceLevel(GLenum target,
+ int level,
+ bool dirty,
+ IDirect3DSurface9 **outSurface)
+{
+ ASSERT(target == GL_TEXTURE_2D);
+
+ IDirect3DBaseTexture9 *baseTexture = NULL;
+ gl::Error error = getBaseTexture(&baseTexture);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IDirect3DTexture9 *texture = static_cast<IDirect3DTexture9*>(baseTexture);
+
+ HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface);
+
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
+ }
+
+ // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+ if (level + mTopLevel != 0 && isManaged() && dirty)
+ {
+ texture->AddDirtyRect(NULL);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+ ASSERT(index.mipIndex < getLevelCount());
+
+ if (!mRenderTargets[index.mipIndex] && isRenderTarget())
+ {
+ IDirect3DBaseTexture9 *baseTexture = NULL;
+ gl::Error error = getBaseTexture(&baseTexture);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IDirect3DSurface9 *surface = NULL;
+ error = getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, false, &surface);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ size_t textureMipLevel = mTopLevel + index.mipIndex;
+ size_t mipWidth = std::max<size_t>(mTextureWidth >> textureMipLevel, 1u);
+ size_t mipHeight = std::max<size_t>(mTextureHeight >> textureMipLevel, 1u);
+
+ baseTexture->AddRef();
+ mRenderTargets[index.mipIndex] = new TextureRenderTarget9(
+ baseTexture, textureMipLevel, surface, mInternalFormat, static_cast<GLsizei>(mipWidth),
+ static_cast<GLsizei>(mipHeight), 1, 0);
+ }
+
+ ASSERT(outRT);
+ *outRT = mRenderTargets[index.mipIndex];
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
+{
+ IDirect3DSurface9 *upper = NULL;
+ gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, sourceIndex.mipIndex, false, &upper);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IDirect3DSurface9 *lower = NULL;
+ error = getSurfaceLevel(GL_TEXTURE_2D, destIndex.mipIndex, true, &lower);
+ if (error.isError())
+ {
+ SafeRelease(upper);
+ return error;
+ }
+
+ ASSERT(upper && lower);
+ error = mRenderer->boxFilter(upper, lower);
+
+ SafeRelease(upper);
+ SafeRelease(lower);
+
+ return error;
+}
+
+gl::Error TextureStorage9_2D::getBaseTexture(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 == NULL && 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, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D storage texture, result: 0x%X.", result);
+ }
+ }
+
+ *outTexture = mTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+
+ TextureStorage9_2D *dest9 = GetAs<TextureStorage9_2D>(destStorage);
+
+ int levels = getLevelCount();
+ for (int i = 0; i < levels; ++i)
+ {
+ IDirect3DSurface9 *srcSurf = NULL;
+ gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, i, false, &srcSurf);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IDirect3DSurface9 *dstSurf = NULL;
+ error = dest9->getSurfaceLevel(GL_TEXTURE_2D, i, true, &dstSurf);
+ if (error.isError())
+ {
+ SafeRelease(srcSurf);
+ return error;
+ }
+
+ error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged());
+
+ SafeRelease(srcSurf);
+ SafeRelease(dstSurf);
+
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+TextureStorage9_EGLImage::TextureStorage9_EGLImage(Renderer9 *renderer,
+ EGLImageD3D *image,
+ RenderTarget9 *renderTarget9)
+ : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET), 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()
+{
+}
+
+gl::Error TextureStorage9_EGLImage::getSurfaceLevel(GLenum target,
+ int level,
+ bool,
+ IDirect3DSurface9 **outSurface)
+{
+ ASSERT(target == GL_TEXTURE_2D);
+ ASSERT(level == 0);
+
+ RenderTargetD3D *renderTargetD3D = nullptr;
+ gl::Error error = mImage->getRenderTarget(&renderTargetD3D);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
+
+ *outSurface = renderTarget9->getSurface();
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage9_EGLImage::getRenderTarget(const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(!index.hasLayer());
+ ASSERT(index.mipIndex == 0);
+
+ return mImage->getRenderTarget(outRT);
+}
+
+gl::Error TextureStorage9_EGLImage::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
+{
+ RenderTargetD3D *renderTargetD3D = nullptr;
+ gl::Error error = mImage->getRenderTarget(&renderTargetD3D);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
+ *outTexture = renderTarget9->getTexture();
+ ASSERT(*outTexture != nullptr);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage9_EGLImage::generateMipmap(const gl::ImageIndex &, const gl::ImageIndex &)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+ ASSERT(getLevelCount() == 1);
+
+ TextureStorage9 *dest9 = GetAs<TextureStorage9>(destStorage);
+
+ IDirect3DBaseTexture9 *destBaseTexture9 = nullptr;
+ gl::Error error = dest9->getBaseTexture(&destBaseTexture9);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IDirect3DTexture9 *destTexture9 = static_cast<IDirect3DTexture9 *>(destBaseTexture9);
+
+ IDirect3DSurface9 *destSurface = nullptr;
+ HRESULT result = destTexture9->GetSurfaceLevel(destStorage->getTopLevel(), &destSurface);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to get the surface from a texture, result: 0x%X.", result);
+ }
+
+ RenderTargetD3D *sourceRenderTarget = nullptr;
+ error = mImage->getRenderTarget(&sourceRenderTarget);
+ if (error.isError())
+ {
+ SafeRelease(destSurface);
+ return error;
+ }
+
+ RenderTarget9 *sourceRenderTarget9 = GetAs<RenderTarget9>(sourceRenderTarget);
+ error =
+ mRenderer->copyToRenderTarget(destSurface, sourceRenderTarget9->getSurface(), isManaged());
+ if (error.isError())
+ {
+ SafeRelease(destSurface);
+ return error;
+ }
+
+ if (destStorage->getTopLevel() != 0)
+ {
+ destTexture9->AddDirtyRect(nullptr);
+ }
+
+ SafeRelease(destSurface);
+ return gl::Error(GL_NO_ERROR);
+}
+
+TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
+ : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
+{
+ mTexture = NULL;
+ for (size_t i = 0; i < CUBE_FACE_COUNT; ++i)
+ {
+ mRenderTarget[i] = NULL;
+ }
+
+ 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 < CUBE_FACE_COUNT; ++i)
+ {
+ SafeDelete(mRenderTarget[i]);
+ }
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+gl::Error TextureStorage9_Cube::getSurfaceLevel(GLenum target,
+ int level,
+ bool dirty,
+ IDirect3DSurface9 **outSurface)
+{
+ IDirect3DBaseTexture9 *baseTexture = NULL;
+ gl::Error error = getBaseTexture(&baseTexture);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IDirect3DCubeTexture9 *texture = static_cast<IDirect3DCubeTexture9*>(baseTexture);
+
+ D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(target);
+ HRESULT result = texture->GetCubeMapSurface(face, level, outSurface);
+
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
+ }
+
+ // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+ if (level != 0 && isManaged() && dirty)
+ {
+ texture->AddDirtyRect(face, NULL);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+{
+ ASSERT(outRT);
+ ASSERT(index.mipIndex == 0);
+ ASSERT(index.layerIndex >= 0 && static_cast<size_t>(index.layerIndex) < CUBE_FACE_COUNT);
+
+ if (mRenderTarget[index.layerIndex] == NULL && isRenderTarget())
+ {
+ IDirect3DBaseTexture9 *baseTexture = NULL;
+ gl::Error error = getBaseTexture(&baseTexture);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IDirect3DSurface9 *surface = NULL;
+ error = getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex,
+ mTopLevel + index.mipIndex, false, &surface);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ baseTexture->AddRef();
+ mRenderTarget[index.layerIndex] = new TextureRenderTarget9(
+ baseTexture, mTopLevel + index.mipIndex, surface, mInternalFormat,
+ static_cast<GLsizei>(mTextureWidth), static_cast<GLsizei>(mTextureHeight), 1, 0);
+ }
+
+ *outRT = mRenderTarget[index.layerIndex];
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
+{
+ IDirect3DSurface9 *upper = NULL;
+ gl::Error error = getSurfaceLevel(sourceIndex.type, sourceIndex.mipIndex, false, &upper);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IDirect3DSurface9 *lower = NULL;
+ error = getSurfaceLevel(destIndex.type, destIndex.mipIndex, true, &lower);
+ if (error.isError())
+ {
+ SafeRelease(upper);
+ return error;
+ }
+
+ ASSERT(upper && lower);
+ error = mRenderer->boxFilter(upper, lower);
+
+ SafeRelease(upper);
+ SafeRelease(lower);
+
+ return error;
+}
+
+gl::Error TextureStorage9_Cube::getBaseTexture(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 == NULL && 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, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube storage texture, result: 0x%X.", result);
+ }
+ }
+
+ *outTexture = mTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+
+ TextureStorage9_Cube *dest9 = GetAs<TextureStorage9_Cube>(destStorage);
+
+ int levels = getLevelCount();
+ for (int f = 0; f < static_cast<int>(CUBE_FACE_COUNT); f++)
+ {
+ for (int i = 0; i < levels; i++)
+ {
+ IDirect3DSurface9 *srcSurf = NULL;
+ gl::Error error =
+ getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IDirect3DSurface9 *dstSurf = NULL;
+ error = dest9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf);
+ if (error.isError())
+ {
+ SafeRelease(srcSurf);
+ return error;
+ }
+
+ error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged());
+
+ SafeRelease(srcSurf);
+ SafeRelease(dstSurf);
+
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
new file mode 100755
index 000000000..f0455a9b7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
@@ -0,0 +1,134 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// 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 "libANGLE/renderer/d3d/TextureStorage.h"
+#include "common/debug.h"
+
+namespace rx
+{
+class EGLImageD3D;
+class Renderer9;
+class SwapChain9;
+class RenderTargetD3D;
+class RenderTarget9;
+
+class TextureStorage9 : public TextureStorage
+{
+ public:
+ virtual ~TextureStorage9();
+
+ static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget);
+
+ D3DPOOL getPool() const;
+ DWORD getUsage() const;
+
+ virtual gl::Error getSurfaceLevel(GLenum target,
+ int level,
+ bool dirty,
+ IDirect3DSurface9 **outSurface) = 0;
+ virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) = 0;
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
+
+ virtual int getTopLevel() const;
+ virtual bool isRenderTarget() const;
+ virtual bool isManaged() const;
+ bool supportsNativeMipmapFunction() const override;
+ virtual int getLevelCount() const;
+
+ virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixelData);
+
+ protected:
+ int mTopLevel;
+ size_t mMipLevels;
+ size_t mTextureWidth;
+ size_t mTextureHeight;
+ GLenum mInternalFormat;
+ D3DFORMAT mTextureFormat;
+
+ Renderer9 *mRenderer;
+
+ TextureStorage9(Renderer9 *renderer, DWORD usage);
+
+ private:
+ const DWORD mD3DUsage;
+ const D3DPOOL mD3DPool;
+};
+
+class TextureStorage9_2D : public TextureStorage9
+{
+ public:
+ TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain);
+ TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
+ virtual ~TextureStorage9_2D();
+
+ gl::Error getSurfaceLevel(GLenum target,
+ int level,
+ bool dirty,
+ IDirect3DSurface9 **outSurface) override;
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+ virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture);
+ virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
+ virtual gl::Error copyToStorage(TextureStorage *destStorage);
+
+ private:
+ IDirect3DTexture9 *mTexture;
+ std::vector<RenderTarget9 *> mRenderTargets;
+};
+
+class TextureStorage9_EGLImage final : public TextureStorage9
+{
+ public:
+ TextureStorage9_EGLImage(Renderer9 *renderer, EGLImageD3D *image, RenderTarget9 *renderTarget9);
+ ~TextureStorage9_EGLImage() override;
+
+ gl::Error getSurfaceLevel(GLenum target,
+ int level,
+ bool dirty,
+ IDirect3DSurface9 **outSurface) override;
+ gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+ gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) override;
+ gl::Error generateMipmap(const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex) override;
+ gl::Error copyToStorage(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);
+ virtual ~TextureStorage9_Cube();
+
+ gl::Error getSurfaceLevel(GLenum target,
+ int level,
+ bool dirty,
+ IDirect3DSurface9 **outSurface) override;
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+ virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture);
+ virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
+ virtual gl::Error copyToStorage(TextureStorage *destStorage);
+
+ private:
+ static const size_t CUBE_FACE_COUNT = 6;
+
+ IDirect3DCubeTexture9 *mTexture;
+ RenderTarget9 *mRenderTarget[CUBE_FACE_COUNT];
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_
+
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h
new file mode 100755
index 000000000..28b8717e6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h
@@ -0,0 +1,29 @@
+//
+// 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/renderer/VertexArrayImpl.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+class Renderer9;
+
+class VertexArray9 : public VertexArrayImpl
+{
+ public:
+ VertexArray9(const gl::VertexArrayState &data) : VertexArrayImpl(data) {}
+
+ virtual ~VertexArray9() { }
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp
new file mode 100755
index 000000000..c5c07c348
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp
@@ -0,0 +1,165 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
+
+#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/Buffer.h"
+
+namespace rx
+{
+
+VertexBuffer9::VertexBuffer9(Renderer9 *renderer) : mRenderer(renderer)
+{
+ mVertexBuffer = NULL;
+ mBufferSize = 0;
+ mDynamicUsage = false;
+}
+
+VertexBuffer9::~VertexBuffer9()
+{
+ SafeRelease(mVertexBuffer);
+}
+
+gl::Error VertexBuffer9::initialize(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);
+
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size);
+ }
+ }
+
+ mBufferSize = size;
+ mDynamicUsage = dynamicUsage;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib,
+ GLenum currentValueType,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ unsigned int offset,
+ const uint8_t *sourceData)
+{
+ if (!mVertexBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+ }
+
+ int inputStride = static_cast<int>(gl::ComputeVertexAttributeStride(attrib));
+ int elementSize = static_cast<int>(gl::ComputeVertexAttributeTypeSize(attrib));
+
+ DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
+
+ uint8_t *mapPtr = nullptr;
+
+ auto errorOrMapSize = mRenderer->getVertexSpaceRequired(attrib, count, instances);
+ if (errorOrMapSize.isError())
+ {
+ return errorOrMapSize.getError();
+ }
+
+ unsigned int mapSize = errorOrMapSize.getResult();
+
+ HRESULT result = mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void**>(&mapPtr), lockFlags);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal vertex buffer, HRESULT: 0x%08x.", result);
+ }
+
+ const uint8_t *input = sourceData;
+
+ if (instances == 0 || attrib.divisor == 0)
+ {
+ input += inputStride * start;
+ }
+
+ gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType);
+ const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormatType);
+ bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0;
+
+ if (!needsConversion && inputStride == elementSize)
+ {
+ size_t copySize = static_cast<size_t>(count) * static_cast<size_t>(inputStride);
+ memcpy(mapPtr, input, copySize);
+ }
+ else
+ {
+ d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr);
+ }
+
+ mVertexBuffer->Unlock();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+unsigned int VertexBuffer9::getBufferSize() const
+{
+ return mBufferSize;
+}
+
+gl::Error VertexBuffer9::setBufferSize(unsigned int size)
+{
+ if (size > mBufferSize)
+ {
+ return initialize(size, mDynamicUsage);
+ }
+ else
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+gl::Error VertexBuffer9::discard()
+{
+ if (!mVertexBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+ }
+
+ void *dummy;
+ HRESULT result;
+
+ result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal buffer for discarding, HRESULT: 0x%08x", result);
+ }
+
+ result = mVertexBuffer->Unlock();
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal buffer for discarding, HRESULT: 0x%08x", result);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
+{
+ return mVertexBuffer;
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h
new file mode 100755
index 000000000..0d2d8c288
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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);
+
+ gl::Error initialize(unsigned int size, bool dynamicUsage) override;
+
+ gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib,
+ GLenum currentValueType,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ unsigned int offset,
+ const uint8_t *sourceData) override;
+
+ unsigned int getBufferSize() const override;
+ gl::Error setBufferSize(unsigned int size) override;
+ gl::Error discard() override;
+
+ IDirect3DVertexBuffer9 *getBuffer() const;
+
+ private:
+ ~VertexBuffer9() override;
+ Renderer9 *mRenderer;
+
+ IDirect3DVertexBuffer9 *mVertexBuffer;
+ unsigned int mBufferSize;
+ bool mDynamicUsage;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp
new file mode 100755
index 000000000..c2e935e71
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp
@@ -0,0 +1,255 @@
+//
+// Copyright (c) 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/VertexAttribute.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.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 = NULL;
+ mVertexDeclCache[i].lruCount = 0;
+ }
+
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mAppliedVBs[i].serial = 0;
+ }
+
+ mLastSetVDecl = NULL;
+ mInstancingEnabled = true;
+}
+
+VertexDeclarationCache::~VertexDeclarationCache()
+{
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ SafeRelease(mVertexDeclCache[i].vertexDeclaration);
+ }
+}
+
+gl::Error VertexDeclarationCache::applyDeclaration(
+ 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 || !attributes.size());
+ }
+
+ 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 == NULL);
+
+ 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_RESULT(attributes[i].computeOffset(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;
+ }
+
+ gl::VertexFormatType vertexformatType = gl::GetVertexFormatType(*attributes[i].attribute, GL_FLOAT);
+ const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexformatType);
+
+ 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 gl::Error(GL_NO_ERROR);
+ }
+ }
+
+ 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 != NULL)
+ {
+ 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);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal vertex declaration, result: 0x%X.", result);
+ }
+
+ device->SetVertexDeclaration(lastCache->vertexDeclaration);
+ mLastSetVDecl = lastCache->vertexDeclaration;
+ lastCache->lruCount = ++mMaxLru;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void VertexDeclarationCache::markStateDirty()
+{
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mAppliedVBs[i].serial = 0;
+ }
+
+ mLastSetVDecl = NULL;
+ mInstancingEnabled = true; // Forces it to be disabled when not used
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h
new file mode 100755
index 000000000..7bd7cabae
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h
@@ -0,0 +1,65 @@
+//
+// Copyright (c) 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 rx
+{
+
+class VertexDeclarationCache
+{
+ public:
+ VertexDeclarationCache();
+ ~VertexDeclarationCache();
+
+ gl::Error applyDeclaration(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];
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp
new file mode 100755
index 000000000..7cff9a117
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp
@@ -0,0 +1,659 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// 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 "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;
+
+constexpr D3DFormat::D3DFormat()
+ : pixelBytes(0),
+ blockWidth(0),
+ blockHeight(0),
+ redBits(0),
+ greenBits(0),
+ blueBits(0),
+ alphaBits(0),
+ luminanceBits(0),
+ depthBits(0),
+ stencilBits(0),
+ formatID(angle::Format::ID::NONE)
+{
+}
+
+constexpr D3DFormat::D3DFormat(GLuint bits,
+ GLuint blockWidth,
+ GLuint blockHeight,
+ GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint lumBits,
+ GLuint depthBits,
+ GLuint stencilBits,
+ Format::ID 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 constexpr D3DFormat info(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Format::ID::NONE);
+ return info;
+ }
+
+ if (format == D3DFMT_INTZ)
+ {
+ static constexpr D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 8,
+ Format::ID::D24_UNORM_S8_UINT);
+ return info;
+ }
+
+ switch (format)
+ {
+ case D3DFMT_UNKNOWN:
+ {
+ static constexpr D3DFormat info(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Format::ID::NONE);
+ return info;
+ }
+
+ case D3DFMT_L8:
+ {
+ static constexpr D3DFormat info(8, 1, 1, 0, 0, 0, 0, 8, 0, 0, Format::ID::L8_UNORM);
+ return info;
+ }
+ case D3DFMT_A8:
+ {
+ static constexpr D3DFormat info(8, 1, 1, 0, 0, 0, 8, 0, 0, 0, Format::ID::A8_UNORM);
+ return info;
+ }
+ case D3DFMT_A8L8:
+ {
+ static constexpr D3DFormat info(16, 1, 1, 0, 0, 0, 8, 8, 0, 0, Format::ID::L8A8_UNORM);
+ return info;
+ }
+
+ case D3DFMT_A4R4G4B4:
+ {
+ static constexpr D3DFormat info(16, 1, 1, 4, 4, 4, 4, 0, 0, 0,
+ Format::ID::B4G4R4A4_UNORM);
+ return info;
+ }
+ case D3DFMT_A1R5G5B5:
+ {
+ static constexpr D3DFormat info(16, 1, 1, 5, 5, 5, 1, 0, 0, 0,
+ Format::ID::B5G5R5A1_UNORM);
+ return info;
+ }
+ case D3DFMT_R5G6B5:
+ {
+ static constexpr D3DFormat info(16, 1, 1, 5, 6, 5, 0, 0, 0, 0,
+ Format::ID::R5G6B5_UNORM);
+ return info;
+ }
+ case D3DFMT_X8R8G8B8:
+ {
+ static constexpr D3DFormat info(32, 1, 1, 8, 8, 8, 0, 0, 0, 0,
+ Format::ID::B8G8R8X8_UNORM);
+ return info;
+ }
+ case D3DFMT_A8R8G8B8:
+ {
+ static constexpr D3DFormat info(32, 1, 1, 8, 8, 8, 8, 0, 0, 0,
+ Format::ID::B8G8R8A8_UNORM);
+ return info;
+ }
+
+ case D3DFMT_R16F:
+ {
+ static constexpr D3DFormat info(16, 1, 1, 16, 0, 0, 0, 0, 0, 0, Format::ID::R16_FLOAT);
+ return info;
+ }
+ case D3DFMT_G16R16F:
+ {
+ static constexpr D3DFormat info(32, 1, 1, 16, 16, 0, 0, 0, 0, 0,
+ Format::ID::R16G16_FLOAT);
+ return info;
+ }
+ case D3DFMT_A16B16G16R16F:
+ {
+ static constexpr D3DFormat info(64, 1, 1, 16, 16, 16, 16, 0, 0, 0,
+ Format::ID::R16G16B16A16_FLOAT);
+ return info;
+ }
+ case D3DFMT_R32F:
+ {
+ static constexpr D3DFormat info(32, 1, 1, 32, 0, 0, 0, 0, 0, 0, Format::ID::R32_FLOAT);
+ return info;
+ }
+ case D3DFMT_G32R32F:
+ {
+ static constexpr D3DFormat info(64, 1, 1, 32, 32, 0, 0, 0, 0, 0,
+ Format::ID::R32G32_FLOAT);
+ return info;
+ }
+ case D3DFMT_A32B32G32R32F:
+ {
+ static constexpr D3DFormat info(128, 1, 1, 32, 32, 32, 32, 0, 0, 0,
+ Format::ID::R32G32B32A32_FLOAT);
+ return info;
+ }
+
+ case D3DFMT_D16:
+ {
+ static constexpr D3DFormat info(16, 1, 1, 0, 0, 0, 0, 0, 16, 0, Format::ID::D16_UNORM);
+ return info;
+ }
+ case D3DFMT_D24S8:
+ {
+ static constexpr D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 8,
+ Format::ID::D24_UNORM_S8_UINT);
+ return info;
+ }
+ case D3DFMT_D24X8:
+ {
+ static constexpr D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 0, Format::ID::D16_UNORM);
+ return info;
+ }
+ case D3DFMT_D32:
+ {
+ static constexpr D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 32, 0, Format::ID::D32_UNORM);
+ return info;
+ }
+
+ case D3DFMT_DXT1:
+ {
+ static constexpr D3DFormat info(64, 4, 4, 0, 0, 0, 0, 0, 0, 0,
+ Format::ID::BC1_RGBA_UNORM_BLOCK);
+ return info;
+ }
+ case D3DFMT_DXT3:
+ {
+ static constexpr D3DFormat info(128, 4, 4, 0, 0, 0, 0, 0, 0, 0,
+ Format::ID::BC2_RGBA_UNORM_BLOCK);
+ return info;
+ }
+ case D3DFMT_DXT5:
+ {
+ static constexpr D3DFormat info(128, 4, 4, 0, 0, 0, 0, 0, 0, 0,
+ Format::ID::BC3_RGBA_UNORM_BLOCK);
+ return info;
+ }
+
+ default:
+ {
+ static constexpr D3DFormat defaultInfo;
+ return defaultInfo;
+ }
+ }
+}
+
+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(NULL),
+ 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 InternalFormatInitialzerMap dataInitializationMap = BuildInternalFormatInitialzerMap();
+ InternalFormatInitialzerMap::const_iterator dataInitIter = dataInitializationMap.find(internalFormat);
+ info.dataInitializerFunction = (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : NULL;
+
+ 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_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, 8> );
+ InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> );
+ InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> );
+ InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3DFMT_DXT5, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 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_L8, LoadToNative<GLubyte, 1> );
+ InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, D3DFMT_A8L8, D3DFMT_A8L8, LoadToNative<GLubyte, 2> );
+ // clang-format on
+
+ return map;
+}
+
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat)
+{
+ static const 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(NULL),
+ 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, gl::VertexFormatType vertexFormatType)
+{
+ static bool initialized = false;
+ 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;
+ }
+ }
+ }
+ }
+ initialized = true;
+ initializedDeclTypes = supportedDeclTypes;
+ }
+
+ const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType);
+
+ // Pure integer attributes only supported in ES3.0
+ ASSERT(!vertexFormat.pureInteger);
+ return formatConverters[ComputeTypeIndex(vertexFormat.type)][vertexFormat.normalized][vertexFormat.components - 1];
+}
+
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h
new file mode 100755
index 000000000..828252d33
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// 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/renderer_utils.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+
+namespace rx
+{
+
+class Renderer9;
+
+namespace d3d9
+{
+
+struct D3DFormat
+{
+ constexpr D3DFormat();
+ constexpr D3DFormat(GLuint pixelBytes,
+ GLuint blockWidth,
+ GLuint blockHeight,
+ GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint luminanceBits,
+ GLuint depthBits,
+ GLuint stencilBits,
+ angle::Format::ID 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::Format::ID formatID;
+};
+
+const D3DFormat &GetD3DFormatInfo(D3DFORMAT format);
+
+struct VertexFormat
+{
+ VertexFormat();
+
+ VertexConversionType conversionType;
+ size_t outputElementSize;
+ VertexCopyFunction copyFunction;
+ D3DDECLTYPE nativeFormat;
+ GLenum componentType;
+};
+const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, gl::VertexFormatType vertexFormatType);
+
+struct TextureFormat
+{
+ TextureFormat();
+
+ D3DFORMAT texFormat;
+ D3DFORMAT renderFormat;
+
+ InitializeTextureDataFunction dataInitializerFunction;
+
+ LoadImageFunction loadFunction;
+};
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat);
+
+}
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
new file mode 100755
index 000000000..a6e1f239d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -0,0 +1,659 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// renderer9_utils.cpp: Conversion functions and other utility routines
+// specific to the D3D9 renderer.
+
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+#include "common/mathutil.h"
+#include "common/debug.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
+#include "libANGLE/renderer/driver_utils.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_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dWrap;
+}
+
+D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
+{
+ D3DCULL cull = D3DCULL_CCW;
+ switch (cullFace)
+ {
+ case GL_FRONT:
+ cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
+ break;
+ case GL_BACK:
+ cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
+ break;
+ case GL_FRONT_AND_BACK:
+ cull = D3DCULL_NONE; // culling will be handled during draw
+ break;
+ default: UNREACHABLE();
+ }
+
+ return cull;
+}
+
+D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
+{
+ D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
+
+ switch (cubeFace)
+ {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ face = D3DCUBEMAP_FACE_POSITIVE_X;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ face = D3DCUBEMAP_FACE_NEGATIVE_X;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ face = D3DCUBEMAP_FACE_POSITIVE_Y;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ face = D3DCUBEMAP_FACE_NEGATIVE_Y;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ face = D3DCUBEMAP_FACE_POSITIVE_Z;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ 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(GLenum queryType)
+{
+ switch (queryType)
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ return D3DQUERYTYPE_OCCLUSION;
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ 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 d3d9_gl
+{
+
+unsigned int GetReservedVertexUniformVectors()
+{
+ return 3; // dx_ViewCoords, dx_ViewAdjust and dx_DepthRange.
+}
+
+unsigned int GetReservedFragmentUniformVectors()
+{
+ return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange.
+}
+
+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::GetInternalFormatInfo(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::GetInternalFormatInfo(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));
+ }
+
+ textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat));
+ }
+
+ if (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN)
+ {
+ textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
+
+ if ((formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) && !textureCaps.renderable)
+ {
+ textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
+ }
+
+ 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, NULL);
+ 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;
+ const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
+ for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat)
+ {
+ gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter,
+ currentDisplayMode.Format);
+ textureCapsMap->insert(*internalFormat, textureCaps);
+
+ maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
+
+ if (gl::GetInternalFormatInfo(*internalFormat).compressed)
+ {
+ caps->compressedTextureFormats.push_back(*internalFormat);
+ }
+ }
+
+ // 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;
+
+ const size_t MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256;
+ caps->maxVertexUniformVectors =
+ MAX_VERTEX_CONSTANT_VECTORS_D3D9 - GetReservedVertexUniformVectors();
+ caps->maxVertexUniformComponents = caps->maxVertexUniformVectors * 4;
+
+ caps->maxVertexUniformBlocks = 0;
+
+ // SM3 only supports 11 output variables, with a special 12th register for PSIZE.
+ const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 9;
+ const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 7;
+ 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->maxVertexTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS_VTF_SM3;
+ }
+ else
+ {
+ caps->maxVertexTextureImageUnits = 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->maxFragmentUniformComponents = caps->maxFragmentUniformVectors * 4;
+ caps->maxFragmentUniformBlocks = 0;
+ caps->maxFragmentInputComponents = caps->maxVertexOutputComponents;
+ caps->maxTextureImageUnits = 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->maxCombinedVertexUniformComponents = 0;
+ caps->maxCombinedFragmentUniformComponents = 0;
+ caps->maxVaryingComponents = 0;
+
+ // Aggregate shader limits
+ caps->maxVaryingVectors = caps->maxVertexOutputComponents / 4;
+ caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
+
+ // Transform feedback limits
+ caps->maxTransformFeedbackInterleavedComponents = 0;
+ caps->maxTransformFeedbackSeparateAttributes = 0;
+ caps->maxTransformFeedbackSeparateComponents = 0;
+
+ // Multisample limits
+ caps->maxSamples = maxSamples;
+
+ // GL extension support
+ extensions->setTextureExtensionSupport(*textureCapsMap);
+ extensions->elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16);
+ extensions->getProgramBinary = true;
+ extensions->rgb8rgba8 = true;
+ extensions->readFormatBGRA = true;
+ extensions->pixelBufferObject = false;
+ extensions->mapBuffer = false;
+ extensions->mapBufferRange = false;
+
+ // textureRG is emulated and not performant.
+ extensions->textureRG = false;
+
+ D3DADAPTER_IDENTIFIER9 adapterId = {};
+ if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId)))
+ {
+ // ATI cards on XP have problems with non-power-of-two textures.
+ extensions->textureNPOT = !(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->depthTextures = false;
+ }
+ }
+ else
+ {
+ extensions->textureNPOT = false;
+ }
+
+ extensions->drawBuffers = false;
+ extensions->textureStorage = true;
+
+ // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
+ extensions->textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2;
+ extensions->maxTextureAnisotropy = static_cast<GLfloat>(deviceCaps.MaxAnisotropy);
+
+ // Check occlusion query support by trying to create one
+ IDirect3DQuery9 *occlusionQuery = NULL;
+ extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery;
+ SafeRelease(occlusionQuery);
+
+ // Check event query support by trying to create one
+ IDirect3DQuery9 *eventQuery = NULL;
+ extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery;
+ SafeRelease(eventQuery);
+
+ extensions->timerQuery = false; // Unimplemented
+ extensions->disjointTimerQuery = false;
+ extensions->robustness = true;
+ extensions->blendMinMax = true;
+ extensions->framebufferBlit = true;
+ extensions->framebufferMultisample = true;
+ extensions->instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
+ extensions->packReverseRowOrder = true;
+ extensions->standardDerivatives = (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
+ extensions->shaderTextureLOD = true;
+ extensions->fragDepth = true;
+ extensions->textureUsage = true;
+ extensions->translatedShaderSource = true;
+ extensions->fboRenderMipmap = false;
+ extensions->discardFramebuffer = false; // It would be valid to set this to true, since glDiscardFramebufferEXT is just a hint
+ extensions->colorBufferFloat = false;
+ extensions->debugMarker = true;
+ extensions->eglImage = true;
+ extensions->eglImageExternal = true;
+ extensions->unpackSubimage = true;
+ extensions->packSubimage = true;
+ extensions->syncQuery = extensions->fence;
+
+ // 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;
+}
+
+}
+
+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;
+}
+
+WorkaroundsD3D GenerateWorkarounds()
+{
+ WorkaroundsD3D workarounds;
+ workarounds.mrtPerfWorkaround = true;
+ workarounds.setDataFasterThanImageUpload = false;
+ workarounds.useInstancedPointSpriteEmulation = false;
+
+ // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
+ workarounds.expandIntegerPowExpressions = true;
+
+ return workarounds;
+}
+
+} // namespace d3d9
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h
new file mode 100755
index 000000000..ff6d55fd5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h
@@ -0,0 +1,95 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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"
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace rx
+{
+class RenderTarget9;
+struct WorkaroundsD3D;
+
+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(GLenum cullFace, GLenum frontFace);
+D3DCUBEMAP_FACES ConvertCubeFace(GLenum 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(GLenum queryType);
+
+D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples);
+
+}
+
+namespace d3d9_gl
+{
+
+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
+{
+
+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;
+ }
+}
+
+WorkaroundsD3D GenerateWorkarounds();
+}
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps
new file mode 100755
index 000000000..dc357d0fa
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 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.
+//
+
+sampler2D tex : s0;
+
+uniform float4 mult : c0;
+uniform float4 add : c1;
+
+// Passthrough Pixel Shader
+// Outputs texture 0 sampled at texcoord 0.
+float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR
+{
+ return tex2D(tex, texcoord.xy);
+};
+
+// Luminance Conversion Pixel Shader
+// Performs a mad operation using the LA data from the texture with mult.xw and add.xw.
+// Returns data in the form of llla
+float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR
+{
+ return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy;
+};
+
+// RGB/A Component Mask Pixel Shader
+// Performs a mad operation using the texture's RGBA data with mult.xyzw and add.xyzw.
+// Returns data in the form of rgba
+float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR
+{
+ return tex2D(tex, texcoord.xy) * mult + add;
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs
new file mode 100755
index 000000000..3a36980b9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 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.
+//
+
+struct VS_OUTPUT
+{
+ float4 position : POSITION;
+ float4 texcoord : TEXCOORD0;
+};
+
+uniform float4 halfPixelSize : c0;
+
+// Standard Vertex Shader
+// Input 0 is the homogenous position.
+// Outputs the homogenous position as-is.
+// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right.
+// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0.
+VS_OUTPUT standardvs(in float4 position : POSITION)
+{
+ VS_OUTPUT Out;
+
+ Out.position = position + halfPixelSize;
+ Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);
+
+ return Out;
+};
+
+// Flip Y Vertex Shader
+// Input 0 is the homogenous position.
+// Outputs the homogenous position as-is.
+// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right.
+// C0.XY must be the half-pixel width and height. C0.ZW must be 0.
+VS_OUTPUT flipyvs(in float4 position : POSITION)
+{
+ VS_OUTPUT Out;
+
+ Out.position = position + halfPixelSize;
+ Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);
+
+ return Out;
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h
new file mode 100755
index 000000000..24482d755
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h
@@ -0,0 +1,84 @@
+#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/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h
new file mode 100755
index 000000000..5eb513132
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h
@@ -0,0 +1,66 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 halfPixelSize;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// halfPixelSize c0 1
+//
+
+ vs_2_0
+ def c1, 0.5, 1, 0, 0
+ dcl_position v0
+ add oPos, v0, c0
+ mad oT0, v0, c1.xxyy, c1.xxzz
+
+// approximately 2 instruction slots used
+#endif
+
+const BYTE g_vs20_flipyvs[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 36, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 87, 0,
+ 0, 0, 0, 2, 254, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 80, 0, 0, 0, 48, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 64, 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, 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, 171,
+ 171, 171, 81, 0, 0, 5,
+ 1, 0, 15, 160, 0, 0,
+ 0, 63, 0, 0, 128, 63,
+ 0, 0, 0, 0, 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, 224, 0, 0, 228, 144,
+ 1, 0, 80, 160, 1, 0,
+ 160, 160, 255, 255, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h
new file mode 100755
index 000000000..bdd25ac13
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h
@@ -0,0 +1,94 @@
+#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/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h
new file mode 100755
index 000000000..337af92ec
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h
@@ -0,0 +1,61 @@
+#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/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h
new file mode 100755
index 000000000..a83050d8c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h
@@ -0,0 +1,66 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 halfPixelSize;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// halfPixelSize c0 1
+//
+
+ vs_2_0
+ def c1, 0.5, -0.5, 1, 0
+ dcl_position v0
+ add oPos, v0, c0
+ mad oT0, v0, c1.xyzz, c1.xxww
+
+// approximately 2 instruction slots used
+#endif
+
+const BYTE g_vs20_standardvs[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 36, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 87, 0,
+ 0, 0, 0, 2, 254, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 80, 0, 0, 0, 48, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 64, 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, 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, 171,
+ 171, 171, 81, 0, 0, 5,
+ 1, 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, 224, 0, 0, 228, 144,
+ 1, 0, 164, 160, 1, 0,
+ 240, 160, 255, 255, 0, 0
+};
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/generate_shaders.bat b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/generate_shaders.bat
new file mode 100755
index 000000000..19a99ba91
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/shaders/generate_shaders.bat
@@ -0,0 +1,63 @@
+@ECHO OFF
+REM
+REM Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+REM Use of this source code is governed by a BSD-style license that can be
+REM found in the LICENSE file.
+REM
+
+PATH %PATH%;%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86;%DXSDK_DIR%\Utilities\bin\x86
+
+setlocal
+set errorCount=0
+set successCount=0
+set debug=0
+
+if "%1" == "debug" (
+ set debug=1
+)
+if "%1" == "release" (
+ set debug=0
+)
+
+:: | Input file | Entry point | Type | Output file | Debug |
+call:BuildShader Blit.vs standardvs vs_2_0 compiled\standardvs.h %debug%
+call:BuildShader Blit.vs flipyvs vs_2_0 compiled\flipyvs.h %debug%
+call:BuildShader Blit.ps passthroughps ps_2_0 compiled\passthroughps.h %debug%
+call:BuildShader Blit.ps luminanceps ps_2_0 compiled\luminanceps.h %debug%
+call:BuildShader Blit.ps componentmaskps ps_2_0 compiled\componentmaskps.h %debug%
+
+echo.
+
+if %successCount% GTR 0 (
+ echo %successCount% shaders compiled successfully.
+)
+if %errorCount% GTR 0 (
+ echo There were %errorCount% shader compilation errors.
+)
+
+endlocal
+exit /b
+
+:BuildShader
+set input=%~1
+set entry=%~2
+set type=%~3
+set output=%~4
+set debug=%~5
+
+if %debug% == 0 (
+ set "buildCMD=fxc /nologo /E %entry% /T %type% /Fh %output% %input%"
+) else (
+ set "buildCMD=fxc /nologo /Zi /Od /E %entry% /T %type% /Fh %output% %input%"
+)
+
+set error=0
+%buildCMD% || set error=1
+
+if %error% == 0 (
+ set /a successCount=%successCount%+1
+) else (
+ set /a errorCount=%errorCount%+1
+)
+
+exit /b
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h
new file mode 100755
index 000000000..aa05934bc
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h
@@ -0,0 +1,200 @@
+//
+// Copyright (c) 2002-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.
+//
+
+// 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 <limits>
+#include <cstdint>
+#include <cstddef>
+
+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;
+ }
+ }
+ }
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h b/gfx/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h
new file mode 100755
index 000000000..4893beb9a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 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_
+
+#include "angle_gl.h"
+
+#include <cstddef>
+#include <stdint.h>
+
+#include <map>
+
+namespace gl
+{
+struct FormatType;
+}
+
+namespace rx
+{
+typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth,
+ uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
+
+typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+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/src/libANGLE/renderer/driver_utils.cpp b/gfx/angle/src/libANGLE/renderer/driver_utils.cpp
new file mode 100644
index 000000000..7e7b2d8a2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/driver_utils.cpp
@@ -0,0 +1,81 @@
+//
+// Copyright (c) 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"
+
+namespace rx
+{
+// Intel
+// Referenced from https://cgit.freedesktop.org/vaapi/intel-driver/tree/src/i965_pciids.h
+namespace
+{
+// gen7
+const uint32_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 uint32_t Broadwell[] = {0x1602, 0x1606, 0x160A, 0x160B, 0x160D, 0x160E,
+ 0x1612, 0x1616, 0x161A, 0x161B, 0x161D, 0x161E,
+ 0x1622, 0x1626, 0x162A, 0x162B, 0x162D, 0x162E};
+
+const uint32_t CherryView[] = {0x22B0, 0x22B1, 0x22B2, 0x22B3};
+
+// gen9
+const uint32_t Skylake[] = {0x1902, 0x1906, 0x190A, 0x190B, 0x190E, 0x1912, 0x1913, 0x1915, 0x1916,
+ 0x1917, 0x191A, 0x191B, 0x191D, 0x191E, 0x1921, 0x1923, 0x1926, 0x1927,
+ 0x192A, 0x192B, 0x192D, 0x1932, 0x193A, 0x193B, 0x193D};
+
+const uint32_t Broxton[] = {0x0A84, 0x1A84, 0x1A85, 0x5A84, 0x5A85};
+
+// gen9p5
+const uint32_t Kabylake[] = {0x5916, 0x5913, 0x5906, 0x5926, 0x5921, 0x5915, 0x590E,
+ 0x591E, 0x5912, 0x5917, 0x5902, 0x591B, 0x593B, 0x590B,
+ 0x591A, 0x590A, 0x591D, 0x5908, 0x5923, 0x5927};
+
+} // anonymous namespace
+
+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);
+}
+
+} // namespace rx \ No newline at end of file
diff --git a/gfx/angle/src/libANGLE/renderer/driver_utils.h b/gfx/angle/src/libANGLE/renderer/driver_utils.h
new file mode 100644
index 000000000..865de73e1
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/driver_utils.h
@@ -0,0 +1,57 @@
+//
+// Copyright (c) 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 "libANGLE/angletypes.h"
+
+namespace rx
+{
+
+enum VendorID : uint32_t
+{
+ VENDOR_ID_UNKNOWN = 0x0,
+ VENDOR_ID_AMD = 0x1002,
+ VENDOR_ID_INTEL = 0x8086,
+ VENDOR_ID_NVIDIA = 0x10DE,
+ // 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,
+};
+
+inline bool IsAMD(uint32_t vendor_id)
+{
+ return vendor_id == VENDOR_ID_AMD;
+}
+
+inline bool IsIntel(uint32_t vendor_id)
+{
+ return vendor_id == VENDOR_ID_INTEL;
+}
+
+inline bool IsNvidia(uint32_t vendor_id)
+{
+ return vendor_id == VENDOR_ID_NVIDIA;
+}
+
+inline bool IsQualcomm(uint32_t vendor_id)
+{
+ return vendor_id == VENDOR_ID_QUALCOMM;
+}
+
+// Intel
+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);
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_DRIVER_UTILS_H_ \ No newline at end of file
diff --git a/gfx/angle/src/libANGLE/renderer/gen_angle_format_table.py b/gfx/angle/src/libANGLE/renderer/gen_angle_format_table.py
new file mode 100755
index 000000000..6b56bb40c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gen_angle_format_table.py
@@ -0,0 +1,272 @@
+#!/usr/bin/python
+# 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.
+#
+# gen_angle_format_table.py:
+# Code generation for ANGLE format map.
+#
+
+import angle_format
+from datetime import date
+import json
+import math
+import pprint
+import re
+import sys
+
+template_autogen_h = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}
+//
+// Copyright {copyright_year} The ANGLE Project 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.
+
+namespace angle
+{{
+
+enum class Format::ID
+{{
+{angle_format_enum}
+}};
+
+}} // namespace angle
+"""
+
+template_autogen_inl = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}
+//
+// Copyright {copyright_year} The ANGLE Project 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 = {{GL_RGBA, GL_UNSIGNED_BYTE,
+ CopyBGRA8ToRGBA8}};
+static constexpr rx::FastCopyFunctionMap BGRACopyFunctions = {{&BGRAEntry, 1}};
+static constexpr rx::FastCopyFunctionMap NoCopyFunctions;
+
+constexpr Format g_formatInfoTable[] = {{
+ // clang-format off
+ {{ Format::ID::NONE, GL_NONE, GL_NONE, nullptr, NoCopyFunctions, nullptr, GL_NONE, 0, 0, 0, 0, 0, 0 }},
+{angle_format_info_cases} // clang-format on
+}};
+
+// static
+const Format &Format::Get(ID id)
+{{
+ return g_formatInfoTable[static_cast<size_t>(id)];
+}}
+
+}} // namespace angle
+"""
+
+def get_channel_struct(angle_format):
+ if 'bits' not in angle_format or angle_format['bits'] is None:
+ return None
+ if 'BLOCK' in angle_format['id']:
+ return None
+ bits = angle_format['bits']
+ if 'D' in bits or 'S' in bits:
+ return None
+
+ if 'channelStruct' in angle_format:
+ return angle_format['channelStruct']
+
+ struct_name = ''
+ for channel in angle_format['channels']:
+ if channel == 'r':
+ struct_name += 'R{}'.format(bits['R'])
+ if channel == 'g':
+ struct_name += 'G{}'.format(bits['G'])
+ if channel == 'b':
+ struct_name += 'B{}'.format(bits['B'])
+ if channel == 'a':
+ struct_name += 'A{}'.format(bits['A'])
+ if channel == 'l':
+ struct_name += 'L{}'.format(bits['L'])
+ if angle_format['componentType'] == 'float':
+ struct_name += 'F'
+ if angle_format['componentType'] == 'int' or angle_format['componentType'] == 'snorm':
+ struct_name += 'S'
+ return struct_name
+
+def get_mip_generation_function(angle_format):
+ channel_struct = get_channel_struct(angle_format)
+ if channel_struct == None or "BLOCK" in angle_format["id"]:
+ return 'nullptr'
+ return 'GenerateMip<' + channel_struct + '>'
+
+def get_color_read_function(angle_format):
+ channel_struct = get_channel_struct(angle_format)
+ if channel_struct == None:
+ return 'nullptr'
+ component_type_map = {
+ 'uint': 'GLuint',
+ 'int': 'GLint',
+ 'unorm': 'GLfloat',
+ 'snorm': 'GLfloat',
+ 'float': 'GLfloat'
+ }
+ return 'ReadColor<' + channel_struct + ', '+ component_type_map[angle_format['componentType']] + '>'
+
+format_entry_template = """ {{ Format::ID::{id}, {glInternalFormat}, {fboImplementationInternalFormat}, {mipGenerationFunction}, {fastCopyFunctions}, {colorReadFunction}, {namedComponentType}, {R}, {G}, {B}, {A}, {D}, {S} }},
+"""
+
+def get_component_type(format_id):
+ if "SNORM" in format_id:
+ return "snorm"
+ elif "UNORM" in format_id:
+ return "unorm"
+ elif "FLOAT" in format_id:
+ return "float"
+ elif "UINT" in format_id:
+ return "uint"
+ elif "SINT" in format_id:
+ return "int"
+ elif format_id == "NONE":
+ return "none"
+ elif "SRGB" in format_id:
+ return "unorm"
+ else:
+ raise ValueError("Unknown component type for " + format_id)
+
+def get_channel_tokens(format_id):
+ r = re.compile(r'([ABDGLRS][\d]+)')
+ return filter(r.match, r.split(format_id))
+
+def get_channels(format_id):
+ channels = ''
+ tokens = get_channel_tokens(format_id)
+ if len(tokens) == 0:
+ return None
+ for token in tokens:
+ channels += token[0].lower()
+
+ return channels
+
+def get_bits(format_id):
+ bits = {}
+ tokens = get_channel_tokens(format_id)
+ if len(tokens) == 0:
+ return None
+ for token in tokens:
+ bits[token[0]] = int(token[1:])
+ return bits
+
+def get_named_component_type(component_type):
+ if component_type == "snorm":
+ return "GL_SIGNED_NORMALIZED"
+ elif component_type == "unorm":
+ return "GL_UNSIGNED_NORMALIZED"
+ elif component_type == "float":
+ return "GL_FLOAT"
+ elif component_type == "uint":
+ return "GL_UNSIGNED_INT"
+ elif component_type == "int":
+ return "GL_INT"
+ elif component_type == "none":
+ return "GL_NONE"
+ else:
+ raise ValueError("Unknown component type for " + component_type)
+
+def json_to_table_data(format_id, json, angle_to_gl):
+
+ table_data = ""
+
+ parsed = {
+ "id": format_id,
+ "fastCopyFunctions": "NoCopyFunctions",
+ }
+
+ for k, v in json.iteritems():
+ parsed[k] = v
+
+ if "glInternalFormat" not in parsed:
+ parsed["glInternalFormat"] = angle_to_gl[format_id]
+
+ if "fboImplementationInternalFormat" not in parsed:
+ parsed["fboImplementationInternalFormat"] = parsed["glInternalFormat"]
+
+ if "componentType" not in parsed:
+ parsed["componentType"] = get_component_type(format_id)
+
+ if "channels" not in parsed:
+ parsed["channels"] = get_channels(format_id)
+
+ if "bits" not in parsed:
+ parsed["bits"] = get_bits(format_id)
+
+ # Derived values.
+ parsed["mipGenerationFunction"] = get_mip_generation_function(parsed)
+ parsed["colorReadFunction"] = get_color_read_function(parsed)
+
+ for channel in "ABDGLRS":
+ if parsed["bits"] != None and channel in parsed["bits"]:
+ parsed[channel] = parsed["bits"][channel]
+ else:
+ parsed[channel] = "0"
+
+ parsed["namedComponentType"] = get_named_component_type(parsed["componentType"])
+
+ if format_id == "B8G8R8A8_UNORM":
+ parsed["fastCopyFunctions"] = "BGRACopyFunctions"
+
+ return format_entry_template.format(**parsed)
+
+def parse_angle_format_table(all_angle, json_data, angle_to_gl):
+ table_data = ''
+ for format_id in sorted(all_angle):
+ if format_id != "NONE":
+ format_info = json_data[format_id] if format_id in json_data else {}
+ table_data += json_to_table_data(format_id, format_info, angle_to_gl)
+
+ return table_data
+
+def gen_enum_string(all_angle):
+ enum_data = ' NONE'
+ for format_id in sorted(all_angle):
+ if format_id == 'NONE':
+ continue
+ enum_data += ',\n ' + format_id
+ return enum_data
+
+gl_to_angle = angle_format.load_forward_table('angle_format_map.json')
+angle_to_gl = angle_format.load_inverse_table('angle_format_map.json')
+data_source_name = 'angle_format_data.json'
+json_data = angle_format.load_json(data_source_name)
+all_angle = angle_to_gl.keys()
+
+angle_format_cases = parse_angle_format_table(
+ all_angle, json_data, angle_to_gl)
+output_cpp = template_autogen_inl.format(
+ script_name = sys.argv[0],
+ copyright_year = date.today().year,
+ angle_format_info_cases = angle_format_cases,
+ data_source_name = data_source_name)
+with open('Format_table_autogen.cpp', 'wt') as out_file:
+ out_file.write(output_cpp)
+ out_file.close()
+
+enum_data = gen_enum_string(all_angle)
+output_h = template_autogen_h.format(
+ script_name = sys.argv[0],
+ copyright_year = date.today().year,
+ angle_format_enum = enum_data,
+ data_source_name = data_source_name)
+with open('Format_ID_autogen.inl', 'wt') as out_file:
+ out_file.write(output_h)
+ out_file.close()
diff --git a/gfx/angle/src/libANGLE/renderer/gen_load_functions_table.py b/gfx/angle/src/libANGLE/renderer/gen_load_functions_table.py
new file mode 100755
index 000000000..eb3e4c5bf
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gen_load_functions_table.py
@@ -0,0 +1,191 @@
+#!/usr/bin/python
+# 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.
+#
+# gen_load_functions_table.py:
+# Code generation for the load function tables used for texture formats
+#
+
+import json, sys
+from datetime import date
+
+sys.path.append('../..')
+import angle_format
+
+template = """// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_load_functions_table.py using data from load_functions_data.json
+//
+// Copyright {copyright_year} The ANGLE Project 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();
+}}
+
+{load_functions_data}}} // namespace
+
+LoadFunctionMap GetLoadFunctionsMap(GLenum {internal_format}, Format::ID {angle_format})
+{{
+ // clang-format off
+ switch ({internal_format})
+ {{
+{switch_data}
+ default:
+ {{
+ static LoadFunctionMap emptyLoadFunctionsMap;
+ return emptyLoadFunctionsMap;
+ }}
+ }}
+ // clang-format on
+
+}} // GetLoadFunctionsMap
+
+}} // namespace angle
+"""
+
+internal_format_param = 'internalFormat'
+angle_format_param = 'angleFormat'
+angle_format_unknown = 'NONE'
+
+def load_functions_name(internal_format, angle_format):
+ return internal_format[3:] + "_to_" + angle_format
+
+def unknown_func_name(internal_format):
+ return load_functions_name(internal_format, "default")
+
+def get_load_func(func_name, type_functions):
+ snippet = "LoadImageFunctionInfo " + func_name + "(GLenum type)\n"
+ snippet += "{\n"
+ snippet += " switch (type)\n"
+ snippet += " {\n"
+ for gl_type, load_function in sorted(type_functions.iteritems()):
+ snippet += " case " + gl_type + ":\n"
+ requiresConversion = str('LoadToNative<' not in load_function).lower()
+ snippet += " return LoadImageFunctionInfo(" + load_function + ", " + requiresConversion + ");\n"
+ snippet += " default:\n"
+ snippet += " UNREACHABLE();\n"
+ snippet += " return LoadImageFunctionInfo(UnreachableLoadFunction, true);\n"
+ snippet += " }\n"
+ snippet += "}\n"
+ snippet += "\n"
+
+ return snippet
+
+def get_unknown_load_func(angle_to_type_map, internal_format):
+ assert angle_format_unknown in angle_to_type_map
+ return get_load_func(unknown_func_name(internal_format), angle_to_type_map[angle_format_unknown])
+
+def parse_json(json_data):
+ table_data = ''
+ load_functions_data = ''
+ for internal_format, angle_to_type_map in sorted(json_data.iteritems()):
+
+ s = ' '
+
+ table_data += s + 'case ' + internal_format + ':\n'
+
+ do_switch = len(angle_to_type_map) > 1 or angle_to_type_map.keys()[0] != angle_format_unknown
+
+ if do_switch:
+ table_data += s + '{\n'
+ s += ' '
+ table_data += s + 'switch (' + angle_format_param + ')\n'
+ table_data += s + '{\n'
+ s += ' '
+
+ for angle_format, type_functions in sorted(angle_to_type_map.iteritems()):
+
+ if angle_format == angle_format_unknown:
+ continue
+
+ func_name = load_functions_name(internal_format, angle_format)
+
+ # Main case statements
+ table_data += s + 'case Format::ID::' + angle_format + ':\n'
+ table_data += s + ' return ' + func_name + ';\n'
+
+ if angle_format_unknown in angle_to_type_map:
+ for gl_type, load_function in angle_to_type_map[angle_format_unknown].iteritems():
+ if gl_type not in type_functions:
+ type_functions[gl_type] = load_function
+
+ load_functions_data += get_load_func(func_name, type_functions)
+
+ if do_switch:
+ table_data += s + 'default:\n'
+
+ if angle_format_unknown in angle_to_type_map:
+ table_data += s + ' return ' + unknown_func_name(internal_format) + ';\n'
+ load_functions_data += get_unknown_load_func(angle_to_type_map, internal_format)
+ else:
+ table_data += s + ' break;\n'
+
+ if do_switch:
+ s = s[4:]
+ table_data += s + '}\n'
+ s = s[4:]
+ table_data += s + '}\n'
+
+ return table_data, load_functions_data
+
+json_data = angle_format.load_json('load_functions_data.json')
+
+switch_data, load_functions_data = parse_json(json_data)
+output = template.format(internal_format = internal_format_param,
+ angle_format = angle_format_param,
+ switch_data = switch_data,
+ load_functions_data = load_functions_data,
+ copyright_year = date.today().year)
+
+with open('load_functions_table_autogen.cpp', 'wt') as out_file:
+ out_file.write(output)
+ out_file.close()
diff --git a/gfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp
new file mode 100755
index 000000000..b181822ff
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp
@@ -0,0 +1,486 @@
+//
+// 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.
+//
+
+// BlitGL.cpp: Implements the BlitGL class, a helper for blitting textures
+
+#include "libANGLE/renderer/gl/BlitGL.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/renderer/gl/formatutilsgl.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+
+namespace
+{
+
+gl::Error CheckCompileStatus(const rx::FunctionsGL *functions, GLuint shader)
+{
+ GLint compileStatus = GL_FALSE;
+ functions->getShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
+ ASSERT(compileStatus == GL_TRUE);
+ if (compileStatus == GL_FALSE)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to compile internal blit shader.");
+ }
+
+ return gl::NoError();
+}
+
+gl::Error CheckLinkStatus(const rx::FunctionsGL *functions, GLuint program)
+{
+ GLint linkStatus = GL_FALSE;
+ functions->getProgramiv(program, GL_LINK_STATUS, &linkStatus);
+ ASSERT(linkStatus == GL_TRUE);
+ if (linkStatus == GL_FALSE)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to link internal blit program.");
+ }
+
+ return gl::NoError();
+}
+
+} // anonymous namespace
+
+namespace rx
+{
+
+BlitGL::BlitGL(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ StateManagerGL *stateManager)
+ : mFunctions(functions),
+ mWorkarounds(workarounds),
+ mStateManager(stateManager),
+ mBlitProgram(0),
+ mSourceTextureLocation(-1),
+ mScaleLocation(-1),
+ mOffsetLocation(-1),
+ mScratchFBO(0),
+ mVAO(0)
+{
+ for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
+ {
+ mScratchTextures[i] = 0;
+ }
+
+ ASSERT(mFunctions);
+ ASSERT(mStateManager);
+}
+
+BlitGL::~BlitGL()
+{
+ if (mBlitProgram != 0)
+ {
+ mStateManager->deleteProgram(mBlitProgram);
+ mBlitProgram = 0;
+ }
+
+ for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
+ {
+ if (mScratchTextures[i] != 0)
+ {
+ mStateManager->deleteTexture(mScratchTextures[i]);
+ mScratchTextures[i] = 0;
+ }
+ }
+
+ if (mScratchFBO != 0)
+ {
+ mStateManager->deleteFramebuffer(mScratchFBO);
+ mScratchFBO = 0;
+ }
+
+ if (mVAO != 0)
+ {
+ mStateManager->deleteVertexArray(mVAO);
+ mVAO = 0;
+ }
+}
+
+gl::Error BlitGL::copyImageToLUMAWorkaroundTexture(GLuint texture,
+ GLenum textureType,
+ GLenum target,
+ GLenum lumaFormat,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source)
+{
+ mStateManager->bindTexture(textureType, texture);
+
+ // Allocate the texture memory
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
+ mFunctions->texImage2D(target, static_cast<GLint>(level), internalFormat, sourceArea.width,
+ sourceArea.height, 0, internalFormatInfo.format,
+ source->getImplementationColorReadType(), nullptr);
+
+ return copySubImageToLUMAWorkaroundTexture(texture, textureType, target, lumaFormat, level,
+ gl::Offset(0, 0, 0), sourceArea, source);
+}
+
+gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture,
+ GLenum textureType,
+ GLenum target,
+ GLenum lumaFormat,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ ANGLE_TRY(initializeResources());
+
+ // Blit the framebuffer to the first scratch texture
+ const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
+
+ nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat(
+ mFunctions, mWorkarounds, source->getImplementationColorReadFormat(),
+ source->getImplementationColorReadType());
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetInternalFormatInfo(copyTexImageFormat.internalFormat);
+
+ mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
+ mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.x,
+ sourceArea.y, sourceArea.width, sourceArea.height, 0);
+
+ // Set the swizzle of the scratch texture so that the channels sample into the correct emulated
+ // LUMA channels.
+ GLint swizzle[4] = {
+ (lumaFormat == GL_ALPHA) ? GL_ALPHA : GL_RED,
+ (lumaFormat == GL_LUMINANCE_ALPHA) ? GL_ALPHA : GL_ZERO, GL_ZERO, GL_ZERO,
+ };
+ mFunctions->texParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
+
+ // Make a temporary framebuffer using the second scratch texture to render the swizzled result
+ // to.
+ mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[1]);
+ mFunctions->texImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.width,
+ sourceArea.height, 0, internalFormatInfo.format,
+ source->getImplementationColorReadType(), nullptr);
+
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
+ mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ mScratchTextures[1], 0);
+
+ // Render to the destination texture, sampling from the scratch texture
+ mStateManager->setViewport(gl::Rectangle(0, 0, sourceArea.width, sourceArea.height));
+ mStateManager->setScissorTestEnabled(false);
+ mStateManager->setDepthRange(0.0f, 1.0f);
+ mStateManager->setBlendEnabled(false);
+ mStateManager->setColorMask(true, true, true, true);
+ mStateManager->setSampleAlphaToCoverageEnabled(false);
+ mStateManager->setSampleCoverageEnabled(false);
+ mStateManager->setDepthTestEnabled(false);
+ mStateManager->setStencilTestEnabled(false);
+ mStateManager->setCullFaceEnabled(false);
+ mStateManager->setPolygonOffsetFillEnabled(false);
+ mStateManager->setRasterizerDiscardEnabled(false);
+ mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
+
+ setScratchTextureParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ setScratchTextureParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ mStateManager->activeTexture(0);
+ mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
+
+ mStateManager->useProgram(mBlitProgram);
+ mFunctions->uniform1i(mSourceTextureLocation, 0);
+ mFunctions->uniform2f(mScaleLocation, 1.0, 1.0);
+ mFunctions->uniform2f(mOffsetLocation, 0.0, 0.0);
+
+ mStateManager->bindVertexArray(mVAO, 0);
+
+ mFunctions->drawArrays(GL_TRIANGLES, 0, 3);
+
+ // Copy the swizzled texture to the destination texture
+ mStateManager->bindTexture(textureType, texture);
+ mFunctions->copyTexSubImage2D(target, static_cast<GLint>(level), destOffset.x, destOffset.y, 0,
+ 0, sourceArea.width, sourceArea.height);
+
+ // Finally orphan the scratch textures so they can be GCed by the driver.
+ orphanScratchTextures();
+
+ return gl::NoError();
+}
+
+gl::Error BlitGL::blitColorBufferWithShader(const gl::Framebuffer *source,
+ const gl::Framebuffer *dest,
+ const gl::Rectangle &sourceAreaIn,
+ const gl::Rectangle &destAreaIn,
+ GLenum filter)
+{
+ ANGLE_TRY(initializeResources());
+
+ // Normalize the destination area to have positive width and height because we will use
+ // glViewport to set it, which doesn't allow negative width or height.
+ gl::Rectangle sourceArea = sourceAreaIn;
+ gl::Rectangle destArea = destAreaIn;
+ if (destArea.width < 0)
+ {
+ destArea.x += destArea.width;
+ destArea.width = -destArea.width;
+ sourceArea.x += sourceArea.width;
+ sourceArea.width = -sourceArea.width;
+ }
+ if (destArea.height < 0)
+ {
+ destArea.y += destArea.height;
+ destArea.height = -destArea.height;
+ sourceArea.y += sourceArea.height;
+ sourceArea.height = -sourceArea.height;
+ }
+
+ const gl::FramebufferAttachment *readAttachment = source->getReadColorbuffer();
+ ASSERT(readAttachment->getSamples() <= 1);
+
+ // Compute the part of the source that will be sampled.
+ gl::Rectangle inBoundsSource;
+ {
+ gl::Extents sourceSize = readAttachment->getSize();
+ gl::Rectangle sourceBounds(0, 0, sourceSize.width, sourceSize.height);
+ gl::ClipRectangle(sourceArea, sourceBounds, &inBoundsSource);
+
+ // Note that inBoundsSource will have lost the orientation information.
+ ASSERT(inBoundsSource.width >= 0 && inBoundsSource.height >= 0);
+
+ // Early out when the sampled part is empty as the blit will be a noop,
+ // and it prevents a division by zero in later computations.
+ if (inBoundsSource.width == 0 || inBoundsSource.height == 0)
+ {
+ return gl::NoError();
+ }
+ }
+
+ // The blit will be emulated by getting the source of the blit in a texture and sampling it
+ // with CLAMP_TO_EDGE. The quad used to draw can trivially compute texture coordinates going
+ // from (0, 0) to (1, 1). These texture coordinates will need to be transformed to make two
+ // regions match:
+ // - The region of the texture representing the source framebuffer region that will be sampled
+ // - The region of the drawn quad that corresponds to non-clamped blit, this is the same as the
+ // region of the source rectangle that is inside the source attachment.
+ //
+ // These two regions, T (texture) and D (dest) are defined by their offset in texcoord space
+ // in (0, 1)^2 and their size in texcoord space in (-1, 1)^2. The size can be negative to
+ // represent the orientation of the blit.
+ //
+ // Then if P is the quad texcoord, Q the texcoord inside T, and R the texture texcoord:
+ // - Q = (P - D.offset) / D.size
+ // - Q = (R - T.offset) / T.size
+ // Hence R = (P - D.offset) / D.size * T.size - T.offset
+ // = P * (T.size / D.size) + (T.offset - D.offset * T.size / D.size)
+
+ GLuint textureId;
+ gl::Vector2 TOffset;
+ gl::Vector2 TSize;
+
+ // TODO(cwallez) once texture dirty bits are landed, reuse attached texture instead of using
+ // CopyTexImage2D
+ {
+ textureId = mScratchTextures[0];
+ TOffset = gl::Vector2(0.0, 0.0);
+ TSize = gl::Vector2(1.0, 1.0);
+ if (sourceArea.width < 0)
+ {
+ TOffset.x = 1.0;
+ TSize.x = -1.0;
+ }
+ if (sourceArea.height < 0)
+ {
+ TOffset.y = 1.0;
+ TSize.y = -1.0;
+ }
+
+ GLenum format = readAttachment->getFormat().info->internalFormat;
+ const FramebufferGL *sourceGL = GetImplAs<FramebufferGL>(source);
+ mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceGL->getFramebufferID());
+ mStateManager->bindTexture(GL_TEXTURE_2D, textureId);
+
+ mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, format, inBoundsSource.x, inBoundsSource.y,
+ inBoundsSource.width, inBoundsSource.height, 0);
+ }
+
+ // Compute normalized sampled draw quad region
+ // It is the same as the region of the source rectangle that is in bounds.
+ gl::Vector2 DOffset;
+ gl::Vector2 DSize;
+ {
+ ASSERT(sourceArea.width != 0 && sourceArea.height != 0);
+ gl::Rectangle orientedInBounds = inBoundsSource;
+ if (sourceArea.width < 0)
+ {
+ orientedInBounds.x += orientedInBounds.width;
+ orientedInBounds.width = -orientedInBounds.width;
+ }
+ if (sourceArea.height < 0)
+ {
+ orientedInBounds.y += orientedInBounds.height;
+ orientedInBounds.height = -orientedInBounds.height;
+ }
+
+ DOffset =
+ gl::Vector2(static_cast<float>(orientedInBounds.x - sourceArea.x) / sourceArea.width,
+ static_cast<float>(orientedInBounds.y - sourceArea.y) / sourceArea.height);
+ DSize = gl::Vector2(static_cast<float>(orientedInBounds.width) / sourceArea.width,
+ static_cast<float>(orientedInBounds.height) / sourceArea.height);
+ }
+
+ ASSERT(DSize.x != 0.0 && DSize.y != 0.0);
+ gl::Vector2 texCoordScale = gl::Vector2(TSize.x / DSize.x, TSize.y / DSize.y);
+ gl::Vector2 texCoordOffset = gl::Vector2(TOffset.x - DOffset.x * texCoordScale.x,
+ TOffset.y - DOffset.y * texCoordScale.y);
+
+ // Reset all the state except scissor and viewport
+ mStateManager->setDepthRange(0.0f, 1.0f);
+ mStateManager->setBlendEnabled(false);
+ mStateManager->setColorMask(true, true, true, true);
+ mStateManager->setSampleAlphaToCoverageEnabled(false);
+ mStateManager->setSampleCoverageEnabled(false);
+ mStateManager->setDepthTestEnabled(false);
+ mStateManager->setStencilTestEnabled(false);
+ mStateManager->setCullFaceEnabled(false);
+ mStateManager->setPolygonOffsetFillEnabled(false);
+ mStateManager->setRasterizerDiscardEnabled(false);
+
+ // Use the viewport to draw exactly to the destination rectangle
+ mStateManager->setViewport(destArea);
+
+ // Set uniforms
+ setScratchTextureParameter(GL_TEXTURE_MIN_FILTER, filter);
+ setScratchTextureParameter(GL_TEXTURE_MAG_FILTER, filter);
+ setScratchTextureParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ setScratchTextureParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ mStateManager->activeTexture(0);
+ mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
+
+ mStateManager->useProgram(mBlitProgram);
+ mFunctions->uniform1i(mSourceTextureLocation, 0);
+ mFunctions->uniform2f(mScaleLocation, texCoordScale.x, texCoordScale.y);
+ mFunctions->uniform2f(mOffsetLocation, texCoordOffset.x, texCoordOffset.y);
+
+ const FramebufferGL *destGL = GetImplAs<FramebufferGL>(dest);
+ mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, destGL->getFramebufferID());
+
+ mStateManager->bindVertexArray(mVAO, 0);
+ mFunctions->drawArrays(GL_TRIANGLES, 0, 3);
+
+ return gl::NoError();
+}
+
+gl::Error BlitGL::initializeResources()
+{
+ if (mBlitProgram == 0)
+ {
+ mBlitProgram = mFunctions->createProgram();
+
+ // Compile the fragment shader
+ // It uses a single, large triangle, to avoid arithmetic precision issues where fragments
+ // with the same Y coordinate don't get exactly the same interpolated texcoord Y.
+ const char *vsSource =
+ "#version 150\n"
+ "out vec2 v_texcoord;\n"
+ "uniform vec2 u_scale;\n"
+ "uniform vec2 u_offset;\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " const vec2 quad_positions[3] = vec2[3]\n"
+ " (\n"
+ " vec2(-0.5f, 0.0f),\n"
+ " vec2( 1.5f, 0.0f),\n"
+ " vec2( 0.5f, 2.0f)\n"
+ " );\n"
+ "\n"
+ " gl_Position = vec4((quad_positions[gl_VertexID] * 2.0) - 1.0, 0.0, 1.0);\n"
+ " v_texcoord = quad_positions[gl_VertexID] * u_scale + u_offset;\n"
+ "}\n";
+
+ GLuint vs = mFunctions->createShader(GL_VERTEX_SHADER);
+ mFunctions->shaderSource(vs, 1, &vsSource, nullptr);
+ mFunctions->compileShader(vs);
+ ANGLE_TRY(CheckCompileStatus(mFunctions, vs));
+
+ mFunctions->attachShader(mBlitProgram, vs);
+ mFunctions->deleteShader(vs);
+
+ // Compile the vertex shader
+ // It discards if the texcoord is outside (0, 1)^2 so the blitframebuffer workaround
+ // doesn't write when the point sampled is outside of the source framebuffer.
+ const char *fsSource =
+ "#version 150\n"
+ "uniform sampler2D u_source_texture;\n"
+ "in vec2 v_texcoord;\n"
+ "out vec4 output_color;\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " if (clamp(v_texcoord, vec2(0.0), vec2(1.0)) != v_texcoord)\n"
+ " {\n"
+ " discard;\n"
+ " }\n"
+ " output_color = texture(u_source_texture, v_texcoord);\n"
+ "}\n";
+
+ GLuint fs = mFunctions->createShader(GL_FRAGMENT_SHADER);
+ mFunctions->shaderSource(fs, 1, &fsSource, nullptr);
+ mFunctions->compileShader(fs);
+ ANGLE_TRY(CheckCompileStatus(mFunctions, fs));
+
+ mFunctions->attachShader(mBlitProgram, fs);
+ mFunctions->deleteShader(fs);
+
+ mFunctions->linkProgram(mBlitProgram);
+ ANGLE_TRY(CheckLinkStatus(mFunctions, mBlitProgram));
+
+ mSourceTextureLocation = mFunctions->getUniformLocation(mBlitProgram, "u_source_texture");
+ mScaleLocation = mFunctions->getUniformLocation(mBlitProgram, "u_scale");
+ mOffsetLocation = mFunctions->getUniformLocation(mBlitProgram, "u_offset");
+ mStateManager->useProgram(mBlitProgram);
+ }
+
+ for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
+ {
+ if (mScratchTextures[i] == 0)
+ {
+ mFunctions->genTextures(1, &mScratchTextures[i]);
+ }
+ }
+
+ if (mScratchFBO == 0)
+ {
+ mFunctions->genFramebuffers(1, &mScratchFBO);
+ }
+
+ if (mVAO == 0)
+ {
+ mFunctions->genVertexArrays(1, &mVAO);
+ }
+
+ return gl::NoError();
+}
+
+void BlitGL::orphanScratchTextures()
+{
+ for (auto texture : mScratchTextures)
+ {
+ mStateManager->bindTexture(GL_TEXTURE_2D, texture);
+ mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ nullptr);
+ }
+}
+
+void BlitGL::setScratchTextureParameter(GLenum param, GLenum value)
+{
+ for (auto texture : mScratchTextures)
+ {
+ mStateManager->bindTexture(GL_TEXTURE_2D, texture);
+ mFunctions->texParameteri(GL_TEXTURE_2D, param, value);
+ mFunctions->texParameteri(GL_TEXTURE_2D, param, value);
+ }
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/BlitGL.h b/gfx/angle/src/libANGLE/renderer/gl/BlitGL.h
new file mode 100755
index 000000000..b306ede29
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/BlitGL.h
@@ -0,0 +1,83 @@
+//
+// 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.
+//
+
+// BlitGL.h: Defines the BlitGL class, a helper for blitting textures
+
+#ifndef LIBANGLE_RENDERER_GL_BLITGL_H_
+#define LIBANGLE_RENDERER_GL_BLITGL_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+
+class FramebufferGL;
+class FunctionsGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class BlitGL : public angle::NonCopyable
+{
+ public:
+ BlitGL(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ StateManagerGL *stateManager);
+ ~BlitGL();
+
+ gl::Error copyImageToLUMAWorkaroundTexture(GLuint texture,
+ GLenum textureType,
+ GLenum target,
+ GLenum lumaFormat,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source);
+ gl::Error copySubImageToLUMAWorkaroundTexture(GLuint texture,
+ GLenum textureType,
+ GLenum target,
+ GLenum lumaFormat,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source);
+
+ gl::Error blitColorBufferWithShader(const gl::Framebuffer *source,
+ const gl::Framebuffer *dest,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLenum filter);
+
+ gl::Error initializeResources();
+
+ private:
+ void orphanScratchTextures();
+ void setScratchTextureParameter(GLenum param, GLenum value);
+
+ const FunctionsGL *mFunctions;
+ const WorkaroundsGL &mWorkarounds;
+ StateManagerGL *mStateManager;
+
+ GLuint mBlitProgram;
+ GLint mSourceTextureLocation;
+ GLint mScaleLocation;
+ GLint mOffsetLocation;
+
+ GLuint mScratchTextures[2];
+ GLuint mScratchFBO;
+
+ GLuint mVAO;
+};
+}
+
+#endif // LIBANGLE_RENDERER_GL_BLITGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp
new file mode 100755
index 000000000..a5eda6b30
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/BufferGL.cpp
@@ -0,0 +1,204 @@
+//
+// 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.
+//
+
+// BufferGL.cpp: Implements the class methods for BufferGL.
+
+#include "libANGLE/renderer/gl/BufferGL.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+namespace rx
+{
+
+// Use the GL_COPY_READ_BUFFER binding when two buffers need to be bound simultaneously.
+// GL_ELEMENT_ARRAY_BUFFER is supported on more versions but can modify the state of the currently
+// bound VAO. Two simultaneous buffer bindings are only needed for glCopyBufferSubData which also
+// adds the GL_COPY_READ_BUFFER binding.
+static const GLenum SourceBufferOperationTarget = GL_COPY_READ_BUFFER;
+
+// Use the GL_ELEMENT_ARRAY_BUFFER binding for most operations since it's available on all
+// supported GL versions and doesn't affect any current state when it changes.
+static const GLenum DestBufferOperationTarget = GL_ARRAY_BUFFER;
+
+BufferGL::BufferGL(const gl::BufferState &state,
+ const FunctionsGL *functions,
+ StateManagerGL *stateManager)
+ : BufferImpl(state),
+ mIsMapped(false),
+ mMapOffset(0),
+ mMapSize(0),
+ mShadowBufferData(!CanMapBufferForRead(functions)),
+ mShadowCopy(),
+ mBufferSize(0),
+ mFunctions(functions),
+ mStateManager(stateManager),
+ mBufferID(0)
+{
+ ASSERT(mFunctions);
+ ASSERT(mStateManager);
+
+ mFunctions->genBuffers(1, &mBufferID);
+}
+
+BufferGL::~BufferGL()
+{
+ mStateManager->deleteBuffer(mBufferID);
+ mBufferID = 0;
+}
+
+gl::Error BufferGL::setData(GLenum /*target*/, const void *data, size_t size, GLenum usage)
+{
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ mFunctions->bufferData(DestBufferOperationTarget, size, data, usage);
+
+ if (mShadowBufferData)
+ {
+ if (!mShadowCopy.resize(size))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize buffer data shadow copy.");
+ }
+
+ if (size > 0 && data != nullptr)
+ {
+ memcpy(mShadowCopy.data(), data, size);
+ }
+ }
+
+ mBufferSize = size;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error BufferGL::setSubData(GLenum /*target*/, const void *data, size_t size, size_t offset)
+{
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ mFunctions->bufferSubData(DestBufferOperationTarget, offset, size, data);
+
+ if (mShadowBufferData && size > 0)
+ {
+ memcpy(mShadowCopy.data() + offset, data, size);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error BufferGL::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
+{
+ BufferGL *sourceGL = GetAs<BufferGL>(source);
+
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ mStateManager->bindBuffer(SourceBufferOperationTarget, sourceGL->getBufferID());
+
+ mFunctions->copyBufferSubData(SourceBufferOperationTarget, DestBufferOperationTarget, sourceOffset, destOffset, size);
+
+ if (mShadowBufferData && size > 0)
+ {
+ ASSERT(sourceGL->mShadowBufferData);
+ memcpy(mShadowCopy.data() + destOffset, sourceGL->mShadowCopy.data() + sourceOffset, size);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error BufferGL::map(GLenum access, GLvoid **mapPtr)
+{
+ if (mShadowBufferData)
+ {
+ *mapPtr = mShadowCopy.data();
+ }
+ else
+ {
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ *mapPtr = mFunctions->mapBuffer(DestBufferOperationTarget, access);
+ }
+
+ mIsMapped = true;
+ mMapOffset = 0;
+ mMapSize = mBufferSize;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error BufferGL::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+{
+ if (mShadowBufferData)
+ {
+ *mapPtr = mShadowCopy.data() + offset;
+ }
+ else
+ {
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ *mapPtr = mFunctions->mapBufferRange(DestBufferOperationTarget, offset, length, access);
+ }
+
+ mIsMapped = true;
+ mMapOffset = offset;
+ mMapSize = length;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error BufferGL::unmap(GLboolean *result)
+{
+ ASSERT(result);
+ ASSERT(mIsMapped);
+
+ if (mShadowBufferData)
+ {
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ mFunctions->bufferSubData(DestBufferOperationTarget, mMapOffset, mMapSize,
+ mShadowCopy.data() + mMapOffset);
+ *result = GL_TRUE;
+ }
+ else
+ {
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+ *result = mFunctions->unmapBuffer(DestBufferOperationTarget);
+ }
+
+ mIsMapped = false;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error BufferGL::getIndexRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ gl::IndexRange *outRange)
+{
+ ASSERT(!mIsMapped);
+
+ if (mShadowBufferData)
+ {
+ *outRange = gl::ComputeIndexRange(type, mShadowCopy.data() + offset, count,
+ primitiveRestartEnabled);
+ }
+ else
+ {
+ mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+
+ const gl::Type &typeInfo = gl::GetTypeInfo(type);
+ const uint8_t *bufferData = MapBufferRangeWithFallback(
+ mFunctions, DestBufferOperationTarget, offset, count * typeInfo.bytes, GL_MAP_READ_BIT);
+ *outRange = gl::ComputeIndexRange(type, bufferData, count, primitiveRestartEnabled);
+ mFunctions->unmapBuffer(DestBufferOperationTarget);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+GLuint BufferGL::getBufferID() const
+{
+ return mBufferID;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/BufferGL.h b/gfx/angle/src/libANGLE/renderer/gl/BufferGL.h
new file mode 100755
index 000000000..d886873fe
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/BufferGL.h
@@ -0,0 +1,62 @@
+//
+// 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.
+//
+
+// BufferGL.h: Defines the class interface for BufferGL.
+
+#ifndef LIBANGLE_RENDERER_GL_BUFFERGL_H_
+#define LIBANGLE_RENDERER_GL_BUFFERGL_H_
+
+#include "common/MemoryBuffer.h"
+#include "libANGLE/renderer/BufferImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+
+class BufferGL : public BufferImpl
+{
+ public:
+ BufferGL(const gl::BufferState &state,
+ const FunctionsGL *functions,
+ StateManagerGL *stateManager);
+ ~BufferGL() override;
+
+ gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) override;
+ gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) override;
+ gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) override;
+ gl::Error map(GLenum access, GLvoid **mapPtr) override;
+ gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override;
+ gl::Error unmap(GLboolean *result) override;
+
+ gl::Error getIndexRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ gl::IndexRange *outRange) override;
+
+ GLuint getBufferID() const;
+
+ private:
+ bool mIsMapped;
+ size_t mMapOffset;
+ size_t mMapSize;
+
+ bool mShadowBufferData;
+ MemoryBuffer mShadowCopy;
+
+ size_t mBufferSize;
+
+ const FunctionsGL *mFunctions;
+ StateManagerGL *mStateManager;
+
+ GLuint mBufferID;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_BUFFERGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.cpp
new file mode 100755
index 000000000..71be15611
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.cpp
@@ -0,0 +1,91 @@
+//
+// 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.
+//
+// CompilerGL:
+// Implementation of the GL compiler methods.
+//
+
+#include "libANGLE/renderer/gl/CompilerGL.h"
+
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
+namespace rx
+{
+
+namespace
+{
+
+ShShaderOutput GetShaderOutputType(const FunctionsGL *functions)
+{
+ ASSERT(functions);
+
+ if (functions->standard == STANDARD_GL_DESKTOP)
+ {
+ // GLSL outputs
+ if (functions->isAtLeastGL(gl::Version(4, 5)))
+ {
+ return SH_GLSL_450_CORE_OUTPUT;
+ }
+ else if (functions->isAtLeastGL(gl::Version(4, 4)))
+ {
+ return SH_GLSL_440_CORE_OUTPUT;
+ }
+ else if (functions->isAtLeastGL(gl::Version(4, 3)))
+ {
+ return SH_GLSL_430_CORE_OUTPUT;
+ }
+ else if (functions->isAtLeastGL(gl::Version(4, 2)))
+ {
+ return SH_GLSL_420_CORE_OUTPUT;
+ }
+ else if (functions->isAtLeastGL(gl::Version(4, 1)))
+ {
+ return SH_GLSL_410_CORE_OUTPUT;
+ }
+ else if (functions->isAtLeastGL(gl::Version(4, 0)))
+ {
+ return SH_GLSL_400_CORE_OUTPUT;
+ }
+ else if (functions->isAtLeastGL(gl::Version(3, 3)))
+ {
+ return SH_GLSL_330_CORE_OUTPUT;
+ }
+ else if (functions->isAtLeastGL(gl::Version(3, 2)))
+ {
+ return SH_GLSL_150_CORE_OUTPUT;
+ }
+ else if (functions->isAtLeastGL(gl::Version(3, 1)))
+ {
+ return SH_GLSL_140_OUTPUT;
+ }
+ else if (functions->isAtLeastGL(gl::Version(3, 0)))
+ {
+ return SH_GLSL_130_OUTPUT;
+ }
+ else
+ {
+ return SH_GLSL_COMPATIBILITY_OUTPUT;
+ }
+ }
+ else if (functions->standard == STANDARD_GL_ES)
+ {
+ // ESSL outputs
+ return SH_ESSL_OUTPUT;
+ }
+ else
+ {
+ UNREACHABLE();
+ return ShShaderOutput(0);
+ }
+}
+
+} // anonymous namespace
+
+CompilerGL::CompilerGL(const FunctionsGL *functions)
+ : mTranslatorOutputType(GetShaderOutputType(functions))
+{
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.h b/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.h
new file mode 100755
index 000000000..eadbf67ed
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/CompilerGL.h
@@ -0,0 +1,33 @@
+//
+// 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.
+//
+
+// CompilerGL.h: Defines the class interface for CompilerGL.
+
+#ifndef LIBANGLE_RENDERER_GL_COMPILERGL_H_
+#define LIBANGLE_RENDERER_GL_COMPILERGL_H_
+
+#include "libANGLE/renderer/CompilerImpl.h"
+
+namespace rx
+{
+class FunctionsGL;
+
+class CompilerGL : public CompilerImpl
+{
+ public:
+ CompilerGL(const FunctionsGL *functions);
+ ~CompilerGL() override {}
+
+ gl::Error release() override { return gl::Error(GL_NO_ERROR); }
+ ShShaderOutput getTranslatorOutputType() const override { return mTranslatorOutputType; }
+
+ private:
+ ShShaderOutput mTranslatorOutputType;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_COMPILERGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/ContextGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/ContextGL.cpp
new file mode 100755
index 000000000..8e378a4be
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/ContextGL.cpp
@@ -0,0 +1,370 @@
+//
+// 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.
+//
+// ContextGL:
+// OpenGL-specific functionality associated with a GL Context.
+//
+
+#include "libANGLE/renderer/gl/ContextGL.h"
+
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/CompilerGL.h"
+#include "libANGLE/renderer/gl/FenceNVGL.h"
+#include "libANGLE/renderer/gl/FenceSyncGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/PathGL.h"
+#include "libANGLE/renderer/gl/ProgramGL.h"
+#include "libANGLE/renderer/gl/QueryGL.h"
+#include "libANGLE/renderer/gl/RenderbufferGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/SamplerGL.h"
+#include "libANGLE/renderer/gl/ShaderGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
+#include "libANGLE/renderer/gl/VertexArrayGL.h"
+
+namespace rx
+{
+
+ContextGL::ContextGL(const gl::ContextState &state, RendererGL *renderer)
+ : ContextImpl(state), mRenderer(renderer)
+{
+}
+
+ContextGL::~ContextGL()
+{
+}
+
+gl::Error ContextGL::initialize()
+{
+ return gl::NoError();
+}
+
+CompilerImpl *ContextGL::createCompiler()
+{
+ return new CompilerGL(getFunctions());
+}
+
+ShaderImpl *ContextGL::createShader(const gl::ShaderState &data)
+{
+ return new ShaderGL(data, getFunctions(), getWorkaroundsGL());
+}
+
+ProgramImpl *ContextGL::createProgram(const gl::ProgramState &data)
+{
+ return new ProgramGL(data, getFunctions(), getWorkaroundsGL(), getStateManager(),
+ getExtensions().pathRendering);
+}
+
+FramebufferImpl *ContextGL::createFramebuffer(const gl::FramebufferState &data)
+{
+ return new FramebufferGL(data, getFunctions(), getStateManager(), getWorkaroundsGL(),
+ mRenderer->getBlitter(), false);
+}
+
+TextureImpl *ContextGL::createTexture(const gl::TextureState &state)
+{
+ return new TextureGL(state, getFunctions(), getWorkaroundsGL(), getStateManager(),
+ mRenderer->getBlitter());
+}
+
+RenderbufferImpl *ContextGL::createRenderbuffer()
+{
+ return new RenderbufferGL(getFunctions(), getWorkaroundsGL(), getStateManager(),
+ getNativeTextureCaps());
+}
+
+BufferImpl *ContextGL::createBuffer(const gl::BufferState &state)
+{
+ return new BufferGL(state, getFunctions(), getStateManager());
+}
+
+VertexArrayImpl *ContextGL::createVertexArray(const gl::VertexArrayState &data)
+{
+ return new VertexArrayGL(data, getFunctions(), getStateManager());
+}
+
+QueryImpl *ContextGL::createQuery(GLenum type)
+{
+ return new QueryGL(type, getFunctions(), getStateManager());
+}
+
+FenceNVImpl *ContextGL::createFenceNV()
+{
+ return new FenceNVGL(getFunctions());
+}
+
+FenceSyncImpl *ContextGL::createFenceSync()
+{
+ return new FenceSyncGL(getFunctions());
+}
+
+TransformFeedbackImpl *ContextGL::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+ return new TransformFeedbackGL(state, getFunctions(), getStateManager());
+}
+
+SamplerImpl *ContextGL::createSampler()
+{
+ return new SamplerGL(getFunctions(), getStateManager());
+}
+
+std::vector<PathImpl *> ContextGL::createPaths(GLsizei range)
+{
+ const FunctionsGL *funcs = getFunctions();
+
+ std::vector<PathImpl *> ret;
+ ret.reserve(range);
+
+ const GLuint first = funcs->genPathsNV(range);
+ if (first == 0)
+ return ret;
+
+ for (GLsizei i = 0; i < range; ++i)
+ {
+ const auto id = first + i;
+ ret.push_back(new PathGL(funcs, id));
+ }
+
+ return ret;
+}
+
+gl::Error ContextGL::flush()
+{
+ return mRenderer->flush();
+}
+
+gl::Error ContextGL::finish()
+{
+ return mRenderer->finish();
+}
+
+gl::Error ContextGL::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ return mRenderer->drawArrays(mState, mode, first, count);
+}
+
+gl::Error ContextGL::drawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ return mRenderer->drawArraysInstanced(mState, mode, first, count, instanceCount);
+}
+
+gl::Error ContextGL::drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange)
+{
+ return mRenderer->drawElements(mState, mode, count, type, indices, indexRange);
+}
+
+gl::Error ContextGL::drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange)
+{
+ return mRenderer->drawElementsInstanced(mState, mode, count, type, indices, instances,
+ indexRange);
+}
+
+gl::Error ContextGL::drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange)
+{
+ return mRenderer->drawRangeElements(mState, mode, start, end, count, type, indices, indexRange);
+}
+
+void ContextGL::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
+{
+ mRenderer->stencilFillPath(mState, path, fillMode, mask);
+}
+
+void ContextGL::stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask)
+{
+ mRenderer->stencilStrokePath(mState, path, reference, mask);
+}
+
+void ContextGL::coverFillPath(const gl::Path *path, GLenum coverMode)
+{
+ mRenderer->coverFillPath(mState, path, coverMode);
+}
+
+void ContextGL::coverStrokePath(const gl::Path *path, GLenum coverMode)
+{
+ mRenderer->coverStrokePath(mState, path, coverMode);
+}
+
+void ContextGL::stencilThenCoverFillPath(const gl::Path *path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode)
+{
+ mRenderer->stencilThenCoverFillPath(mState, path, fillMode, mask, coverMode);
+}
+
+void ContextGL::stencilThenCoverStrokePath(const gl::Path *path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode)
+{
+ mRenderer->stencilThenCoverStrokePath(mState, path, reference, mask, coverMode);
+}
+
+void ContextGL::coverFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ mRenderer->coverFillPathInstanced(mState, paths, coverMode, transformType, transformValues);
+}
+
+void ContextGL::coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ mRenderer->coverStrokePathInstanced(mState, paths, coverMode, transformType, transformValues);
+}
+
+void ContextGL::stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ mRenderer->stencilFillPathInstanced(mState, paths, fillMode, mask, transformType,
+ transformValues);
+}
+
+void ContextGL::stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ mRenderer->stencilStrokePathInstanced(mState, paths, reference, mask, transformType,
+ transformValues);
+}
+
+void ContextGL::stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ mRenderer->stencilThenCoverFillPathInstanced(mState, paths, coverMode, fillMode, mask,
+ transformType, transformValues);
+}
+
+void ContextGL::stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ mRenderer->stencilThenCoverStrokePathInstanced(mState, paths, coverMode, reference, mask,
+ transformType, transformValues);
+}
+
+GLenum ContextGL::getResetStatus()
+{
+ return mRenderer->getResetStatus();
+}
+
+std::string ContextGL::getVendorString() const
+{
+ return mRenderer->getVendorString();
+}
+
+std::string ContextGL::getRendererDescription() const
+{
+ return mRenderer->getRendererDescription();
+}
+
+void ContextGL::insertEventMarker(GLsizei length, const char *marker)
+{
+ mRenderer->insertEventMarker(length, marker);
+}
+
+void ContextGL::pushGroupMarker(GLsizei length, const char *marker)
+{
+ mRenderer->pushGroupMarker(length, marker);
+}
+
+void ContextGL::popGroupMarker()
+{
+ mRenderer->popGroupMarker();
+}
+
+void ContextGL::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
+{
+ mRenderer->getStateManager()->syncState(state, dirtyBits);
+}
+
+GLint ContextGL::getGPUDisjoint()
+{
+ return mRenderer->getGPUDisjoint();
+}
+
+GLint64 ContextGL::getTimestamp()
+{
+ return mRenderer->getTimestamp();
+}
+
+void ContextGL::onMakeCurrent(const gl::ContextState &data)
+{
+ // Queries need to be paused/resumed on context switches
+ mRenderer->getStateManager()->onMakeCurrent(data);
+}
+
+const gl::Caps &ContextGL::getNativeCaps() const
+{
+ return mRenderer->getNativeCaps();
+}
+
+const gl::TextureCapsMap &ContextGL::getNativeTextureCaps() const
+{
+ return mRenderer->getNativeTextureCaps();
+}
+
+const gl::Extensions &ContextGL::getNativeExtensions() const
+{
+ return mRenderer->getNativeExtensions();
+}
+
+const gl::Limitations &ContextGL::getNativeLimitations() const
+{
+ return mRenderer->getNativeLimitations();
+}
+
+const FunctionsGL *ContextGL::getFunctions() const
+{
+ return mRenderer->getFunctions();
+}
+
+StateManagerGL *ContextGL::getStateManager()
+{
+ return mRenderer->getStateManager();
+}
+
+const WorkaroundsGL &ContextGL::getWorkaroundsGL()
+{
+ return mRenderer->getWorkarounds();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/ContextGL.h b/gfx/angle/src/libANGLE/renderer/gl/ContextGL.h
new file mode 100755
index 000000000..b3d5e0ee8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/ContextGL.h
@@ -0,0 +1,183 @@
+//
+// 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.
+//
+// ContextGL:
+// OpenGL-specific functionality associated with a GL Context.
+//
+
+#ifndef LIBANGLE_RENDERER_GL_CONTEXTGL_H_
+#define LIBANGLE_RENDERER_GL_CONTEXTGL_H_
+
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace sh
+{
+struct BlockMemberInfo;
+}
+
+namespace rx
+{
+class FunctionsGL;
+class RendererGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class ContextGL : public ContextImpl
+{
+ public:
+ ContextGL(const gl::ContextState &state, RendererGL *renderer);
+ ~ContextGL() override;
+
+ gl::Error initialize() 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() 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(GLenum type) override;
+ FenceNVImpl *createFenceNV() override;
+ FenceSyncImpl *createFenceSync() override;
+
+ // Transform Feedback creation
+ TransformFeedbackImpl *createTransformFeedback(
+ const gl::TransformFeedbackState &state) override;
+
+ // Sampler object creation
+ SamplerImpl *createSampler() override;
+
+ // Path object creation
+ std::vector<PathImpl *> createPaths(GLsizei range) override;
+
+ // Flush and finish.
+ gl::Error flush() override;
+ gl::Error finish() override;
+
+ // Drawing methods.
+ gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override;
+ gl::Error drawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) override;
+
+ gl::Error drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange) override;
+ gl::Error drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange) override;
+ gl::Error drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange) override;
+
+ // CHROMIUM_path_rendering implementation
+ void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) override;
+ void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask) override;
+ void coverFillPath(const gl::Path *path, GLenum coverMode) override;
+ void coverStrokePath(const gl::Path *path, GLenum coverMode) override;
+ void stencilThenCoverFillPath(const gl::Path *path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode) override;
+ void stencilThenCoverStrokePath(const gl::Path *path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode) override;
+ void coverFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues) override;
+ void coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues) override;
+ void stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues) override;
+ void stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues) override;
+ void stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues) override;
+ void stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues) override;
+
+ // Device loss
+ GLenum getResetStatus() override;
+
+ // Vendor and description strings.
+ std::string getVendorString() const override;
+ std::string getRendererDescription() const override;
+
+ // Debug markers.
+ void insertEventMarker(GLsizei length, const char *marker) override;
+ void pushGroupMarker(GLsizei length, const char *marker) override;
+ void popGroupMarker() override;
+
+ // State sync with dirty bits.
+ void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) override;
+
+ // Disjoint timer queries
+ GLint getGPUDisjoint() override;
+ GLint64 getTimestamp() override;
+
+ // Context switching
+ void onMakeCurrent(const gl::ContextState &data) override;
+
+ // Caps queries
+ const gl::Caps &getNativeCaps() const override;
+ const gl::TextureCapsMap &getNativeTextureCaps() const override;
+ const gl::Extensions &getNativeExtensions() const override;
+ const gl::Limitations &getNativeLimitations() const override;
+
+ // Handle helpers
+ const FunctionsGL *getFunctions() const;
+ StateManagerGL *getStateManager();
+ const WorkaroundsGL &getWorkaroundsGL();
+
+ private:
+ RendererGL *mRenderer;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_CONTEXTGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/DisplayGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/DisplayGL.cpp
new file mode 100755
index 000000000..30c5c7b4e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/DisplayGL.cpp
@@ -0,0 +1,103 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayGL.h: GL implementation of egl::Display
+
+#include "libANGLE/renderer/gl/DisplayGL.h"
+
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/ContextGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <EGL/eglext.h>
+
+namespace rx
+{
+
+DisplayGL::DisplayGL() : mRenderer(nullptr), mCurrentDrawSurface(nullptr)
+{
+}
+
+DisplayGL::~DisplayGL()
+{
+}
+
+egl::Error DisplayGL::initialize(egl::Display *display)
+{
+ mRenderer = new RendererGL(getFunctionsGL(), display->getAttributeMap());
+
+ const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion();
+ if (maxVersion < gl::Version(2, 0))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "OpenGL ES 2.0 is not supportable.");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayGL::terminate()
+{
+ SafeDelete(mRenderer);
+}
+
+ImageImpl *DisplayGL::createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+ContextImpl *DisplayGL::createContext(const gl::ContextState &state)
+{
+ ASSERT(mRenderer != nullptr);
+ return new ContextGL(state, mRenderer);
+}
+
+StreamProducerImpl *DisplayGL::createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+egl::Error DisplayGL::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
+{
+ // Notify the previous surface (if it still exists) that it is no longer current
+ if (mCurrentDrawSurface && mSurfaceSet.find(mCurrentDrawSurface) != mSurfaceSet.end())
+ {
+ ANGLE_TRY(GetImplAs<SurfaceGL>(mCurrentDrawSurface)->unMakeCurrent());
+ }
+ mCurrentDrawSurface = nullptr;
+
+ if (!drawSurface)
+ {
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ // Pause transform feedback before making a new surface current, to workaround anglebug.com/1426
+ ContextGL *glContext = GetImplAs<ContextGL>(context);
+ glContext->getStateManager()->pauseTransformFeedback(context->getContextState());
+
+ SurfaceGL *glDrawSurface = GetImplAs<SurfaceGL>(drawSurface);
+ ANGLE_TRY(glDrawSurface->makeCurrent());
+ mCurrentDrawSurface = drawSurface;
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+gl::Version DisplayGL::getMaxSupportedESVersion() const
+{
+ ASSERT(mRenderer != nullptr);
+ return mRenderer->getMaxSupportedESVersion();
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/DisplayGL.h b/gfx/angle/src/libANGLE/renderer/gl/DisplayGL.h
new file mode 100755
index 000000000..a63da6bbc
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/DisplayGL.h
@@ -0,0 +1,62 @@
+//
+// 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.
+//
+
+// DisplayGL.h: Defines the class interface for DisplayGL.
+
+#ifndef LIBANGLE_RENDERER_GL_DISPLAYGL_H_
+#define LIBANGLE_RENDERER_GL_DISPLAYGL_H_
+
+#include "libANGLE/renderer/DisplayImpl.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
+namespace egl
+{
+class Surface;
+}
+
+namespace rx
+{
+
+class RendererGL;
+
+class DisplayGL : public DisplayImpl
+{
+ public:
+ DisplayGL();
+ ~DisplayGL() override;
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ ImageImpl *createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs) override;
+
+ ContextImpl *createContext(const gl::ContextState &state) override;
+
+ StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) override;
+
+ egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override;
+
+ virtual egl::Error getDriverVersion(std::string *version) const = 0;
+ gl::Version getMaxSupportedESVersion() const override;
+
+ protected:
+ RendererGL *getRenderer() const { return mRenderer; };
+
+ private:
+ virtual const FunctionsGL *getFunctionsGL() const = 0;
+
+ RendererGL *mRenderer;
+
+ egl::Surface *mCurrentDrawSurface;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_DISPLAYGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/FeatureSupportGL.md b/gfx/angle/src/libANGLE/renderer/gl/FeatureSupportGL.md
new file mode 100755
index 000000000..edc2353ab
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/FeatureSupportGL.md
@@ -0,0 +1,107 @@
+# ANGLE RendererGL feature support
+Documentation of OpenGL ES and EGL features, caps and formats and required extensions.
+
+## OpenGL ES Feature Support
+|Feature|OpenGL version|OpenGL extension|OpenGL ES version|OpenGL ES extension|Notes|
+|---|---|---|---|---|---|
+|Framebuffer/renderbuffer objects|3.0|[GL_EXT_framebuffer_object](https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt)|2.0|--|Can potentially be emulated with Pbuffers but realistically this extension is always required.|
+|Blit framebuffer|3.0|[GL_EXT_framebuffer_blit](https://www.opengl.org/registry/specs/EXT/framebuffer_blit.txt)|3.0|[GL_ANGLE_framebuffer_blit](https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_framebuffer_blit.txt) or [GL_NV_framebuffer_blit](https://www.khronos.org/registry/gles/extensions/NV/NV_framebuffer_blit.txt)||
+|Multisampling|3.0|[GL_EXT_framebuffer_multisample](https://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt)|3.0|[GL_EXT_multisampled_render_to_texture](https://www.khronos.org/registry/gles/extensions/EXT/EXT_multisampled_render_to_texture.txt) or [GL_ANGLE_framebuffer_multisample](https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_framebuffer_multisample.txt)||
+|Depth textures|3.0|[GL_ARB_depth_texture](https://www.opengl.org/registry/specs/ARB/depth_texture.txt)|3.0|[GL_OES_depth_texture](https://www.khronos.org/registry/gles/extensions/OES/OES_depth_texture.txt) or [GL_ANGLE_depth_texture](https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_depth_texture.txt)
+|Draw buffers (MRT)|2.0?|[GL_ARB_draw_buffers](https://www.opengl.org/registry/specs/ARB/draw_buffers.txt) or [GL_EXT_draw_buffers2](https://www.opengl.org/registry/specs/EXT/draw_buffers2.txt)|3.0|[GL_EXT_draw_buffers](https://www.khronos.org/registry/gles/extensions/EXT/EXT_draw_buffers.txt)||
+|3D textures|1.2|[GL_EXT_texture3D](https://www.opengl.org/registry/specs/EXT/texture3D.txt)|3.0|[GL_OES_texture_3D](https://www.khronos.org/registry/gles/extensions/OES/OES_texture_3D.txt)||
+|Array textures|3.0|[GL_EXT_texture_array](https://www.opengl.org/registry/specs/EXT/texture_array.txt)|3.0|--||
+|Texture storage|4.2|[GL_EXT_texture_storage](https://www.khronos.org/registry/gles/extensions/EXT/EXT_texture_storage.txt)|3.0|[GL_EXT_texture_storage](https://www.khronos.org/registry/gles/extensions/EXT/EXT_texture_storage.txt)|Can be emulated with TexImage calls.|
+|Uniform buffer object|3.1|[GL_ARB_uniform_buffer_object](https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt)|3.0|--||
+|Sync objects|3.2|[GL_ARB_sync](https://www.opengl.org/registry/specs/ARB/sync.txt)|3.0|--||
+|Fence objects|--|[GL_NV_fence](https://www.opengl.org/registry/specs/NV/fence.txt)|--|[GL_NV_fence](https://www.opengl.org/registry/specs/NV/fence.txt)||
+|MapBuffer|1.5|--|--|[GL_OES_mapbuffer](https://www.khronos.org/registry/gles/extensions/OES/OES_mapbuffer.txt)||
+|MapBufferRange|3.0|[GL_ARB_map_buffer_range](https://www.opengl.org/registry/specs/ARB/map_buffer_range.txt)|3.0|[GL_EXT_map_buffer_range](https://www.khronos.org/registry/gles/extensions/EXT/EXT_map_buffer_range.txt)||
+|Transform feedback|3.0|[GL_EXT_transform_feedback](GL_EXT_transform_feedback) or [GL_EXT_transform_feedback2](http://developer.download.nvidia.com/opengl/specs/GL_EXT_transform_feedback2.txt) or [GL_ARB_transform_feedback3](https://www.opengl.org/registry/specs/ARB/transform_feedback3.txt)|3.0|--||
+|Sampler object|3.3|[GL_ARB_sampler_objects](https://www.opengl.org/registry/specs/ARB/sampler_objects.txt)|3.0|--||
+|Occlusion query|1.5|[GL_ARB_occlusion_query](https://www.opengl.org/registry/specs/ARB/occlusion_query.txt)|2.0|--||
+|Timer query|3.3|[GL_ARB_timer_query](https://www.opengl.org/registry/specs/ARB/timer_query.txt)|--|[GL_EXT_disjoint_timer_query](https://www.khronos.org/registry/gles/extensions/EXT/EXT_disjoint_timer_query.txt)||
+|Vertex array object|3.0|[GL_ARB_vertex_array_object](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt)|3.0|[GL_OES_vertex_array_object](https://www.khronos.org/registry/gles/extensions/OES/OES_vertex_array_object.txt)|Can be emulated but costsmany extra API calls. Virtualized contexts also require some kind of emulation of the default attribute state.|
+|Anisotropic filtering|--|[GL_EXT_texture_filter_anisotropic](https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt)|--|[GL_EXT_texture_filter_anisotropic](https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt)|Ubiquitous extension.|
+
+## OpenGL ES Caps
+|Cap(s)|OpenGL version|OpenGL extension|OpenGL ES version|OpenGL ES extension|Notes|
+|---|---|---|---|---|---|
+|GL_MAX_ELEMENT_INDEX|4.3|[GL_ARB_ES3_compatibility](https://www.opengl.org/registry/specs/ARB/ES3_compatibility.txt)|3.0|--|Seems pretty safe to use an arbitrary limit, all implementations tested return 0xFFFFFFFF.|
+|GL_MAX_3D_TEXTURE_SIZE|1.2|[GL_EXT_texture3D](https://www.opengl.org/registry/specs/EXT/texture3D.txt)|3.0|[GL_OES_texture_3D](https://www.khronos.org/registry/gles/extensions/OES/OES_texture_3D.txt)||
+|GL_MAX_TEXTURE_SIZE|1.0|--|2.0|--||
+|GL_MAX_CUBE_MAP_TEXTURE_SIZE|1.3|--|2.0||
+|GL_MAX_ARRAY_TEXTURE_LAYERS|3.0|[GL_EXT_texture_array](https://www.opengl.org/registry/specs/EXT/texture_array.txt)|3.0|--||
+|GL_MAX_TEXTURE_LOD_BIAS|1.5|[GL_EXT_texture_lod_bias](https://www.opengl.org/registry/specs/EXT/texture_lod_bias.txt)|3.0|--||
+|GL_MAX_RENDERBUFFER_SIZE GL_MAX_COLOR_ATTACHMENTS|3.0|[GL_EXT_framebuffer_object](https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt) |2.0|--||
+|GL_MAX_DRAW_BUFFERS|2.0?|[GL_ARB_draw_buffers](https://www.opengl.org/registry/specs/ARB/draw_buffers.txt) or [GL_EXT_draw_buffers2](https://www.opengl.org/registry/specs/EXT/draw_buffers2.txt)|3.0|[GL_EXT_draw_buffers](https://www.khronos.org/registry/gles/extensions/EXT/EXT_draw_buffers.txt)||
+|GL_MAX_VIEWPORT_DIMS|1.0|--|2.0|--||
+|GL_ALIASED_POINT_SIZE_RANGE|1.0?|--|2.0|--||
+|GL_ALIASED_LINE_WIDTH_RANGE|1.2|--|2.0|--||
+|GL_ALIASED_LINE_WIDTH_RANGE|1.2|--|2.0|--||
+|GL_MAX_ELEMENTS_INDICES|1.2|--|3.0|--||
+|GL_MAX_ELEMENTS_VERTICES|1.2|--|3.0|--||
+|Shader format precision (glGetShaderPrecisionFormat)|4.1|[GL_ARB_ES2_compatibility](https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt)|2.0|--|Can use reasonable default values (IEEE float and twos complement integer).|
+|GL_MAX_VERTEX_ATTRIBS|2.0|--|2.0|--||
+|GL_MAX_VERTEX_UNIFORM_COMPONENTS|2.0|--|2.0|--||
+|GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS|2.0|--|2.0|--||
+|GL_MAX_VERTEX_UNIFORM_VECTORS GL_MAX_FRAGMENT_UNIFORM_VECTORS|4.1|[GL_ARB_ES2_compatibility](https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt)|2.0|--|Defined as GL_MAX_VERTEX_UNIFORM_COMPONENTS / 4 and GL_MAX_FRAGMENT_UNIFORM_COMPONENTS / 4. Can simply use those values when the cap is not available.|
+|GL_MAX_VERTEX_UNIFORM_BLOCKS GL_MAX_FRAGMENT_UNIFORM_BLOCKS GL_MAX_UNIFORM_BUFFER_BINDINGS GL_MAX_UNIFORM_BLOCK_SIZE GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT GL_MAX_COMBINED_UNIFORM_BLOCKS GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS |3.1|[GL_ARB_uniform_buffer_object](https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt)|3.0|--||
+|GL_MAX_VERTEX_OUTPUT_COMPONENTS|3.2|--|3.0|--|Doesn't seem to be a desktop extension for this cap, it may be possible to use the minimum ES3 value (64) if lower than GL 3.2.|
+|GL_MAX_FRAGMENT_UNIFORM_COMPONENTS|2.0|--|2.0|--||
+|GL_MAX_TEXTURE_IMAGE_UNITS|2.0|--|2.0|--||
+|GL_MAX_FRAGMENT_INPUT_COMPONENTS|3.2|--|3.0|--|Doesn't seem to be a desktop extension for this cap either, it may be possible to use the minimum ES3 value (60) if lower than GL 3.2.|
+|GL_MIN_PROGRAM_TEXEL_OFFSET GL_MAX_PROGRAM_TEXEL_OFFSET|3.0|--|3.0|--|Could potentially be emulated in the shader by adding the offsets in normalized texture coordinates before sampling.|
+|GL_MAX_VARYING_COMPONENTS|3.0|[GL_ARB_ES3_compatibility](https://www.opengl.org/registry/specs/ARB/ES3_compatibility.txt)|3.0|--|Was depricated in the OpenGL core spec but re-added in GL_ARB_ES3_compatibility|
+|GL_MAX_VARYING_VECTORS|4.1|[GL_ARB_ES2_compatibility](https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt)|2.0|--|Defined as GL_MAX_VARYING_COMPONENTS / 4.|
+|GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS|3.0|[GL_EXT_transform_feedback](GL_EXT_transform_feedback) or [GL_EXT_transform_feedback2](http://developer.download.nvidia.com/opengl/specs/GL_EXT_transform_feedback2.txt) or [GL_ARB_transform_feedback3](https://www.opengl.org/registry/specs/ARB/transform_feedback3.txt)|3.0|--
+|GL_MAX_SAMPLES|3.0|[GL_EXT_framebuffer_multisample](https://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt)|3.0|[GL_EXT_multisampled_render_to_texture](https://www.khronos.org/registry/gles/extensions/EXT/EXT_multisampled_render_to_texture.txt) or [GL_ANGLE_framebuffer_multisample](https://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_framebuffer_multisample.txt)||
+|GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT|--|[GL_EXT_texture_filter_anisotropic](https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt)|--|[GL_EXT_texture_filter_anisotropic](https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt)|Ubiquitous extension.|
+|IMPLEMENTATION_COLOR_READ_FORMAT IMPLEMENTATION_COLOR_READ_TYPE|--|[GL_ARB_ES2_compatibility](https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt)|2.0|--|Desktop GL doesn't as many limitations as ES for ReadPixels, can either always return GL_RGBA/GL_UNSIGNED_BYTE or return the format and type of the read buffer.|
+
+##OpenGL ES Formats (TODO)
+|Format|OpenGL version|OpenGL extension|OpenGL ES version|OpenGL ES extension|Notes|
+|---|---|---|---|---|---|
+|GL_RGBA8<br>GL_RGB8 |1.0|--|3.0|[GL_OES_rgb8_rgba8](https://www.khronos.org/registry/gles/extensions/OES/OES_rgb8_rgba8.txt)||
+
+## ESSL Features (TODO)
+|Feature|GLSL version|Notes|
+|---|---|---|
+|Unsigned integers|1.30||
+|Pack layout std140|1.40||
+
+## ESSL3 Builtins
+Builtins that are added going from ESSL1 to ESSL3.
+
+|Function|GLSL version|Extension|Notes|
+|---|---|---|---|
+|sinh<br>cosh<br>tanh<br>asinh<br>acosh|1.30|||
+|atanh|1.10|||
+|abs (genIType)|1.30|[GL_EXT_gpu_shader4](https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt)||
+|sign (genIType)|1.50|[GL_EXT_gpu_shader4](https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt)|Can be emulated easily.|
+|trunc|1.30|||
+|round<br>roundEven|1.30|||
+|min (genIType, genUType)<br>max (genIType, genUType)<br>clamp (genIType, genUType)|1.30||
+|mix (genBType)|4.50|[GL_EXT_shader_integer_mix](https://www.opengl.org/registry/specs/EXT/shader_integer_mix.txt)|Should be possible to emulate with a ternery operation.|
+|modf|1.30|||
+|isnan|1.30|||
+|isinf|1.10|||
+|floatBitsToInt<br>floatBitsToUint<br>intBitsToFloat<br>uintBitsToFloat|3.30|[GL_ARB_shader_bit_encoding](https://www.opengl.org/registry/specs/ARB/shader_bit_encoding.txt) or [ARB_gpu_shader5](https://www.opengl.org/registry/specs/ARB/gpu_shader5.txt)||
+|packSnorm2x16<br>packHalf2x16<br>unpackSnorm2x16<br>unpackHalf2x16|4.20|[GL_ARB_shading_language_packing](https://www.opengl.org/registry/specs/ARB/shading_language_packing.txt)|Can be emulated using bit casting functions.|
+|packUnorm2x16<br>unpackUnorm2x16|4.10|[GL_ARB_shading_language_packing](https://www.opengl.org/registry/specs/ARB/shading_language_packing.txt)|Can be emulated using bit casting functions.|
+|matrixCompMult (NxM matrices)|1.10|||
+|outerProduct|1.20|||
+|transpose|1.20|||
+|determinant|1.50||Can be emulated.|
+|inverse|1.40||Can be emulated.|
+|lessThan (uvec)<br>lessThanEqual (uvec)<br>greaterThan (uvec)<br>greaterThanEqual (uvec)<br>equal (uvec)<br>notEqual (uvec)|1.30|||
+|texture<br>textureProj<br>textureLod<br>textureOffset<br>textureProjOffset<br>textureLodOffset<br>textureProjLod<br>textureProjLodOffset<br>texelFetch<br>texelFetchOffset<br>textureGrad<br>textureGradOffset<br>textureProjGrad<br>textureProjGradOffset<br>textureSize|1.30||Equivalent to texture2D, textureCube, etc|
+|dFdx<br>dFdy<br>fwidth|1.10||
+
+## EGL Feature Support (TODO)
+|Feature|EGL version|EGL extension|WGL core|WGL extension|GLX version|GLX extensions|Notes|
+|---|---|---|---|---|---|---|---|
+|Pbuffers|||No|[WGL_ARB_pbuffer](https://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt)||||
+|BindTexImage|||No|[WGL_ARB_render_texture](https://www.opengl.org/registry/specs/ARB/wgl_render_texture.txt)|||Possibly to emulate with OpenGL textures but not strictly required, it is possible only export EGL configs without EGL_BIND_TO_TEXTURE_RGB and EGL_BIND_TO_TEXTURE_RGBA. Bindable pbuffers may be required by Chrome though.|
+|Pixmaps||||||||
+|Swap control|||No|[WGL_EXT_swap_control](https://www.opengl.org/registry/specs/EXT/wgl_swap_control.txt)|No|[GLX_EXT_swap_control](https://www.opengl.org/registry/specs/EXT/swap_control.txt)||
diff --git a/gfx/angle/src/libANGLE/renderer/gl/FenceNVGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/FenceNVGL.cpp
new file mode 100755
index 000000000..b463054c3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/FenceNVGL.cpp
@@ -0,0 +1,51 @@
+//
+// 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.
+//
+
+// FenceNVGL.cpp: Implements the class methods for FenceNVGL.
+
+#include "libANGLE/renderer/gl/FenceNVGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
+
+namespace rx
+{
+
+FenceNVGL::FenceNVGL(const FunctionsGL *functions)
+ : FenceNVImpl(),
+ mFunctions(functions)
+{
+ mFunctions->genFencesNV(1, &mFence);
+}
+
+FenceNVGL::~FenceNVGL()
+{
+ mFunctions->deleteFencesNV(1, &mFence);
+ mFence = 0;
+}
+
+gl::Error FenceNVGL::set(GLenum condition)
+{
+ ASSERT(condition == GL_ALL_COMPLETED_NV);
+ mFunctions->setFenceNV(mFence, condition);
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FenceNVGL::test(GLboolean *outFinished)
+{
+ ASSERT(outFinished);
+ *outFinished = mFunctions->testFenceNV(mFence);
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FenceNVGL::finish()
+{
+ mFunctions->finishFenceNV(mFence);
+ return gl::Error(GL_NO_ERROR);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/FenceNVGL.h b/gfx/angle/src/libANGLE/renderer/gl/FenceNVGL.h
new file mode 100755
index 000000000..ffeca8515
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/FenceNVGL.h
@@ -0,0 +1,36 @@
+//
+// 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.
+//
+
+// FenceNVGL.h: Defines the class interface for FenceNVGL.
+
+#ifndef LIBANGLE_RENDERER_GL_FENCENVGL_H_
+#define LIBANGLE_RENDERER_GL_FENCENVGL_H_
+
+#include "libANGLE/renderer/FenceNVImpl.h"
+
+namespace rx
+{
+class FunctionsGL;
+
+class FenceNVGL : public FenceNVImpl
+{
+ public:
+ explicit FenceNVGL(const FunctionsGL *functions);
+ ~FenceNVGL() override;
+
+ gl::Error set(GLenum condition) override;
+ gl::Error test(GLboolean *outFinished) override;
+ gl::Error finish() override;
+
+ private:
+ GLuint mFence;
+
+ const FunctionsGL *mFunctions;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_FENCENVGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.cpp
new file mode 100755
index 000000000..a3589b95e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.cpp
@@ -0,0 +1,67 @@
+//
+// 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.
+//
+
+// FenceSyncGL.cpp: Implements the class methods for FenceSyncGL.
+
+#include "libANGLE/renderer/gl/FenceSyncGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
+namespace rx
+{
+
+FenceSyncGL::FenceSyncGL(const FunctionsGL *functions)
+ : FenceSyncImpl(),
+ mFunctions(functions),
+ mSyncObject(0)
+{
+ ASSERT(mFunctions);
+}
+
+FenceSyncGL::~FenceSyncGL()
+{
+ if (mSyncObject != 0)
+ {
+ mFunctions->deleteSync(mSyncObject);
+ }
+}
+
+gl::Error FenceSyncGL::set(GLenum condition, GLbitfield flags)
+{
+ ASSERT(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0);
+ mSyncObject = mFunctions->fenceSync(condition, flags);
+ if (mSyncObject == 0)
+ {
+ // if glFenceSync fails, it returns 0.
+ return gl::Error(GL_OUT_OF_MEMORY, "glFenceSync failed to create a GLsync object.");
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FenceSyncGL::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+{
+ ASSERT(mSyncObject != 0);
+ *outResult = mFunctions->clientWaitSync(mSyncObject, flags, timeout);
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FenceSyncGL::serverWait(GLbitfield flags, GLuint64 timeout)
+{
+ ASSERT(mSyncObject != 0);
+ mFunctions->waitSync(mSyncObject, flags, timeout);
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FenceSyncGL::getStatus(GLint *outResult)
+{
+ ASSERT(mSyncObject != 0);
+ mFunctions->getSynciv(mSyncObject, GL_SYNC_STATUS, 1, nullptr, outResult);
+ return gl::Error(GL_NO_ERROR);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.h b/gfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.h
new file mode 100755
index 000000000..8dfd6632d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/FenceSyncGL.h
@@ -0,0 +1,36 @@
+//
+// 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.
+//
+
+// FenceSyncGL.h: Defines the class interface for FenceSyncGL.
+
+#ifndef LIBANGLE_RENDERER_GL_FENCESYNCGL_H_
+#define LIBANGLE_RENDERER_GL_FENCESYNCGL_H_
+
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+namespace rx
+{
+class FunctionsGL;
+
+class FenceSyncGL : public FenceSyncImpl
+{
+ public:
+ explicit FenceSyncGL(const FunctionsGL *functions);
+ ~FenceSyncGL() override;
+
+ gl::Error set(GLenum condition, GLbitfield flags) override;
+ gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override;
+ gl::Error serverWait(GLbitfield flags, GLuint64 timeout) override;
+ gl::Error getStatus(GLint *outResult) override;
+
+ private:
+ const FunctionsGL *mFunctions;
+ GLsync mSyncObject;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_FENCESYNCGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
new file mode 100755
index 000000000..0a058f8ba
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -0,0 +1,553 @@
+//
+// 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.
+//
+
+// FramebufferGL.cpp: Implements the class methods for FramebufferGL.
+
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+
+#include "common/BitSetIterator.h"
+#include "common/debug.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/State.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/gl/BlitGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/RenderbufferGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "libANGLE/renderer/gl/formatutilsgl.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+#include "platform/Platform.h"
+
+using namespace gl;
+using angle::CheckedNumeric;
+
+namespace rx
+{
+
+FramebufferGL::FramebufferGL(const FramebufferState &state,
+ const FunctionsGL *functions,
+ StateManagerGL *stateManager,
+ const WorkaroundsGL &workarounds,
+ BlitGL *blitter,
+ bool isDefault)
+ : FramebufferImpl(state),
+ mFunctions(functions),
+ mStateManager(stateManager),
+ mWorkarounds(workarounds),
+ mBlitter(blitter),
+ mFramebufferID(0),
+ mIsDefault(isDefault)
+{
+ if (!mIsDefault)
+ {
+ mFunctions->genFramebuffers(1, &mFramebufferID);
+ }
+}
+
+FramebufferGL::FramebufferGL(GLuint id,
+ const FramebufferState &state,
+ const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ BlitGL *blitter,
+ StateManagerGL *stateManager)
+ : FramebufferImpl(state),
+ mFunctions(functions),
+ mStateManager(stateManager),
+ mWorkarounds(workarounds),
+ mBlitter(blitter),
+ mFramebufferID(id),
+ mIsDefault(true)
+{
+}
+
+FramebufferGL::~FramebufferGL()
+{
+ mStateManager->deleteFramebuffer(mFramebufferID);
+ mFramebufferID = 0;
+}
+
+static void BindFramebufferAttachment(const FunctionsGL *functions,
+ GLenum attachmentPoint,
+ const FramebufferAttachment *attachment)
+{
+ if (attachment)
+ {
+ if (attachment->type() == GL_TEXTURE)
+ {
+ const Texture *texture = attachment->getTexture();
+ const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
+
+ if (texture->getTarget() == GL_TEXTURE_2D)
+ {
+ functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D,
+ textureGL->getTextureID(), attachment->mipLevel());
+ }
+ else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
+ {
+ functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, attachment->cubeMapFace(),
+ textureGL->getTextureID(), attachment->mipLevel());
+ }
+ else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY || texture->getTarget() == GL_TEXTURE_3D)
+ {
+ functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint, textureGL->getTextureID(),
+ attachment->mipLevel(), attachment->layer());
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+ else if (attachment->type() == GL_RENDERBUFFER)
+ {
+ const Renderbuffer *renderbuffer = attachment->getRenderbuffer();
+ const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
+
+ functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
+ renderbufferGL->getRenderbufferID());
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ // Unbind this attachment
+ functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
+ }
+}
+
+Error FramebufferGL::discard(size_t count, const GLenum *attachments)
+{
+ UNIMPLEMENTED();
+ return Error(GL_INVALID_OPERATION);
+}
+
+Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
+{
+ // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
+ if (mFunctions->invalidateFramebuffer)
+ {
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count), attachments);
+ }
+
+ return Error(GL_NO_ERROR);
+}
+
+Error FramebufferGL::invalidateSub(size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area)
+{
+ // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
+ if (mFunctions->invalidateSubFramebuffer)
+ {
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
+ attachments, area.x, area.y, area.width, area.height);
+ }
+
+ return Error(GL_NO_ERROR);
+}
+
+Error FramebufferGL::clear(ContextImpl *context, GLbitfield mask)
+{
+ syncClearState(mask);
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ mFunctions->clear(mask);
+
+ return Error(GL_NO_ERROR);
+}
+
+Error FramebufferGL::clearBufferfv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values)
+{
+ syncClearBufferState(buffer, drawbuffer);
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ mFunctions->clearBufferfv(buffer, drawbuffer, values);
+
+ return Error(GL_NO_ERROR);
+}
+
+Error FramebufferGL::clearBufferuiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values)
+{
+ syncClearBufferState(buffer, drawbuffer);
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ mFunctions->clearBufferuiv(buffer, drawbuffer, values);
+
+ return Error(GL_NO_ERROR);
+}
+
+Error FramebufferGL::clearBufferiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values)
+{
+ syncClearBufferState(buffer, drawbuffer);
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ mFunctions->clearBufferiv(buffer, drawbuffer, values);
+
+ return Error(GL_NO_ERROR);
+}
+
+Error FramebufferGL::clearBufferfi(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
+{
+ syncClearBufferState(buffer, drawbuffer);
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
+
+ return Error(GL_NO_ERROR);
+}
+
+GLenum FramebufferGL::getImplementationColorReadFormat() const
+{
+ const auto *readAttachment = mState.getReadAttachment();
+ const Format &format = readAttachment->getFormat();
+ return format.info->getReadPixelsFormat();
+}
+
+GLenum FramebufferGL::getImplementationColorReadType() const
+{
+ const auto *readAttachment = mState.getReadAttachment();
+ const Format &format = readAttachment->getFormat();
+ return format.info->getReadPixelsType();
+}
+
+Error FramebufferGL::readPixels(ContextImpl *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels) const
+{
+ // TODO: don't sync the pixel pack state here once the dirty bits contain the pixel pack buffer
+ // binding
+ const PixelPackState &packState = context->getGLState().getPackState();
+ mStateManager->setPixelPackState(packState);
+
+ nativegl::ReadPixelsFormat readPixelsFormat =
+ nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
+ GLenum readFormat = readPixelsFormat.format;
+ GLenum readType = readPixelsFormat.type;
+
+ mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
+
+ if (mWorkarounds.packOverlappingRowsSeparatelyPackBuffer && packState.pixelBuffer.get() &&
+ packState.rowLength != 0 && packState.rowLength < area.width)
+ {
+ return readPixelsRowByRowWorkaround(area, readFormat, readType, packState, pixels);
+ }
+
+ if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
+ {
+ gl::Extents size(area.width, area.height, 1);
+
+ bool apply;
+ ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, packState, readFormat, readType,
+ false, pixels),
+ apply);
+
+ if (apply)
+ {
+ return readPixelsPaddingWorkaround(area, readFormat, readType, packState, pixels);
+ }
+ }
+
+ mFunctions->readPixels(area.x, area.y, area.width, area.height, readFormat, readType, pixels);
+
+ return gl::NoError();
+}
+
+Error FramebufferGL::blit(ContextImpl *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter)
+{
+ const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
+ const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
+
+ const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
+ GLsizei readAttachmentSamples = colorReadAttachment->getSamples();
+
+ bool needManualColorBlit = false;
+
+ // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
+ // could avoid doing a manual blit.
+
+ // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
+ // When values are taken from the read buffer, no linearization is performed, even
+ // if the format of the buffer is SRGB.
+ // Starting from OpenGL 4.4 (section 18.3.1) it reads:
+ // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
+ // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
+ // corresponding to the read buffer is SRGB, the red, green, and blue components are
+ // converted from the non-linear sRGB color space according [...].
+ {
+ bool sourceSRGB = colorReadAttachment != nullptr &&
+ colorReadAttachment->getColorEncoding() == GL_SRGB;
+ needManualColorBlit =
+ needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3)));
+ }
+
+ // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
+ // Blit operations bypass the fragment pipeline. The only fragment operations which
+ // affect a blit are the pixel ownership test and scissor test.
+ // Starting from OpenGL 4.2 (section 4.3.2) it reads:
+ // When values are written to the draw buffers, blit operations bypass the fragment
+ // pipeline. The only fragment operations which affect a blit are the pixel ownership
+ // test, the scissor test and sRGB conversion.
+ if (!needManualColorBlit)
+ {
+ bool destSRGB = false;
+ for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
+ {
+ const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
+ if (attachment && attachment->getColorEncoding() == GL_SRGB)
+ {
+ destSRGB = true;
+ break;
+ }
+ }
+
+ needManualColorBlit =
+ needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1)));
+ }
+
+ // Enable FRAMEBUFFER_SRGB if needed
+ mStateManager->setFramebufferSRGBEnabledForFramebuffer(true, this);
+
+ GLenum blitMask = mask;
+ if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
+ {
+ ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer,
+ sourceArea, destArea, filter));
+ blitMask &= ~GL_COLOR_BUFFER_BIT;
+ }
+
+ if (blitMask == 0)
+ {
+ return gl::NoError();
+ }
+
+ const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
+ mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
+ mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
+
+ mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
+ destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
+ filter);
+
+ return gl::NoError();
+}
+
+bool FramebufferGL::checkStatus() const
+{
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ ANGLEPlatformCurrent()->logWarning("GL framebuffer returned incomplete.");
+ }
+ return (status == GL_FRAMEBUFFER_COMPLETE);
+}
+
+void FramebufferGL::syncState(const Framebuffer::DirtyBits &dirtyBits)
+{
+ // Don't need to sync state for the default FBO.
+ if (mIsDefault)
+ {
+ return;
+ }
+
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+
+ for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
+ {
+ switch (dirtyBit)
+ {
+ case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
+ BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT,
+ mState.getDepthAttachment());
+ break;
+ case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
+ BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT,
+ mState.getStencilAttachment());
+ break;
+ case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
+ {
+ const auto &drawBuffers = mState.getDrawBufferStates();
+ mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
+ drawBuffers.data());
+ break;
+ }
+ case Framebuffer::DIRTY_BIT_READ_BUFFER:
+ mFunctions->readBuffer(mState.getReadBufferState());
+ break;
+ default:
+ {
+ ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
+ dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
+ size_t index =
+ static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
+ BindFramebufferAttachment(mFunctions,
+ static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index),
+ mState.getColorAttachment(index));
+ break;
+ }
+ }
+ }
+}
+
+GLuint FramebufferGL::getFramebufferID() const
+{
+ return mFramebufferID;
+}
+
+bool FramebufferGL::isDefault() const
+{
+ return mIsDefault;
+}
+
+void FramebufferGL::syncClearState(GLbitfield mask)
+{
+ if (mFunctions->standard == STANDARD_GL_DESKTOP)
+ {
+ if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
+ (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
+ {
+ bool hasSRGBAttachment = false;
+ for (const auto &attachment : mState.getColorAttachments())
+ {
+ if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
+ {
+ hasSRGBAttachment = true;
+ break;
+ }
+ }
+
+ mStateManager->setFramebufferSRGBEnabled(hasSRGBAttachment);
+ }
+ else
+ {
+ mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
+ }
+ }
+}
+
+void FramebufferGL::syncClearBufferState(GLenum buffer, GLint drawBuffer)
+{
+ if (mFunctions->standard == STANDARD_GL_DESKTOP)
+ {
+ if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
+ !mIsDefault)
+ {
+ // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
+ // is an SRGB format.
+ const auto &drawbufferState = mState.getDrawBufferStates();
+ const auto &colorAttachments = mState.getColorAttachments();
+
+ const FramebufferAttachment *attachment = nullptr;
+ if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
+ drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
+ {
+ size_t attachmentIdx =
+ static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
+ attachment = &colorAttachments[attachmentIdx];
+ }
+
+ if (attachment != nullptr)
+ {
+ mStateManager->setFramebufferSRGBEnabled(attachment->getColorEncoding() == GL_SRGB);
+ }
+ }
+ else
+ {
+ mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
+ }
+ }
+}
+gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelPackState &pack,
+ GLvoid *pixels) const
+{
+ intptr_t offset = reinterpret_cast<intptr_t>(pixels);
+
+ const gl::InternalFormat &glFormat =
+ gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
+ GLuint rowBytes = 0;
+ ANGLE_TRY_RESULT(glFormat.computeRowPitch(area.width, pack.alignment, pack.rowLength),
+ rowBytes);
+ GLuint skipBytes = 0;
+ ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
+
+ gl::PixelPackState directPack;
+ directPack.pixelBuffer = pack.pixelBuffer;
+ directPack.alignment = 1;
+ mStateManager->setPixelPackState(directPack);
+ directPack.pixelBuffer.set(nullptr);
+
+ offset += skipBytes;
+ for (GLint row = 0; row < area.height; ++row)
+ {
+ mFunctions->readPixels(area.x, row + area.y, area.width, 1, format, type,
+ reinterpret_cast<GLvoid *>(offset));
+ offset += row * rowBytes;
+ }
+
+ return gl::NoError();
+}
+
+gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelPackState &pack,
+ GLvoid *pixels) const
+{
+ const gl::InternalFormat &glFormat =
+ gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
+ GLuint rowBytes = 0;
+ ANGLE_TRY_RESULT(glFormat.computeRowPitch(area.width, pack.alignment, pack.rowLength),
+ rowBytes);
+ GLuint skipBytes = 0;
+ ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
+
+ // Get all by the last row
+ if (area.height > 1)
+ {
+ mFunctions->readPixels(area.x, area.y, area.width, area.height - 1, format, type, pixels);
+ }
+
+ // Get the last row manually
+ gl::PixelPackState directPack;
+ directPack.pixelBuffer = pack.pixelBuffer;
+ directPack.alignment = 1;
+ mStateManager->setPixelPackState(directPack);
+ directPack.pixelBuffer.set(nullptr);
+
+ intptr_t lastRowOffset =
+ reinterpret_cast<intptr_t>(pixels) + skipBytes + (area.height - 1) * rowBytes;
+ mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
+ reinterpret_cast<GLvoid *>(lastRowOffset));
+
+ return gl::NoError();
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.h b/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.h
new file mode 100755
index 000000000..a8bcb894c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.h
@@ -0,0 +1,113 @@
+//
+// 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.
+//
+
+// FramebufferGL.h: Defines the class interface for FramebufferGL.
+
+#ifndef LIBANGLE_RENDERER_GL_FRAMEBUFFERGL_H_
+#define LIBANGLE_RENDERER_GL_FRAMEBUFFERGL_H_
+
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace rx
+{
+
+class BlitGL;
+class FunctionsGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class FramebufferGL : public FramebufferImpl
+{
+ public:
+ FramebufferGL(const gl::FramebufferState &data,
+ const FunctionsGL *functions,
+ StateManagerGL *stateManager,
+ const WorkaroundsGL &workarounds,
+ BlitGL *blitter,
+ bool isDefault);
+ // Constructor called when we need to create a FramebufferGL from an
+ // existing framebuffer name, for example for the default framebuffer
+ // on the Mac EGL CGL backend.
+ FramebufferGL(GLuint id,
+ const gl::FramebufferState &data,
+ const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ BlitGL *blitter,
+ StateManagerGL *stateManager);
+ ~FramebufferGL() override;
+
+ gl::Error discard(size_t count, const GLenum *attachments) override;
+ gl::Error invalidate(size_t count, const GLenum *attachments) override;
+ gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
+
+ gl::Error clear(ContextImpl *context, GLbitfield mask) override;
+ gl::Error clearBufferfv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values) override;
+ gl::Error clearBufferuiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values) override;
+ gl::Error clearBufferiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values) override;
+ gl::Error clearBufferfi(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil) override;
+
+ GLenum getImplementationColorReadFormat() const override;
+ GLenum getImplementationColorReadType() const override;
+ gl::Error readPixels(ContextImpl *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels) const override;
+
+ gl::Error blit(ContextImpl *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter) override;
+
+ bool checkStatus() const override;
+
+ void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
+
+ GLuint getFramebufferID() const;
+ bool isDefault() const;
+
+ private:
+ void syncClearState(GLbitfield mask);
+ void syncClearBufferState(GLenum buffer, GLint drawBuffer);
+
+ gl::Error readPixelsRowByRowWorkaround(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelPackState &pack,
+ GLvoid *pixels) const;
+
+ gl::Error readPixelsPaddingWorkaround(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelPackState &pack,
+ GLvoid *pixels) const;
+
+ const FunctionsGL *mFunctions;
+ StateManagerGL *mStateManager;
+ const WorkaroundsGL &mWorkarounds;
+ BlitGL *mBlitter;
+
+ GLuint mFramebufferID;
+ bool mIsDefault;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_FRAMEBUFFERGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp
new file mode 100755
index 000000000..fcbf211bc
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp
@@ -0,0 +1,2316 @@
+//
+// Copyright (c) 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.cpp: Implements the FuntionsGL class to contain loaded GL functions
+
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
+#include <algorithm>
+
+#include "common/string_utils.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+namespace rx
+{
+
+static void GetGLVersion(PFNGLGETSTRINGPROC getStringFunction, gl::Version *outVersion, StandardGL *outStandard)
+{
+ const std::string version = reinterpret_cast<const char*>(getStringFunction(GL_VERSION));
+ if (version.find("OpenGL ES") == std::string::npos)
+ {
+ // OpenGL spec states the GL_VERSION string will be in the following format:
+ // <version number><space><vendor-specific information>
+ // The version number is either of the form major number.minor number or major
+ // number.minor number.release number, where the numbers all have one or more
+ // digits
+ *outStandard = STANDARD_GL_DESKTOP;
+ *outVersion = gl::Version(version[0] - '0', version[2] - '0');
+ }
+ else
+ {
+ // ES spec states that the GL_VERSION string will be in the following format:
+ // "OpenGL ES N.M vendor-specific information"
+ *outStandard = STANDARD_GL_ES;
+ *outVersion = gl::Version(version[10] - '0', version[12] - '0');
+ }
+}
+
+static std::vector<std::string> GetIndexedExtensions(PFNGLGETINTEGERVPROC getIntegerFunction, PFNGLGETSTRINGIPROC getStringIFunction)
+{
+ std::vector<std::string> result;
+
+ GLint numExtensions;
+ getIntegerFunction(GL_NUM_EXTENSIONS, &numExtensions);
+
+ result.reserve(numExtensions);
+
+ for (GLint i = 0; i < numExtensions; i++)
+ {
+ result.push_back(reinterpret_cast<const char*>(getStringIFunction(GL_EXTENSIONS, i)));
+ }
+
+ return result;
+}
+
+template <typename T>
+static void AssignGLEntryPoint(void *function, T *outFunction)
+{
+ *outFunction = reinterpret_cast<T>(function);
+}
+
+template <typename T>
+static void AssignGLExtensionEntryPoint(const std::vector<std::string> &extensions, const char *requiredExtensionString,
+ void *function, T *outFunction)
+{
+ std::vector<std::string> requiredExtensions;
+ angle::SplitStringAlongWhitespace(requiredExtensionString, &requiredExtensions);
+ for (const std::string& requiredExtension : requiredExtensions)
+ {
+ if (std::find(extensions.begin(), extensions.end(), requiredExtension) == extensions.end())
+ {
+ return;
+ }
+ }
+
+ *outFunction = reinterpret_cast<T>(function);
+}
+
+FunctionsGL::FunctionsGL()
+ : version(),
+ standard(),
+ extensions(),
+
+ blendFunc(nullptr),
+ clear(nullptr),
+ clearColor(nullptr),
+ clearDepth(nullptr),
+ clearStencil(nullptr),
+ colorMask(nullptr),
+ cullFace(nullptr),
+ depthFunc(nullptr),
+ depthMask(nullptr),
+ depthRange(nullptr),
+ disable(nullptr),
+ drawBuffer(nullptr),
+ enable(nullptr),
+ finish(nullptr),
+ flush(nullptr),
+ frontFace(nullptr),
+ getBooleanv(nullptr),
+ getDoublev(nullptr),
+ getError(nullptr),
+ getFloatv(nullptr),
+ getIntegerv(nullptr),
+ getString(nullptr),
+ getTexImage(nullptr),
+ getTexLevelParameterfv(nullptr),
+ getTexLevelParameteriv(nullptr),
+ getTexParameterfv(nullptr),
+ getTexParameteriv(nullptr),
+ hint(nullptr),
+ isEnabled(nullptr),
+ lineWidth(nullptr),
+ logicOp(nullptr),
+ pixelStoref(nullptr),
+ pixelStorei(nullptr),
+ pointSize(nullptr),
+ polygonMode(nullptr),
+ readBuffer(nullptr),
+ readPixels(nullptr),
+ scissor(nullptr),
+ stencilFunc(nullptr),
+ stencilMask(nullptr),
+ stencilOp(nullptr),
+ texImage1D(nullptr),
+ texImage2D(nullptr),
+ texParameterf(nullptr),
+ texParameterfv(nullptr),
+ texParameteri(nullptr),
+ texParameteriv(nullptr),
+ viewport(nullptr),
+
+ bindTexture(nullptr),
+ copyTexImage1D(nullptr),
+ copyTexImage2D(nullptr),
+ copyTexSubImage1D(nullptr),
+ copyTexSubImage2D(nullptr),
+ deleteTextures(nullptr),
+ drawArrays(nullptr),
+ drawElements(nullptr),
+ genTextures(nullptr),
+ isTexture(nullptr),
+ polygonOffset(nullptr),
+ texSubImage1D(nullptr),
+ texSubImage2D(nullptr),
+
+ blendColor(nullptr),
+ blendEquation(nullptr),
+ copyTexSubImage3D(nullptr),
+ drawRangeElements(nullptr),
+ texImage3D(nullptr),
+ texSubImage3D(nullptr),
+
+ deleteFencesNV(nullptr),
+ genFencesNV(nullptr),
+ isFenceNV(nullptr),
+ testFenceNV(nullptr),
+ getFenceivNV(nullptr),
+ finishFenceNV(nullptr),
+ setFenceNV(nullptr),
+
+ activeTexture(nullptr),
+ compressedTexImage1D(nullptr),
+ compressedTexImage2D(nullptr),
+ compressedTexImage3D(nullptr),
+ compressedTexSubImage1D(nullptr),
+ compressedTexSubImage2D(nullptr),
+ compressedTexSubImage3D(nullptr),
+ getCompressedTexImage(nullptr),
+ sampleCoverage(nullptr),
+
+ blendFuncSeparate(nullptr),
+ multiDrawArrays(nullptr),
+ multiDrawElements(nullptr),
+ pointParameterf(nullptr),
+ pointParameterfv(nullptr),
+ pointParameteri(nullptr),
+ pointParameteriv(nullptr),
+
+ beginQuery(nullptr),
+ bindBuffer(nullptr),
+ bufferData(nullptr),
+ bufferSubData(nullptr),
+ deleteBuffers(nullptr),
+ deleteQueries(nullptr),
+ endQuery(nullptr),
+ genBuffers(nullptr),
+ genQueries(nullptr),
+ getBufferParameteriv(nullptr),
+ getBufferPointerv(nullptr),
+ getBufferSubData(nullptr),
+ getQueryObjectiv(nullptr),
+ getQueryObjectuiv(nullptr),
+ getQueryiv(nullptr),
+ isBuffer(nullptr),
+ isQuery(nullptr),
+ mapBuffer(nullptr),
+ unmapBuffer(nullptr),
+
+ attachShader(nullptr),
+ bindAttribLocation(nullptr),
+ blendEquationSeparate(nullptr),
+ compileShader(nullptr),
+ createProgram(nullptr),
+ createShader(nullptr),
+ deleteProgram(nullptr),
+ deleteShader(nullptr),
+ detachShader(nullptr),
+ disableVertexAttribArray(nullptr),
+ drawBuffers(nullptr),
+ enableVertexAttribArray(nullptr),
+ getActiveAttrib(nullptr),
+ getActiveUniform(nullptr),
+ getAttachedShaders(nullptr),
+ getAttribLocation(nullptr),
+ getProgramInfoLog(nullptr),
+ getProgramiv(nullptr),
+ getShaderInfoLog(nullptr),
+ getShaderSource(nullptr),
+ getShaderiv(nullptr),
+ getUniformLocation(nullptr),
+ getUniformfv(nullptr),
+ getUniformiv(nullptr),
+ getVertexAttribPointerv(nullptr),
+ getVertexAttribdv(nullptr),
+ getVertexAttribfv(nullptr),
+ getVertexAttribiv(nullptr),
+ isProgram(nullptr),
+ isShader(nullptr),
+ linkProgram(nullptr),
+ shaderSource(nullptr),
+ stencilFuncSeparate(nullptr),
+ stencilMaskSeparate(nullptr),
+ stencilOpSeparate(nullptr),
+ uniform1f(nullptr),
+ uniform1fv(nullptr),
+ uniform1i(nullptr),
+ uniform1iv(nullptr),
+ uniform2f(nullptr),
+ uniform2fv(nullptr),
+ uniform2i(nullptr),
+ uniform2iv(nullptr),
+ uniform3f(nullptr),
+ uniform3fv(nullptr),
+ uniform3i(nullptr),
+ uniform3iv(nullptr),
+ uniform4f(nullptr),
+ uniform4fv(nullptr),
+ uniform4i(nullptr),
+ uniform4iv(nullptr),
+ uniformMatrix2fv(nullptr),
+ uniformMatrix3fv(nullptr),
+ uniformMatrix4fv(nullptr),
+ useProgram(nullptr),
+ validateProgram(nullptr),
+ vertexAttrib1d(nullptr),
+ vertexAttrib1dv(nullptr),
+ vertexAttrib1f(nullptr),
+ vertexAttrib1fv(nullptr),
+ vertexAttrib1s(nullptr),
+ vertexAttrib1sv(nullptr),
+ vertexAttrib2d(nullptr),
+ vertexAttrib2dv(nullptr),
+ vertexAttrib2f(nullptr),
+ vertexAttrib2fv(nullptr),
+ vertexAttrib2s(nullptr),
+ vertexAttrib2sv(nullptr),
+ vertexAttrib3d(nullptr),
+ vertexAttrib3dv(nullptr),
+ vertexAttrib3f(nullptr),
+ vertexAttrib3fv(nullptr),
+ vertexAttrib3s(nullptr),
+ vertexAttrib3sv(nullptr),
+ vertexAttrib4Nbv(nullptr),
+ vertexAttrib4Niv(nullptr),
+ vertexAttrib4Nsv(nullptr),
+ vertexAttrib4Nub(nullptr),
+ vertexAttrib4Nubv(nullptr),
+ vertexAttrib4Nuiv(nullptr),
+ vertexAttrib4Nusv(nullptr),
+ vertexAttrib4bv(nullptr),
+ vertexAttrib4d(nullptr),
+ vertexAttrib4dv(nullptr),
+ vertexAttrib4f(nullptr),
+ vertexAttrib4fv(nullptr),
+ vertexAttrib4iv(nullptr),
+ vertexAttrib4s(nullptr),
+ vertexAttrib4sv(nullptr),
+ vertexAttrib4ubv(nullptr),
+ vertexAttrib4uiv(nullptr),
+ vertexAttrib4usv(nullptr),
+ vertexAttribPointer(nullptr),
+
+ uniformMatrix2x3fv(nullptr),
+ uniformMatrix2x4fv(nullptr),
+ uniformMatrix3x2fv(nullptr),
+ uniformMatrix3x4fv(nullptr),
+ uniformMatrix4x2fv(nullptr),
+ uniformMatrix4x3fv(nullptr),
+
+ beginConditionalRender(nullptr),
+ beginTransformFeedback(nullptr),
+ bindBufferBase(nullptr),
+ bindBufferRange(nullptr),
+ bindFragDataLocation(nullptr),
+ bindFramebuffer(nullptr),
+ bindRenderbuffer(nullptr),
+ bindVertexArray(nullptr),
+ blitFramebuffer(nullptr),
+ checkFramebufferStatus(nullptr),
+ clampColor(nullptr),
+ clearBufferfi(nullptr),
+ clearBufferfv(nullptr),
+ clearBufferiv(nullptr),
+ clearBufferuiv(nullptr),
+ colorMaski(nullptr),
+ deleteFramebuffers(nullptr),
+ deleteRenderbuffers(nullptr),
+ deleteVertexArrays(nullptr),
+ disablei(nullptr),
+ enablei(nullptr),
+ endConditionalRender(nullptr),
+ endTransformFeedback(nullptr),
+ flushMappedBufferRange(nullptr),
+ framebufferRenderbuffer(nullptr),
+ framebufferTexture1D(nullptr),
+ framebufferTexture2D(nullptr),
+ framebufferTexture3D(nullptr),
+ framebufferTextureLayer(nullptr),
+ genFramebuffers(nullptr),
+ genRenderbuffers(nullptr),
+ genVertexArrays(nullptr),
+ generateMipmap(nullptr),
+ getBooleani_v(nullptr),
+ getFragDataLocation(nullptr),
+ getFramebufferAttachmentParameteriv(nullptr),
+ getIntegeri_v(nullptr),
+ getRenderbufferParameteriv(nullptr),
+ getStringi(nullptr),
+ getTexParameterIiv(nullptr),
+ getTexParameterIuiv(nullptr),
+ getTransformFeedbackVarying(nullptr),
+ getUniformuiv(nullptr),
+ getVertexAttribIiv(nullptr),
+ getVertexAttribIuiv(nullptr),
+ isEnabledi(nullptr),
+ isFramebuffer(nullptr),
+ isRenderbuffer(nullptr),
+ isVertexArray(nullptr),
+ mapBufferRange(nullptr),
+ renderbufferStorage(nullptr),
+ renderbufferStorageMultisample(nullptr),
+ texParameterIiv(nullptr),
+ texParameterIuiv(nullptr),
+ transformFeedbackVaryings(nullptr),
+ uniform1ui(nullptr),
+ uniform1uiv(nullptr),
+ uniform2ui(nullptr),
+ uniform2uiv(nullptr),
+ uniform3ui(nullptr),
+ uniform3uiv(nullptr),
+ uniform4ui(nullptr),
+ uniform4uiv(nullptr),
+ vertexAttribI1i(nullptr),
+ vertexAttribI1iv(nullptr),
+ vertexAttribI1ui(nullptr),
+ vertexAttribI1uiv(nullptr),
+ vertexAttribI2i(nullptr),
+ vertexAttribI2iv(nullptr),
+ vertexAttribI2ui(nullptr),
+ vertexAttribI2uiv(nullptr),
+ vertexAttribI3i(nullptr),
+ vertexAttribI3iv(nullptr),
+ vertexAttribI3ui(nullptr),
+ vertexAttribI3uiv(nullptr),
+ vertexAttribI4bv(nullptr),
+ vertexAttribI4i(nullptr),
+ vertexAttribI4iv(nullptr),
+ vertexAttribI4sv(nullptr),
+ vertexAttribI4ubv(nullptr),
+ vertexAttribI4ui(nullptr),
+ vertexAttribI4uiv(nullptr),
+ vertexAttribI4usv(nullptr),
+ vertexAttribIPointer(nullptr),
+
+ copyBufferSubData(nullptr),
+ drawArraysInstanced(nullptr),
+ drawElementsInstanced(nullptr),
+ getActiveUniformBlockName(nullptr),
+ getActiveUniformBlockiv(nullptr),
+ getActiveUniformName(nullptr),
+ getActiveUniformsiv(nullptr),
+ getUniformBlockIndex(nullptr),
+ getUniformIndices(nullptr),
+ primitiveRestartIndex(nullptr),
+ texBuffer(nullptr),
+ uniformBlockBinding(nullptr),
+
+ clientWaitSync(nullptr),
+ deleteSync(nullptr),
+ drawElementsBaseVertex(nullptr),
+ drawElementsInstancedBaseVertex(nullptr),
+ drawRangeElementsBaseVertex(nullptr),
+ fenceSync(nullptr),
+ framebufferTexture(nullptr),
+ getBufferParameteri64v(nullptr),
+ getInteger64i_v(nullptr),
+ getInteger64v(nullptr),
+ getMultisamplefv(nullptr),
+ getSynciv(nullptr),
+ isSync(nullptr),
+ multiDrawElementsBaseVertex(nullptr),
+ provokingVertex(nullptr),
+ sampleMaski(nullptr),
+ texImage2DMultisample(nullptr),
+ texImage3DMultisample(nullptr),
+ waitSync(nullptr),
+
+ matrixLoadEXT(nullptr),
+ genPathsNV(nullptr),
+ delPathsNV(nullptr),
+ pathCommandsNV(nullptr),
+ setPathParameterfNV(nullptr),
+ setPathParameteriNV(nullptr),
+ getPathParameterfNV(nullptr),
+ getPathParameteriNV(nullptr),
+ pathStencilFuncNV(nullptr),
+ stencilFillPathNV(nullptr),
+ stencilStrokePathNV(nullptr),
+ coverFillPathNV(nullptr),
+ coverStrokePathNV(nullptr),
+ stencilThenCoverFillPathNV(nullptr),
+ stencilThenCoverStrokePathNV(nullptr),
+ coverFillPathInstancedNV(nullptr),
+ coverStrokePathInstancedNV(nullptr),
+ stencilFillPathInstancedNV(nullptr),
+ stencilStrokePathInstancedNV(nullptr),
+ stencilThenCoverFillPathInstancedNV(nullptr),
+ stencilThenCoverStrokePathInstancedNV(nullptr),
+ programPathFragmentInputGenNV(nullptr),
+
+ bindFragDataLocationIndexed(nullptr),
+ bindSampler(nullptr),
+ deleteSamplers(nullptr),
+ genSamplers(nullptr),
+ getFragDataIndex(nullptr),
+ getQueryObjecti64v(nullptr),
+ getQueryObjectui64v(nullptr),
+ getSamplerParameterIiv(nullptr),
+ getSamplerParameterIuiv(nullptr),
+ getSamplerParameterfv(nullptr),
+ getSamplerParameteriv(nullptr),
+ isSampler(nullptr),
+ queryCounter(nullptr),
+ samplerParameterIiv(nullptr),
+ samplerParameterIuiv(nullptr),
+ samplerParameterf(nullptr),
+ samplerParameterfv(nullptr),
+ samplerParameteri(nullptr),
+ samplerParameteriv(nullptr),
+ vertexAttribDivisor(nullptr),
+ vertexAttribP1ui(nullptr),
+ vertexAttribP1uiv(nullptr),
+ vertexAttribP2ui(nullptr),
+ vertexAttribP2uiv(nullptr),
+ vertexAttribP3ui(nullptr),
+ vertexAttribP3uiv(nullptr),
+ vertexAttribP4ui(nullptr),
+ vertexAttribP4uiv(nullptr),
+
+ beginQueryIndexed(nullptr),
+ bindTransformFeedback(nullptr),
+ blendEquationSeparatei(nullptr),
+ blendEquationi(nullptr),
+ blendFuncSeparatei(nullptr),
+ blendFunci(nullptr),
+ deleteTransformFeedbacks(nullptr),
+ drawArraysIndirect(nullptr),
+ drawElementsIndirect(nullptr),
+ drawTransformFeedback(nullptr),
+ drawTransformFeedbackStream(nullptr),
+ endQueryIndexed(nullptr),
+ genTransformFeedbacks(nullptr),
+ getActiveSubroutineName(nullptr),
+ getActiveSubroutineUniformName(nullptr),
+ getActiveSubroutineUniformiv(nullptr),
+ getProgramStageiv(nullptr),
+ getQueryIndexediv(nullptr),
+ getSubroutineIndex(nullptr),
+ getSubroutineUniformLocation(nullptr),
+ getUniformSubroutineuiv(nullptr),
+ getUniformdv(nullptr),
+ isTransformFeedback(nullptr),
+ minSampleShading(nullptr),
+ patchParameterfv(nullptr),
+ patchParameteri(nullptr),
+ pauseTransformFeedback(nullptr),
+ resumeTransformFeedback(nullptr),
+ uniform1d(nullptr),
+ uniform1dv(nullptr),
+ uniform2d(nullptr),
+ uniform2dv(nullptr),
+ uniform3d(nullptr),
+ uniform3dv(nullptr),
+ uniform4d(nullptr),
+ uniform4dv(nullptr),
+ uniformMatrix2dv(nullptr),
+ uniformMatrix2x3dv(nullptr),
+ uniformMatrix2x4dv(nullptr),
+ uniformMatrix3dv(nullptr),
+ uniformMatrix3x2dv(nullptr),
+ uniformMatrix3x4dv(nullptr),
+ uniformMatrix4dv(nullptr),
+ uniformMatrix4x2dv(nullptr),
+ uniformMatrix4x3dv(nullptr),
+ uniformSubroutinesuiv(nullptr),
+
+ activeShaderProgram(nullptr),
+ bindProgramPipeline(nullptr),
+ clearDepthf(nullptr),
+ createShaderProgramv(nullptr),
+ deleteProgramPipelines(nullptr),
+ depthRangeArrayv(nullptr),
+ depthRangeIndexed(nullptr),
+ depthRangef(nullptr),
+ genProgramPipelines(nullptr),
+ getDoublei_v(nullptr),
+ getFloati_v(nullptr),
+ getProgramBinary(nullptr),
+ getProgramPipelineInfoLog(nullptr),
+ getProgramPipelineiv(nullptr),
+ getShaderPrecisionFormat(nullptr),
+ getVertexAttribLdv(nullptr),
+ isProgramPipeline(nullptr),
+ programBinary(nullptr),
+ programParameteri(nullptr),
+ programUniform1d(nullptr),
+ programUniform1dv(nullptr),
+ programUniform1f(nullptr),
+ programUniform1fv(nullptr),
+ programUniform1i(nullptr),
+ programUniform1iv(nullptr),
+ programUniform1ui(nullptr),
+ programUniform1uiv(nullptr),
+ programUniform2d(nullptr),
+ programUniform2dv(nullptr),
+ programUniform2f(nullptr),
+ programUniform2fv(nullptr),
+ programUniform2i(nullptr),
+ programUniform2iv(nullptr),
+ programUniform2ui(nullptr),
+ programUniform2uiv(nullptr),
+ programUniform3d(nullptr),
+ programUniform3dv(nullptr),
+ programUniform3f(nullptr),
+ programUniform3fv(nullptr),
+ programUniform3i(nullptr),
+ programUniform3iv(nullptr),
+ programUniform3ui(nullptr),
+ programUniform3uiv(nullptr),
+ programUniform4d(nullptr),
+ programUniform4dv(nullptr),
+ programUniform4f(nullptr),
+ programUniform4fv(nullptr),
+ programUniform4i(nullptr),
+ programUniform4iv(nullptr),
+ programUniform4ui(nullptr),
+ programUniform4uiv(nullptr),
+ programUniformMatrix2dv(nullptr),
+ programUniformMatrix2fv(nullptr),
+ programUniformMatrix2x3dv(nullptr),
+ programUniformMatrix2x3fv(nullptr),
+ programUniformMatrix2x4dv(nullptr),
+ programUniformMatrix2x4fv(nullptr),
+ programUniformMatrix3dv(nullptr),
+ programUniformMatrix3fv(nullptr),
+ programUniformMatrix3x2dv(nullptr),
+ programUniformMatrix3x2fv(nullptr),
+ programUniformMatrix3x4dv(nullptr),
+ programUniformMatrix3x4fv(nullptr),
+ programUniformMatrix4dv(nullptr),
+ programUniformMatrix4fv(nullptr),
+ programUniformMatrix4x2dv(nullptr),
+ programUniformMatrix4x2fv(nullptr),
+ programUniformMatrix4x3dv(nullptr),
+ programUniformMatrix4x3fv(nullptr),
+ releaseShaderCompiler(nullptr),
+ scissorArrayv(nullptr),
+ scissorIndexed(nullptr),
+ scissorIndexedv(nullptr),
+ shaderBinary(nullptr),
+ useProgramStages(nullptr),
+ validateProgramPipeline(nullptr),
+ vertexAttribL1d(nullptr),
+ vertexAttribL1dv(nullptr),
+ vertexAttribL2d(nullptr),
+ vertexAttribL2dv(nullptr),
+ vertexAttribL3d(nullptr),
+ vertexAttribL3dv(nullptr),
+ vertexAttribL4d(nullptr),
+ vertexAttribL4dv(nullptr),
+ vertexAttribLPointer(nullptr),
+ viewportArrayv(nullptr),
+ viewportIndexedf(nullptr),
+ viewportIndexedfv(nullptr),
+
+ bindImageTexture(nullptr),
+ drawArraysInstancedBaseInstance(nullptr),
+ drawElementsInstancedBaseInstance(nullptr),
+ drawElementsInstancedBaseVertexBaseInstance(nullptr),
+ drawTransformFeedbackInstanced(nullptr),
+ drawTransformFeedbackStreamInstanced(nullptr),
+ getActiveAtomicCounterBufferiv(nullptr),
+ getInternalformativ(nullptr),
+ memoryBarrier(nullptr),
+ texStorage1D(nullptr),
+ texStorage2D(nullptr),
+ texStorage3D(nullptr),
+
+ bindVertexBuffer(nullptr),
+ clearBufferData(nullptr),
+ clearBufferSubData(nullptr),
+ copyImageSubData(nullptr),
+ debugMessageCallback(nullptr),
+ debugMessageControl(nullptr),
+ debugMessageInsert(nullptr),
+ dispatchCompute(nullptr),
+ dispatchComputeIndirect(nullptr),
+ framebufferParameteri(nullptr),
+ getDebugMessageLog(nullptr),
+ getFramebufferParameteriv(nullptr),
+ getInternalformati64v(nullptr),
+ getPointerv(nullptr),
+ getObjectLabel(nullptr),
+ getObjectPtrLabel(nullptr),
+ getProgramInterfaceiv(nullptr),
+ getProgramResourceIndex(nullptr),
+ getProgramResourceLocation(nullptr),
+ getProgramResourceLocationIndex(nullptr),
+ getProgramResourceName(nullptr),
+ getProgramResourceiv(nullptr),
+ invalidateBufferData(nullptr),
+ invalidateBufferSubData(nullptr),
+ invalidateFramebuffer(nullptr),
+ invalidateSubFramebuffer(nullptr),
+ invalidateTexImage(nullptr),
+ invalidateTexSubImage(nullptr),
+ multiDrawArraysIndirect(nullptr),
+ multiDrawElementsIndirect(nullptr),
+ objectLabel(nullptr),
+ objectPtrLabel(nullptr),
+ popDebugGroup(nullptr),
+ pushDebugGroup(nullptr),
+ shaderStorageBlockBinding(nullptr),
+ texBufferRange(nullptr),
+ texStorage2DMultisample(nullptr),
+ texStorage3DMultisample(nullptr),
+ textureView(nullptr),
+ vertexAttribBinding(nullptr),
+ vertexAttribFormat(nullptr),
+ vertexAttribIFormat(nullptr),
+ vertexAttribLFormat(nullptr),
+ vertexBindingDivisor(nullptr),
+ coverageModulationNV(nullptr),
+
+ bindBuffersBase(nullptr),
+ bindBuffersRange(nullptr),
+ bindImageTextures(nullptr),
+ bindSamplers(nullptr),
+ bindTextures(nullptr),
+ bindVertexBuffers(nullptr),
+ bufferStorage(nullptr),
+ clearTexImage(nullptr),
+ clearTexSubImage(nullptr),
+
+ bindTextureUnit(nullptr),
+ blitNamedFramebuffer(nullptr),
+ checkNamedFramebufferStatus(nullptr),
+ clearNamedBufferData(nullptr),
+ clearNamedBufferSubData(nullptr),
+ clearNamedFramebufferfi(nullptr),
+ clearNamedFramebufferfv(nullptr),
+ clearNamedFramebufferiv(nullptr),
+ clearNamedFramebufferuiv(nullptr),
+ clipControl(nullptr),
+ compressedTextureSubImage1D(nullptr),
+ compressedTextureSubImage2D(nullptr),
+ compressedTextureSubImage3D(nullptr),
+ copyNamedBufferSubData(nullptr),
+ copyTextureSubImage1D(nullptr),
+ copyTextureSubImage2D(nullptr),
+ copyTextureSubImage3D(nullptr),
+ createBuffers(nullptr),
+ createFramebuffers(nullptr),
+ createProgramPipelines(nullptr),
+ createQueries(nullptr),
+ createRenderbuffers(nullptr),
+ createSamplers(nullptr),
+ createTextures(nullptr),
+ createTransformFeedbacks(nullptr),
+ createVertexArrays(nullptr),
+ disableVertexArrayAttrib(nullptr),
+ enableVertexArrayAttrib(nullptr),
+ flushMappedNamedBufferRange(nullptr),
+ generateTextureMipmap(nullptr),
+ getCompressedTextureImage(nullptr),
+ getCompressedTextureSubImage(nullptr),
+ getGraphicsResetStatus(nullptr),
+ getNamedBufferParameteri64v(nullptr),
+ getNamedBufferParameteriv(nullptr),
+ getNamedBufferPointerv(nullptr),
+ getNamedBufferSubData(nullptr),
+ getNamedFramebufferAttachmentParameteriv(nullptr),
+ getNamedFramebufferParameteriv(nullptr),
+ getNamedRenderbufferParameteriv(nullptr),
+ getQueryBufferObjecti64v(nullptr),
+ getQueryBufferObjectiv(nullptr),
+ getQueryBufferObjectui64v(nullptr),
+ getQueryBufferObjectuiv(nullptr),
+ getTextureImage(nullptr),
+ getTextureLevelParameterfv(nullptr),
+ getTextureLevelParameteriv(nullptr),
+ getTextureParameterIiv(nullptr),
+ getTextureParameterIuiv(nullptr),
+ getTextureParameterfv(nullptr),
+ getTextureParameteriv(nullptr),
+ getTextureSubImage(nullptr),
+ getTransformFeedbacki64_v(nullptr),
+ getTransformFeedbacki_v(nullptr),
+ getTransformFeedbackiv(nullptr),
+ getVertexArrayIndexed64iv(nullptr),
+ getVertexArrayIndexediv(nullptr),
+ getVertexArrayiv(nullptr),
+ getnCompressedTexImage(nullptr),
+ getnTexImage(nullptr),
+ getnUniformdv(nullptr),
+ getnUniformfv(nullptr),
+ getnUniformiv(nullptr),
+ getnUniformuiv(nullptr),
+ invalidateNamedFramebufferData(nullptr),
+ invalidateNamedFramebufferSubData(nullptr),
+ mapNamedBuffer(nullptr),
+ mapNamedBufferRange(nullptr),
+ memoryBarrierByRegion(nullptr),
+ namedBufferData(nullptr),
+ namedBufferStorage(nullptr),
+ namedBufferSubData(nullptr),
+ namedFramebufferDrawBuffer(nullptr),
+ namedFramebufferDrawBuffers(nullptr),
+ namedFramebufferParameteri(nullptr),
+ namedFramebufferReadBuffer(nullptr),
+ namedFramebufferRenderbuffer(nullptr),
+ namedFramebufferTexture(nullptr),
+ namedFramebufferTextureLayer(nullptr),
+ namedRenderbufferStorage(nullptr),
+ namedRenderbufferStorageMultisample(nullptr),
+ readnPixels(nullptr),
+ textureBarrier(nullptr),
+ textureBuffer(nullptr),
+ textureBufferRange(nullptr),
+ textureParameterIiv(nullptr),
+ textureParameterIuiv(nullptr),
+ textureParameterf(nullptr),
+ textureParameterfv(nullptr),
+ textureParameteri(nullptr),
+ textureParameteriv(nullptr),
+ textureStorage1D(nullptr),
+ textureStorage2D(nullptr),
+ textureStorage2DMultisample(nullptr),
+ textureStorage3D(nullptr),
+ textureStorage3DMultisample(nullptr),
+ textureSubImage1D(nullptr),
+ textureSubImage2D(nullptr),
+ textureSubImage3D(nullptr),
+ transformFeedbackBufferBase(nullptr),
+ transformFeedbackBufferRange(nullptr),
+ unmapNamedBuffer(nullptr),
+ vertexArrayAttribBinding(nullptr),
+ vertexArrayAttribFormat(nullptr),
+ vertexArrayAttribIFormat(nullptr),
+ vertexArrayAttribLFormat(nullptr),
+ vertexArrayBindingDivisor(nullptr),
+ vertexArrayElementBuffer(nullptr),
+ vertexArrayVertexBuffer(nullptr),
+ vertexArrayVertexBuffers(nullptr),
+ blendBarrier(nullptr),
+ primitiveBoundingBox(nullptr),
+ eglImageTargetRenderbufferStorageOES(nullptr),
+ eglImageTargetTexture2DOES(nullptr)
+{
+}
+
+FunctionsGL::~FunctionsGL()
+{
+}
+
+void FunctionsGL::initialize()
+{
+ // Grab the version number
+ AssignGLEntryPoint(loadProcAddress("glGetString"), &getString);
+ AssignGLEntryPoint(loadProcAddress("glGetIntegerv"), &getIntegerv);
+ GetGLVersion(getString, &version, &standard);
+
+ // Grab the GL extensions
+ if (isAtLeastGL(gl::Version(3, 0)) || isAtLeastGLES(gl::Version(3, 0)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glGetStringi"), &getStringi);
+ extensions = GetIndexedExtensions(getIntegerv, getStringi);
+ }
+ else
+ {
+ const char *exts = reinterpret_cast<const char*>(getString(GL_EXTENSIONS));
+ angle::SplitStringAlongWhitespace(std::string(exts), &extensions);
+ }
+
+ // Load the entry points
+ switch (standard)
+ {
+ case STANDARD_GL_DESKTOP:
+ initializeProcsDesktopGL();
+ break;
+
+ case STANDARD_GL_ES:
+ initializeProcsGLES();
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void FunctionsGL::initializeProcsDesktopGL()
+{
+ // Check the context profile
+ profile = 0;
+ if (isAtLeastGL(gl::Version(3, 2)))
+ {
+ getIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
+ }
+
+ // clang-format off
+
+ // Load extensions
+ // Even though extensions are written against specific versions of GL, many drivers expose the extensions
+ // in even older versions. Always try loading the extensions regardless of GL version.
+
+ // GL_ARB_program_interface_query (loading only functions relevant to GL_NV_path_rendering here)
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_program_interface_query", loadProcAddress("glGetProgramInterfaceiv"), &getProgramInterfaceiv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_program_interface_query", loadProcAddress("glGetProgramResourceName"), &getProgramResourceName);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_program_interface_query", loadProcAddress("glGetProgramResourceiv"), &getProgramResourceiv);
+
+ // GL_NV_path_rendering
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glMatrixLoadfEXT"), &matrixLoadEXT);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGenPathsNV"), &genPathsNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glDeletePathsNV"), &delPathsNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathCommandsNV"), &pathCommandsNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glIsPathNV"), &isPathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathParameterfNV"), &setPathParameterfNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathParameteriNV"), &setPathParameteriNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGetPathParameterfvNV"), &getPathParameterfNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGetPathParameterivNV"), &getPathParameteriNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathStencilFuncNV"), &pathStencilFuncNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilFillPathNV"), &stencilFillPathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilStrokePathNV"), &stencilStrokePathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverFillPathNV"), &coverFillPathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverStrokePathNV"), &coverStrokePathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverFillPathNV"), &stencilThenCoverFillPathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverStrokePathNV"), &stencilThenCoverStrokePathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverFillPathInstancedNV"), &coverFillPathInstancedNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverStrokePathInstancedNV"), &coverStrokePathInstancedNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilFillPathInstancedNV"), &stencilFillPathInstancedNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilStrokePathInstancedNV"), &stencilStrokePathInstancedNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverFillPathInstancedNV"), &stencilThenCoverFillPathInstancedNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverStrokePathInstancedNV"), &stencilThenCoverStrokePathInstancedNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glProgramPathFragmentInputGenNV"), &programPathFragmentInputGenNV);
+
+ // GL_NV_framebuffer_mixed_samples
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_framebuffer_mixed_samples", loadProcAddress("glCoverageModulationNV"), &coverageModulationNV);
+
+ // GL_NV_fence
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glDeleteFencesNV"), &deleteFencesNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glGenFencesNV"), &genFencesNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glIsFenceNV"), &isFenceNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glTestFenceNV"), &testFenceNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glGetFenceivNV"), &getFenceivNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glFinishFenceNV"), &finishFenceNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glSetFenceNV"), &setFenceNV);
+
+ // GL_EXT_texture_storage
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage", loadProcAddress("glTexStorage1DEXT"), &texStorage1D);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage", loadProcAddress("glTexStorage2DEXT"), &texStorage2D);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage GL_EXT_texture3D", loadProcAddress("glTexStorage3DEXT"), &texStorage3D);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage GL_EXT_direct_state_access", loadProcAddress("glTextureStorage1DEXT"), &textureStorage1D);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage GL_EXT_direct_state_access", loadProcAddress("glTextureStorage2DEXT"), &textureStorage2D);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage GL_EXT_direct_state_access GL_EXT_texture3D", loadProcAddress("glTextureStorage3DEXT"), &textureStorage3D);
+
+ // GL_ARB_vertex_array_object
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_vertex_array_object", loadProcAddress("glBindVertexArray"), &bindVertexArray);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_vertex_array_object", loadProcAddress("glDeleteVertexArrays"), &deleteVertexArrays);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_vertex_array_object", loadProcAddress("glGenVertexArrays"), &genVertexArrays);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_vertex_array_object", loadProcAddress("glIsVertexArray"), &isVertexArray);
+
+ // GL_ARB_sync
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glClientWaitSync"), &clientWaitSync);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glDeleteSync"), &deleteSync);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glFenceSync"), &fenceSync);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glGetInteger64i_v"), &getInteger64i_v);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glGetInteger64v"), &getInteger64v);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glGetSynciv"), &getSynciv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glIsSync"), &isSync);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sync", loadProcAddress("glWaitSync"), &waitSync);
+
+ // GL_EXT_framebuffer_object
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glIsRenderbufferEXT"), &isRenderbuffer);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glBindRenderbufferEXT"), &bindRenderbuffer);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glDeleteRenderbuffersEXT"), &deleteRenderbuffers);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glGenRenderbuffersEXT"), &genRenderbuffers);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glRenderbufferStorageEXT"), &renderbufferStorage);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glGetRenderbufferParameterivEXT"), &getRenderbufferParameteriv);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glIsFramebufferEXT"), &isFramebuffer);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glBindFramebufferEXT"), &bindFramebuffer);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glDeleteFramebuffersEXT"), &deleteFramebuffers);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glGenFramebuffersEXT"), &genFramebuffers);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glCheckFramebufferStatusEXT"), &checkFramebufferStatus);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glFramebufferTexture1DEXT"), &framebufferTexture1D);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glFramebufferTexture2DEXT"), &framebufferTexture2D);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glFramebufferTexture3DEXT"), &framebufferTexture3D);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glFramebufferRenderbufferEXT"), &framebufferRenderbuffer);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glGetFramebufferAttachmentParameterivEXT"), &getFramebufferAttachmentParameteriv);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_object", loadProcAddress("glGenerateMipmapEXT"), &generateMipmap);
+
+ // GL_EXT_framebuffer_blit
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_framebuffer_blit", loadProcAddress("glBlitFramebufferEXT"), &blitFramebuffer);
+
+ // GL_KHR_debug
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glDebugMessageControl"), &debugMessageControl);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glDebugMessageInsert"), &debugMessageInsert);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glDebugMessageCallback"), &debugMessageCallback);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetDebugMessageLog"), &getDebugMessageLog);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetPointerv"), &getPointerv);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glPushDebugGroup"), &pushDebugGroup);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glPopDebugGroup"), &popDebugGroup);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glObjectLabel"), &objectLabel);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetObjectLabel"), &getObjectLabel);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glObjectPtrLabel"), &objectPtrLabel);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetObjectPtrLabel"), &getObjectPtrLabel);
+
+ // GL_ARB_internalformat_query
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_internalformat_query", loadProcAddress("glGetInternalformativ"), &getInternalformativ);
+
+ // GL_ARB_ES2_compatibility
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_ES2_compatibility", loadProcAddress("glReleaseShaderCompiler"), &releaseShaderCompiler);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_ES2_compatibility", loadProcAddress("glShaderBinary"), &shaderBinary);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_ES2_compatibility", loadProcAddress("glGetShaderPrecisionFormat"), &getShaderPrecisionFormat);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_ES2_compatibility", loadProcAddress("glDepthRangef"), &depthRangef);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_ES2_compatibility", loadProcAddress("glClearDepthf"), &clearDepthf);
+
+ // GL_ARB_instanced_arrays
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_instanced_arrays", loadProcAddress("glVertexAttribDivisorARB"), &vertexAttribDivisor);
+
+ // GL_EXT_draw_instanced
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glDrawArraysInstancedEXT"), &drawArraysInstanced);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glDrawElementsInstancedEXT"), &drawElementsInstanced);
+
+ // GL_ARB_draw_instanced
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_draw_instanced", loadProcAddress("glDrawArraysInstancedARB"), &drawArraysInstanced);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_draw_instanced", loadProcAddress("glDrawElementsInstancedARB"), &drawElementsInstanced);
+
+ // GL_ARB_sampler_objects
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGenSamplers"), &genSamplers);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glDeleteSamplers"), &deleteSamplers);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glIsSampler"), &isSampler);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glBindSampler"), &bindSampler);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSamplerParameteri"), &samplerParameteri);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSamplerParameterf"), &samplerParameterf);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSamplerParameteriv"), &samplerParameteriv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSamplerParameterfv"), &samplerParameterfv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSamplerParameterIiv"), &samplerParameterIiv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glSamplerParameterIuiv"), &samplerParameterIuiv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGetSamplerParameteriv"), &getSamplerParameteriv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGetSamplerParameterfv"), &getSamplerParameterfv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGetSamplerParameterIiv"), &getSamplerParameterIiv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGetSamplerParameterIuiv"), &getSamplerParameterIuiv);
+
+ // GL_ARB_occlusion_query
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGenQueriesARB"), &genQueries);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glDeleteQueriesARB"), &deleteQueries);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glIsQueryARB"), &isQuery);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glBeginQueryARB"), &beginQuery);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glEndQueryARB"), &endQuery);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryivARB"), &getQueryiv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryObjectivARB"), &getQueryObjectiv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryObjectuivARB"), &getQueryObjectuiv);
+
+ // EXT_transform_feedback
+ AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBindBufferRangeEXT"), &bindBufferRange);
+ AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBindBufferBaseEXT"), &bindBufferBase);
+ AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBeginTransformFeedbackEXT"), &beginTransformFeedback);
+ AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glEndTransformFeedbackEXT"), &endTransformFeedback);
+ AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glTransformFeedbackVaryingsEXT"), &transformFeedbackVaryings);
+ AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glGetTransformFeedbackVaryingEXT"), &getTransformFeedbackVarying);
+
+ // GL_ARB_transform_feedback2
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glBindTransformFeedback"), &bindTransformFeedback);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glDeleteTransformFeedbacks"), &deleteTransformFeedbacks);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glGenTransformFeedbacks"), &genTransformFeedbacks);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glIsTransformFeedback"), &isTransformFeedback);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glPauseTransformFeedback"), &pauseTransformFeedback);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glResumeTransformFeedback"), &resumeTransformFeedback);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glDrawTransformFeedback"), &drawTransformFeedback);
+
+ // GL_ARB_transform_feedback3
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glDrawTransformFeedbackStream"), &drawTransformFeedbackStream);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glBeginQueryIndexed"), &beginQueryIndexed);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glEndQueryIndexed"), &endQueryIndexed);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glGetQueryIndexediv"), &getQueryIndexediv);
+
+ // GL_ARB_get_program_binary
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_get_program_binary", loadProcAddress("glGetProgramBinary"), &getProgramBinary);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_get_program_binary", loadProcAddress("glProgramBinary"), &programBinary);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_get_program_binary", loadProcAddress("glProgramParameteri"), &programParameteri);
+
+ // GL_ARB_robustness
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_robustness", loadProcAddress("glGetGraphicsResetStatusARB"), &getGraphicsResetStatus);
+
+ // GL_KHR_robustness
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_robustness", loadProcAddress("glGetGraphicsResetStatus"), &getGraphicsResetStatus);
+
+ // 1.0
+ if (isAtLeastGL(gl::Version(1, 0)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBlendFunc"), &blendFunc);
+ AssignGLEntryPoint(loadProcAddress("glClear"), &clear);
+ AssignGLEntryPoint(loadProcAddress("glClearColor"), &clearColor);
+ AssignGLEntryPoint(loadProcAddress("glClearDepth"), &clearDepth);
+ AssignGLEntryPoint(loadProcAddress("glClearStencil"), &clearStencil);
+ AssignGLEntryPoint(loadProcAddress("glColorMask"), &colorMask);
+ AssignGLEntryPoint(loadProcAddress("glCullFace"), &cullFace);
+ AssignGLEntryPoint(loadProcAddress("glDepthFunc"), &depthFunc);
+ AssignGLEntryPoint(loadProcAddress("glDepthMask"), &depthMask);
+ AssignGLEntryPoint(loadProcAddress("glDepthRange"), &depthRange);
+ AssignGLEntryPoint(loadProcAddress("glDisable"), &disable);
+ AssignGLEntryPoint(loadProcAddress("glDrawBuffer"), &drawBuffer);
+ AssignGLEntryPoint(loadProcAddress("glEnable"), &enable);
+ AssignGLEntryPoint(loadProcAddress("glFinish"), &finish);
+ AssignGLEntryPoint(loadProcAddress("glFlush"), &flush);
+ AssignGLEntryPoint(loadProcAddress("glFrontFace"), &frontFace);
+ AssignGLEntryPoint(loadProcAddress("glGetBooleanv"), &getBooleanv);
+ AssignGLEntryPoint(loadProcAddress("glGetDoublev"), &getDoublev);
+ AssignGLEntryPoint(loadProcAddress("glGetError"), &getError);
+ AssignGLEntryPoint(loadProcAddress("glGetFloatv"), &getFloatv);
+ AssignGLEntryPoint(loadProcAddress("glGetIntegerv"), &getIntegerv);
+ AssignGLEntryPoint(loadProcAddress("glGetString"), &getString);
+ AssignGLEntryPoint(loadProcAddress("glGetTexImage"), &getTexImage);
+ AssignGLEntryPoint(loadProcAddress("glGetTexLevelParameterfv"), &getTexLevelParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glGetTexLevelParameteriv"), &getTexLevelParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetTexParameterfv"), &getTexParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glGetTexParameteriv"), &getTexParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glHint"), &hint);
+ AssignGLEntryPoint(loadProcAddress("glIsEnabled"), &isEnabled);
+ AssignGLEntryPoint(loadProcAddress("glLineWidth"), &lineWidth);
+ AssignGLEntryPoint(loadProcAddress("glLogicOp"), &logicOp);
+ AssignGLEntryPoint(loadProcAddress("glPixelStoref"), &pixelStoref);
+ AssignGLEntryPoint(loadProcAddress("glPixelStorei"), &pixelStorei);
+ AssignGLEntryPoint(loadProcAddress("glPointSize"), &pointSize);
+ AssignGLEntryPoint(loadProcAddress("glPolygonMode"), &polygonMode);
+ AssignGLEntryPoint(loadProcAddress("glReadBuffer"), &readBuffer);
+ AssignGLEntryPoint(loadProcAddress("glReadPixels"), &readPixels);
+ AssignGLEntryPoint(loadProcAddress("glScissor"), &scissor);
+ AssignGLEntryPoint(loadProcAddress("glStencilFunc"), &stencilFunc);
+ AssignGLEntryPoint(loadProcAddress("glStencilMask"), &stencilMask);
+ AssignGLEntryPoint(loadProcAddress("glStencilOp"), &stencilOp);
+ AssignGLEntryPoint(loadProcAddress("glTexImage1D"), &texImage1D);
+ AssignGLEntryPoint(loadProcAddress("glTexImage2D"), &texImage2D);
+ AssignGLEntryPoint(loadProcAddress("glTexParameterf"), &texParameterf);
+ AssignGLEntryPoint(loadProcAddress("glTexParameterfv"), &texParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glTexParameteri"), &texParameteri);
+ AssignGLEntryPoint(loadProcAddress("glTexParameteriv"), &texParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glViewport"), &viewport);
+ }
+
+ // 1.1
+ if (isAtLeastGL(gl::Version(1, 1)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBindTexture"), &bindTexture);
+ AssignGLEntryPoint(loadProcAddress("glCopyTexImage1D"), &copyTexImage1D);
+ AssignGLEntryPoint(loadProcAddress("glCopyTexImage2D"), &copyTexImage2D);
+ AssignGLEntryPoint(loadProcAddress("glCopyTexSubImage1D"), &copyTexSubImage1D);
+ AssignGLEntryPoint(loadProcAddress("glCopyTexSubImage2D"), &copyTexSubImage2D);
+ AssignGLEntryPoint(loadProcAddress("glDeleteTextures"), &deleteTextures);
+ AssignGLEntryPoint(loadProcAddress("glDrawArrays"), &drawArrays);
+ AssignGLEntryPoint(loadProcAddress("glDrawElements"), &drawElements);
+ AssignGLEntryPoint(loadProcAddress("glGenTextures"), &genTextures);
+ AssignGLEntryPoint(loadProcAddress("glIsTexture"), &isTexture);
+ AssignGLEntryPoint(loadProcAddress("glPolygonOffset"), &polygonOffset);
+ AssignGLEntryPoint(loadProcAddress("glTexSubImage1D"), &texSubImage1D);
+ AssignGLEntryPoint(loadProcAddress("glTexSubImage2D"), &texSubImage2D);
+ }
+
+ // 1.2
+ if (isAtLeastGL(gl::Version(1, 2)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBlendColor"), &blendColor);
+ AssignGLEntryPoint(loadProcAddress("glBlendEquation"), &blendEquation);
+ AssignGLEntryPoint(loadProcAddress("glCopyTexSubImage3D"), &copyTexSubImage3D);
+ AssignGLEntryPoint(loadProcAddress("glDrawRangeElements"), &drawRangeElements);
+ AssignGLEntryPoint(loadProcAddress("glTexImage3D"), &texImage3D);
+ AssignGLEntryPoint(loadProcAddress("glTexSubImage3D"), &texSubImage3D);
+ }
+
+ // 1.3
+ if (isAtLeastGL(gl::Version(1, 3)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glActiveTexture"), &activeTexture);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTexImage1D"), &compressedTexImage1D);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTexImage2D"), &compressedTexImage2D);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTexImage3D"), &compressedTexImage3D);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTexSubImage1D"), &compressedTexSubImage1D);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTexSubImage2D"), &compressedTexSubImage2D);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTexSubImage3D"), &compressedTexSubImage3D);
+ AssignGLEntryPoint(loadProcAddress("glGetCompressedTexImage"), &getCompressedTexImage);
+ AssignGLEntryPoint(loadProcAddress("glSampleCoverage"), &sampleCoverage);
+ }
+
+ // 1.4
+ if (isAtLeastGL(gl::Version(1, 4)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBlendFuncSeparate"), &blendFuncSeparate);
+ AssignGLEntryPoint(loadProcAddress("glMultiDrawArrays"), &multiDrawArrays);
+ AssignGLEntryPoint(loadProcAddress("glMultiDrawElements"), &multiDrawElements);
+ AssignGLEntryPoint(loadProcAddress("glPointParameterf"), &pointParameterf);
+ AssignGLEntryPoint(loadProcAddress("glPointParameterfv"), &pointParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glPointParameteri"), &pointParameteri);
+ AssignGLEntryPoint(loadProcAddress("glPointParameteriv"), &pointParameteriv);
+ }
+
+ // 1.5
+ if (isAtLeastGL(gl::Version(1, 5)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBeginQuery"), &beginQuery);
+ AssignGLEntryPoint(loadProcAddress("glBindBuffer"), &bindBuffer);
+ AssignGLEntryPoint(loadProcAddress("glBufferData"), &bufferData);
+ AssignGLEntryPoint(loadProcAddress("glBufferSubData"), &bufferSubData);
+ AssignGLEntryPoint(loadProcAddress("glDeleteBuffers"), &deleteBuffers);
+ AssignGLEntryPoint(loadProcAddress("glDeleteQueries"), &deleteQueries);
+ AssignGLEntryPoint(loadProcAddress("glEndQuery"), &endQuery);
+ AssignGLEntryPoint(loadProcAddress("glGenBuffers"), &genBuffers);
+ AssignGLEntryPoint(loadProcAddress("glGenQueries"), &genQueries);
+ AssignGLEntryPoint(loadProcAddress("glGetBufferParameteriv"), &getBufferParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetBufferPointerv"), &getBufferPointerv);
+ AssignGLEntryPoint(loadProcAddress("glGetBufferSubData"), &getBufferSubData);
+ AssignGLEntryPoint(loadProcAddress("glGetQueryObjectiv"), &getQueryObjectiv);
+ AssignGLEntryPoint(loadProcAddress("glGetQueryObjectuiv"), &getQueryObjectuiv);
+ AssignGLEntryPoint(loadProcAddress("glGetQueryiv"), &getQueryiv);
+ AssignGLEntryPoint(loadProcAddress("glIsBuffer"), &isBuffer);
+ AssignGLEntryPoint(loadProcAddress("glIsQuery"), &isQuery);
+ AssignGLEntryPoint(loadProcAddress("glMapBuffer"), &mapBuffer);
+ AssignGLEntryPoint(loadProcAddress("glUnmapBuffer"), &unmapBuffer);
+ }
+
+ // 2.0
+ if (isAtLeastGL(gl::Version(2, 0)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glAttachShader"), &attachShader);
+ AssignGLEntryPoint(loadProcAddress("glBindAttribLocation"), &bindAttribLocation);
+ AssignGLEntryPoint(loadProcAddress("glBlendEquationSeparate"), &blendEquationSeparate);
+ AssignGLEntryPoint(loadProcAddress("glCompileShader"), &compileShader);
+ AssignGLEntryPoint(loadProcAddress("glCreateProgram"), &createProgram);
+ AssignGLEntryPoint(loadProcAddress("glCreateShader"), &createShader);
+ AssignGLEntryPoint(loadProcAddress("glDeleteProgram"), &deleteProgram);
+ AssignGLEntryPoint(loadProcAddress("glDeleteShader"), &deleteShader);
+ AssignGLEntryPoint(loadProcAddress("glDetachShader"), &detachShader);
+ AssignGLEntryPoint(loadProcAddress("glDisableVertexAttribArray"), &disableVertexAttribArray);
+ AssignGLEntryPoint(loadProcAddress("glDrawBuffers"), &drawBuffers);
+ AssignGLEntryPoint(loadProcAddress("glEnableVertexAttribArray"), &enableVertexAttribArray);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveAttrib"), &getActiveAttrib);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveUniform"), &getActiveUniform);
+ AssignGLEntryPoint(loadProcAddress("glGetAttachedShaders"), &getAttachedShaders);
+ AssignGLEntryPoint(loadProcAddress("glGetAttribLocation"), &getAttribLocation);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramInfoLog"), &getProgramInfoLog);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramiv"), &getProgramiv);
+ AssignGLEntryPoint(loadProcAddress("glGetShaderInfoLog"), &getShaderInfoLog);
+ AssignGLEntryPoint(loadProcAddress("glGetShaderSource"), &getShaderSource);
+ AssignGLEntryPoint(loadProcAddress("glGetShaderiv"), &getShaderiv);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformLocation"), &getUniformLocation);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformfv"), &getUniformfv);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformiv"), &getUniformiv);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexAttribPointerv"), &getVertexAttribPointerv);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexAttribdv"), &getVertexAttribdv);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexAttribfv"), &getVertexAttribfv);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexAttribiv"), &getVertexAttribiv);
+ AssignGLEntryPoint(loadProcAddress("glIsProgram"), &isProgram);
+ AssignGLEntryPoint(loadProcAddress("glIsShader"), &isShader);
+ AssignGLEntryPoint(loadProcAddress("glLinkProgram"), &linkProgram);
+ AssignGLEntryPoint(loadProcAddress("glShaderSource"), &shaderSource);
+ AssignGLEntryPoint(loadProcAddress("glStencilFuncSeparate"), &stencilFuncSeparate);
+ AssignGLEntryPoint(loadProcAddress("glStencilMaskSeparate"), &stencilMaskSeparate);
+ AssignGLEntryPoint(loadProcAddress("glStencilOpSeparate"), &stencilOpSeparate);
+ AssignGLEntryPoint(loadProcAddress("glUniform1f"), &uniform1f);
+ AssignGLEntryPoint(loadProcAddress("glUniform1fv"), &uniform1fv);
+ AssignGLEntryPoint(loadProcAddress("glUniform1i"), &uniform1i);
+ AssignGLEntryPoint(loadProcAddress("glUniform1iv"), &uniform1iv);
+ AssignGLEntryPoint(loadProcAddress("glUniform2f"), &uniform2f);
+ AssignGLEntryPoint(loadProcAddress("glUniform2fv"), &uniform2fv);
+ AssignGLEntryPoint(loadProcAddress("glUniform2i"), &uniform2i);
+ AssignGLEntryPoint(loadProcAddress("glUniform2iv"), &uniform2iv);
+ AssignGLEntryPoint(loadProcAddress("glUniform3f"), &uniform3f);
+ AssignGLEntryPoint(loadProcAddress("glUniform3fv"), &uniform3fv);
+ AssignGLEntryPoint(loadProcAddress("glUniform3i"), &uniform3i);
+ AssignGLEntryPoint(loadProcAddress("glUniform3iv"), &uniform3iv);
+ AssignGLEntryPoint(loadProcAddress("glUniform4f"), &uniform4f);
+ AssignGLEntryPoint(loadProcAddress("glUniform4fv"), &uniform4fv);
+ AssignGLEntryPoint(loadProcAddress("glUniform4i"), &uniform4i);
+ AssignGLEntryPoint(loadProcAddress("glUniform4iv"), &uniform4iv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix2fv"), &uniformMatrix2fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix3fv"), &uniformMatrix3fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix4fv"), &uniformMatrix4fv);
+ AssignGLEntryPoint(loadProcAddress("glUseProgram"), &useProgram);
+ AssignGLEntryPoint(loadProcAddress("glValidateProgram"), &validateProgram);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib1d"), &vertexAttrib1d);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib1dv"), &vertexAttrib1dv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib1f"), &vertexAttrib1f);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib1fv"), &vertexAttrib1fv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib1s"), &vertexAttrib1s);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib1sv"), &vertexAttrib1sv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib2d"), &vertexAttrib2d);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib2dv"), &vertexAttrib2dv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib2f"), &vertexAttrib2f);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib2fv"), &vertexAttrib2fv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib2s"), &vertexAttrib2s);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib2sv"), &vertexAttrib2sv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib3d"), &vertexAttrib3d);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib3dv"), &vertexAttrib3dv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib3f"), &vertexAttrib3f);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib3fv"), &vertexAttrib3fv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib3s"), &vertexAttrib3s);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib3sv"), &vertexAttrib3sv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Nbv"), &vertexAttrib4Nbv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Niv"), &vertexAttrib4Niv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Nsv"), &vertexAttrib4Nsv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Nub"), &vertexAttrib4Nub);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Nubv"), &vertexAttrib4Nubv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Nuiv"), &vertexAttrib4Nuiv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4Nusv"), &vertexAttrib4Nusv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4bv"), &vertexAttrib4bv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4d"), &vertexAttrib4d);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4dv"), &vertexAttrib4dv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4f"), &vertexAttrib4f);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4fv"), &vertexAttrib4fv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4iv"), &vertexAttrib4iv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4s"), &vertexAttrib4s);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4sv"), &vertexAttrib4sv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4ubv"), &vertexAttrib4ubv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4uiv"), &vertexAttrib4uiv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4usv"), &vertexAttrib4usv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribPointer"), &vertexAttribPointer);
+ }
+
+ // 2.1
+ if (isAtLeastGL(gl::Version(2, 1)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix2x3fv"), &uniformMatrix2x3fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix2x4fv"), &uniformMatrix2x4fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix3x2fv"), &uniformMatrix3x2fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix3x4fv"), &uniformMatrix3x4fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix4x2fv"), &uniformMatrix4x2fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix4x3fv"), &uniformMatrix4x3fv);
+ }
+
+ // 3.0
+ if (isAtLeastGL(gl::Version(3, 0)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBeginConditionalRender"), &beginConditionalRender);
+ AssignGLEntryPoint(loadProcAddress("glBeginTransformFeedback"), &beginTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glBindBufferBase"), &bindBufferBase);
+ AssignGLEntryPoint(loadProcAddress("glBindBufferRange"), &bindBufferRange);
+ AssignGLEntryPoint(loadProcAddress("glBindFragDataLocation"), &bindFragDataLocation);
+ AssignGLEntryPoint(loadProcAddress("glBindFramebuffer"), &bindFramebuffer);
+ AssignGLEntryPoint(loadProcAddress("glBindRenderbuffer"), &bindRenderbuffer);
+ AssignGLEntryPoint(loadProcAddress("glBindVertexArray"), &bindVertexArray);
+ AssignGLEntryPoint(loadProcAddress("glBlitFramebuffer"), &blitFramebuffer);
+ AssignGLEntryPoint(loadProcAddress("glCheckFramebufferStatus"), &checkFramebufferStatus);
+ AssignGLEntryPoint(loadProcAddress("glClampColor"), &clampColor);
+ AssignGLEntryPoint(loadProcAddress("glClearBufferfi"), &clearBufferfi);
+ AssignGLEntryPoint(loadProcAddress("glClearBufferfv"), &clearBufferfv);
+ AssignGLEntryPoint(loadProcAddress("glClearBufferiv"), &clearBufferiv);
+ AssignGLEntryPoint(loadProcAddress("glClearBufferuiv"), &clearBufferuiv);
+ AssignGLEntryPoint(loadProcAddress("glColorMaski"), &colorMaski);
+ AssignGLEntryPoint(loadProcAddress("glDeleteFramebuffers"), &deleteFramebuffers);
+ AssignGLEntryPoint(loadProcAddress("glDeleteRenderbuffers"), &deleteRenderbuffers);
+ AssignGLEntryPoint(loadProcAddress("glDeleteVertexArrays"), &deleteVertexArrays);
+ AssignGLEntryPoint(loadProcAddress("glDisablei"), &disablei);
+ AssignGLEntryPoint(loadProcAddress("glEnablei"), &enablei);
+ AssignGLEntryPoint(loadProcAddress("glEndConditionalRender"), &endConditionalRender);
+ AssignGLEntryPoint(loadProcAddress("glEndTransformFeedback"), &endTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glFlushMappedBufferRange"), &flushMappedBufferRange);
+ AssignGLEntryPoint(loadProcAddress("glFramebufferRenderbuffer"), &framebufferRenderbuffer);
+ AssignGLEntryPoint(loadProcAddress("glFramebufferTexture1D"), &framebufferTexture1D);
+ AssignGLEntryPoint(loadProcAddress("glFramebufferTexture2D"), &framebufferTexture2D);
+ AssignGLEntryPoint(loadProcAddress("glFramebufferTexture3D"), &framebufferTexture3D);
+ AssignGLEntryPoint(loadProcAddress("glFramebufferTextureLayer"), &framebufferTextureLayer);
+ AssignGLEntryPoint(loadProcAddress("glGenFramebuffers"), &genFramebuffers);
+ AssignGLEntryPoint(loadProcAddress("glGenRenderbuffers"), &genRenderbuffers);
+ AssignGLEntryPoint(loadProcAddress("glGenVertexArrays"), &genVertexArrays);
+ AssignGLEntryPoint(loadProcAddress("glGenerateMipmap"), &generateMipmap);
+ AssignGLEntryPoint(loadProcAddress("glGetBooleani_v"), &getBooleani_v);
+ AssignGLEntryPoint(loadProcAddress("glGetFragDataLocation"), &getFragDataLocation);
+ AssignGLEntryPoint(loadProcAddress("glGetFramebufferAttachmentParameteriv"), &getFramebufferAttachmentParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetIntegeri_v"), &getIntegeri_v);
+ AssignGLEntryPoint(loadProcAddress("glGetRenderbufferParameteriv"), &getRenderbufferParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetStringi"), &getStringi);
+ AssignGLEntryPoint(loadProcAddress("glGetTexParameterIiv"), &getTexParameterIiv);
+ AssignGLEntryPoint(loadProcAddress("glGetTexParameterIuiv"), &getTexParameterIuiv);
+ AssignGLEntryPoint(loadProcAddress("glGetTransformFeedbackVarying"), &getTransformFeedbackVarying);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformuiv"), &getUniformuiv);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexAttribIiv"), &getVertexAttribIiv);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexAttribIuiv"), &getVertexAttribIuiv);
+ AssignGLEntryPoint(loadProcAddress("glIsEnabledi"), &isEnabledi);
+ AssignGLEntryPoint(loadProcAddress("glIsFramebuffer"), &isFramebuffer);
+ AssignGLEntryPoint(loadProcAddress("glIsRenderbuffer"), &isRenderbuffer);
+ AssignGLEntryPoint(loadProcAddress("glIsVertexArray"), &isVertexArray);
+ AssignGLEntryPoint(loadProcAddress("glMapBufferRange"), &mapBufferRange);
+ AssignGLEntryPoint(loadProcAddress("glRenderbufferStorage"), &renderbufferStorage);
+ AssignGLEntryPoint(loadProcAddress("glRenderbufferStorageMultisample"), &renderbufferStorageMultisample);
+ AssignGLEntryPoint(loadProcAddress("glTexParameterIiv"), &texParameterIiv);
+ AssignGLEntryPoint(loadProcAddress("glTexParameterIuiv"), &texParameterIuiv);
+ AssignGLEntryPoint(loadProcAddress("glTransformFeedbackVaryings"), &transformFeedbackVaryings);
+ AssignGLEntryPoint(loadProcAddress("glUniform1ui"), &uniform1ui);
+ AssignGLEntryPoint(loadProcAddress("glUniform1uiv"), &uniform1uiv);
+ AssignGLEntryPoint(loadProcAddress("glUniform2ui"), &uniform2ui);
+ AssignGLEntryPoint(loadProcAddress("glUniform2uiv"), &uniform2uiv);
+ AssignGLEntryPoint(loadProcAddress("glUniform3ui"), &uniform3ui);
+ AssignGLEntryPoint(loadProcAddress("glUniform3uiv"), &uniform3uiv);
+ AssignGLEntryPoint(loadProcAddress("glUniform4ui"), &uniform4ui);
+ AssignGLEntryPoint(loadProcAddress("glUniform4uiv"), &uniform4uiv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI1i"), &vertexAttribI1i);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI1iv"), &vertexAttribI1iv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI1ui"), &vertexAttribI1ui);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI1uiv"), &vertexAttribI1uiv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI2i"), &vertexAttribI2i);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI2iv"), &vertexAttribI2iv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI2ui"), &vertexAttribI2ui);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI2uiv"), &vertexAttribI2uiv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI3i"), &vertexAttribI3i);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI3iv"), &vertexAttribI3iv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI3ui"), &vertexAttribI3ui);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI3uiv"), &vertexAttribI3uiv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI4bv"), &vertexAttribI4bv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI4i"), &vertexAttribI4i);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI4iv"), &vertexAttribI4iv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI4sv"), &vertexAttribI4sv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI4ubv"), &vertexAttribI4ubv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI4ui"), &vertexAttribI4ui);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI4uiv"), &vertexAttribI4uiv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI4usv"), &vertexAttribI4usv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribIPointer"), &vertexAttribIPointer);
+ }
+
+ // 3.1
+ if (isAtLeastGL(gl::Version(3, 1)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glCopyBufferSubData"), &copyBufferSubData);
+ AssignGLEntryPoint(loadProcAddress("glDrawArraysInstanced"), &drawArraysInstanced);
+ AssignGLEntryPoint(loadProcAddress("glDrawElementsInstanced"), &drawElementsInstanced);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveUniformBlockName"), &getActiveUniformBlockName);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveUniformBlockiv"), &getActiveUniformBlockiv);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveUniformName"), &getActiveUniformName);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveUniformsiv"), &getActiveUniformsiv);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformBlockIndex"), &getUniformBlockIndex);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformIndices"), &getUniformIndices);
+ AssignGLEntryPoint(loadProcAddress("glPrimitiveRestartIndex"), &primitiveRestartIndex);
+ AssignGLEntryPoint(loadProcAddress("glTexBuffer"), &texBuffer);
+ AssignGLEntryPoint(loadProcAddress("glUniformBlockBinding"), &uniformBlockBinding);
+ }
+
+ // 3.2
+ if (isAtLeastGL(gl::Version(3, 2)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glClientWaitSync"), &clientWaitSync);
+ AssignGLEntryPoint(loadProcAddress("glDeleteSync"), &deleteSync);
+ AssignGLEntryPoint(loadProcAddress("glDrawElementsBaseVertex"), &drawElementsBaseVertex);
+ AssignGLEntryPoint(loadProcAddress("glDrawElementsInstancedBaseVertex"), &drawElementsInstancedBaseVertex);
+ AssignGLEntryPoint(loadProcAddress("glDrawRangeElementsBaseVertex"), &drawRangeElementsBaseVertex);
+ AssignGLEntryPoint(loadProcAddress("glFenceSync"), &fenceSync);
+ AssignGLEntryPoint(loadProcAddress("glFramebufferTexture"), &framebufferTexture);
+ AssignGLEntryPoint(loadProcAddress("glGetBufferParameteri64v"), &getBufferParameteri64v);
+ AssignGLEntryPoint(loadProcAddress("glGetInteger64i_v"), &getInteger64i_v);
+ AssignGLEntryPoint(loadProcAddress("glGetInteger64v"), &getInteger64v);
+ AssignGLEntryPoint(loadProcAddress("glGetMultisamplefv"), &getMultisamplefv);
+ AssignGLEntryPoint(loadProcAddress("glGetSynciv"), &getSynciv);
+ AssignGLEntryPoint(loadProcAddress("glIsSync"), &isSync);
+ AssignGLEntryPoint(loadProcAddress("glMultiDrawElementsBaseVertex"), &multiDrawElementsBaseVertex);
+ AssignGLEntryPoint(loadProcAddress("glProvokingVertex"), &provokingVertex);
+ AssignGLEntryPoint(loadProcAddress("glSampleMaski"), &sampleMaski);
+ AssignGLEntryPoint(loadProcAddress("glTexImage2DMultisample"), &texImage2DMultisample);
+ AssignGLEntryPoint(loadProcAddress("glTexImage3DMultisample"), &texImage3DMultisample);
+ AssignGLEntryPoint(loadProcAddress("glWaitSync"), &waitSync);
+ }
+
+ // 3.3
+ if (isAtLeastGL(gl::Version(3, 3)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBindFragDataLocationIndexed"), &bindFragDataLocationIndexed);
+ AssignGLEntryPoint(loadProcAddress("glBindSampler"), &bindSampler);
+ AssignGLEntryPoint(loadProcAddress("glDeleteSamplers"), &deleteSamplers);
+ AssignGLEntryPoint(loadProcAddress("glGenSamplers"), &genSamplers);
+ AssignGLEntryPoint(loadProcAddress("glGetFragDataIndex"), &getFragDataIndex);
+ AssignGLEntryPoint(loadProcAddress("glGetQueryObjecti64v"), &getQueryObjecti64v);
+ AssignGLEntryPoint(loadProcAddress("glGetQueryObjectui64v"), &getQueryObjectui64v);
+ AssignGLEntryPoint(loadProcAddress("glGetSamplerParameterIiv"), &getSamplerParameterIiv);
+ AssignGLEntryPoint(loadProcAddress("glGetSamplerParameterIuiv"), &getSamplerParameterIuiv);
+ AssignGLEntryPoint(loadProcAddress("glGetSamplerParameterfv"), &getSamplerParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glGetSamplerParameteriv"), &getSamplerParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glIsSampler"), &isSampler);
+ AssignGLEntryPoint(loadProcAddress("glQueryCounter"), &queryCounter);
+ AssignGLEntryPoint(loadProcAddress("glSamplerParameterIiv"), &samplerParameterIiv);
+ AssignGLEntryPoint(loadProcAddress("glSamplerParameterIuiv"), &samplerParameterIuiv);
+ AssignGLEntryPoint(loadProcAddress("glSamplerParameterf"), &samplerParameterf);
+ AssignGLEntryPoint(loadProcAddress("glSamplerParameterfv"), &samplerParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glSamplerParameteri"), &samplerParameteri);
+ AssignGLEntryPoint(loadProcAddress("glSamplerParameteriv"), &samplerParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribDivisor"), &vertexAttribDivisor);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribP1ui"), &vertexAttribP1ui);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribP1uiv"), &vertexAttribP1uiv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribP2ui"), &vertexAttribP2ui);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribP2uiv"), &vertexAttribP2uiv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribP3ui"), &vertexAttribP3ui);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribP3uiv"), &vertexAttribP3uiv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribP4ui"), &vertexAttribP4ui);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribP4uiv"), &vertexAttribP4uiv);
+ }
+
+ // 4.0
+ if (isAtLeastGL(gl::Version(4, 0)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBeginQueryIndexed"), &beginQueryIndexed);
+ AssignGLEntryPoint(loadProcAddress("glBindTransformFeedback"), &bindTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glBlendEquationSeparatei"), &blendEquationSeparatei);
+ AssignGLEntryPoint(loadProcAddress("glBlendEquationi"), &blendEquationi);
+ AssignGLEntryPoint(loadProcAddress("glBlendFuncSeparatei"), &blendFuncSeparatei);
+ AssignGLEntryPoint(loadProcAddress("glBlendFunci"), &blendFunci);
+ AssignGLEntryPoint(loadProcAddress("glDeleteTransformFeedbacks"), &deleteTransformFeedbacks);
+ AssignGLEntryPoint(loadProcAddress("glDrawArraysIndirect"), &drawArraysIndirect);
+ AssignGLEntryPoint(loadProcAddress("glDrawElementsIndirect"), &drawElementsIndirect);
+ AssignGLEntryPoint(loadProcAddress("glDrawTransformFeedback"), &drawTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glDrawTransformFeedbackStream"), &drawTransformFeedbackStream);
+ AssignGLEntryPoint(loadProcAddress("glEndQueryIndexed"), &endQueryIndexed);
+ AssignGLEntryPoint(loadProcAddress("glGenTransformFeedbacks"), &genTransformFeedbacks);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveSubroutineName"), &getActiveSubroutineName);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveSubroutineUniformName"), &getActiveSubroutineUniformName);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveSubroutineUniformiv"), &getActiveSubroutineUniformiv);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramStageiv"), &getProgramStageiv);
+ AssignGLEntryPoint(loadProcAddress("glGetQueryIndexediv"), &getQueryIndexediv);
+ AssignGLEntryPoint(loadProcAddress("glGetSubroutineIndex"), &getSubroutineIndex);
+ AssignGLEntryPoint(loadProcAddress("glGetSubroutineUniformLocation"), &getSubroutineUniformLocation);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformSubroutineuiv"), &getUniformSubroutineuiv);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformdv"), &getUniformdv);
+ AssignGLEntryPoint(loadProcAddress("glIsTransformFeedback"), &isTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glMinSampleShading"), &minSampleShading);
+ AssignGLEntryPoint(loadProcAddress("glPatchParameterfv"), &patchParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glPatchParameteri"), &patchParameteri);
+ AssignGLEntryPoint(loadProcAddress("glPauseTransformFeedback"), &pauseTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glResumeTransformFeedback"), &resumeTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glUniform1d"), &uniform1d);
+ AssignGLEntryPoint(loadProcAddress("glUniform1dv"), &uniform1dv);
+ AssignGLEntryPoint(loadProcAddress("glUniform2d"), &uniform2d);
+ AssignGLEntryPoint(loadProcAddress("glUniform2dv"), &uniform2dv);
+ AssignGLEntryPoint(loadProcAddress("glUniform3d"), &uniform3d);
+ AssignGLEntryPoint(loadProcAddress("glUniform3dv"), &uniform3dv);
+ AssignGLEntryPoint(loadProcAddress("glUniform4d"), &uniform4d);
+ AssignGLEntryPoint(loadProcAddress("glUniform4dv"), &uniform4dv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix2dv"), &uniformMatrix2dv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix2x3dv"), &uniformMatrix2x3dv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix2x4dv"), &uniformMatrix2x4dv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix3dv"), &uniformMatrix3dv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix3x2dv"), &uniformMatrix3x2dv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix3x4dv"), &uniformMatrix3x4dv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix4dv"), &uniformMatrix4dv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix4x2dv"), &uniformMatrix4x2dv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix4x3dv"), &uniformMatrix4x3dv);
+ AssignGLEntryPoint(loadProcAddress("glUniformSubroutinesuiv"), &uniformSubroutinesuiv);
+ }
+
+ // 4.1
+ if (isAtLeastGL(gl::Version(4, 1)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glActiveShaderProgram"), &activeShaderProgram);
+ AssignGLEntryPoint(loadProcAddress("glBindProgramPipeline"), &bindProgramPipeline);
+ AssignGLEntryPoint(loadProcAddress("glClearDepthf"), &clearDepthf);
+ AssignGLEntryPoint(loadProcAddress("glCreateShaderProgramv"), &createShaderProgramv);
+ AssignGLEntryPoint(loadProcAddress("glDeleteProgramPipelines"), &deleteProgramPipelines);
+ AssignGLEntryPoint(loadProcAddress("glDepthRangeArrayv"), &depthRangeArrayv);
+ AssignGLEntryPoint(loadProcAddress("glDepthRangeIndexed"), &depthRangeIndexed);
+ AssignGLEntryPoint(loadProcAddress("glDepthRangef"), &depthRangef);
+ AssignGLEntryPoint(loadProcAddress("glGenProgramPipelines"), &genProgramPipelines);
+ AssignGLEntryPoint(loadProcAddress("glGetDoublei_v"), &getDoublei_v);
+ AssignGLEntryPoint(loadProcAddress("glGetFloati_v"), &getFloati_v);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramBinary"), &getProgramBinary);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramPipelineInfoLog"), &getProgramPipelineInfoLog);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramPipelineiv"), &getProgramPipelineiv);
+ AssignGLEntryPoint(loadProcAddress("glGetShaderPrecisionFormat"), &getShaderPrecisionFormat);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexAttribLdv"), &getVertexAttribLdv);
+ AssignGLEntryPoint(loadProcAddress("glIsProgramPipeline"), &isProgramPipeline);
+ AssignGLEntryPoint(loadProcAddress("glProgramBinary"), &programBinary);
+ AssignGLEntryPoint(loadProcAddress("glProgramParameteri"), &programParameteri);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1d"), &programUniform1d);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1dv"), &programUniform1dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1f"), &programUniform1f);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1fv"), &programUniform1fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1i"), &programUniform1i);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1iv"), &programUniform1iv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1ui"), &programUniform1ui);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1uiv"), &programUniform1uiv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2d"), &programUniform2d);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2dv"), &programUniform2dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2f"), &programUniform2f);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2fv"), &programUniform2fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2i"), &programUniform2i);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2iv"), &programUniform2iv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2ui"), &programUniform2ui);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2uiv"), &programUniform2uiv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3d"), &programUniform3d);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3dv"), &programUniform3dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3f"), &programUniform3f);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3fv"), &programUniform3fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3i"), &programUniform3i);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3iv"), &programUniform3iv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3ui"), &programUniform3ui);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3uiv"), &programUniform3uiv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4d"), &programUniform4d);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4dv"), &programUniform4dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4f"), &programUniform4f);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4fv"), &programUniform4fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4i"), &programUniform4i);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4iv"), &programUniform4iv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4ui"), &programUniform4ui);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4uiv"), &programUniform4uiv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2dv"), &programUniformMatrix2dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2fv"), &programUniformMatrix2fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2x3dv"), &programUniformMatrix2x3dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2x3fv"), &programUniformMatrix2x3fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2x4dv"), &programUniformMatrix2x4dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2x4fv"), &programUniformMatrix2x4fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3dv"), &programUniformMatrix3dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3fv"), &programUniformMatrix3fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3x2dv"), &programUniformMatrix3x2dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3x2fv"), &programUniformMatrix3x2fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3x4dv"), &programUniformMatrix3x4dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3x4fv"), &programUniformMatrix3x4fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4dv"), &programUniformMatrix4dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4fv"), &programUniformMatrix4fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4x2dv"), &programUniformMatrix4x2dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4x2fv"), &programUniformMatrix4x2fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4x3dv"), &programUniformMatrix4x3dv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4x3fv"), &programUniformMatrix4x3fv);
+ AssignGLEntryPoint(loadProcAddress("glReleaseShaderCompiler"), &releaseShaderCompiler);
+ AssignGLEntryPoint(loadProcAddress("glScissorArrayv"), &scissorArrayv);
+ AssignGLEntryPoint(loadProcAddress("glScissorIndexed"), &scissorIndexed);
+ AssignGLEntryPoint(loadProcAddress("glScissorIndexedv"), &scissorIndexedv);
+ AssignGLEntryPoint(loadProcAddress("glShaderBinary"), &shaderBinary);
+ AssignGLEntryPoint(loadProcAddress("glUseProgramStages"), &useProgramStages);
+ AssignGLEntryPoint(loadProcAddress("glValidateProgramPipeline"), &validateProgramPipeline);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribL1d"), &vertexAttribL1d);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribL1dv"), &vertexAttribL1dv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribL2d"), &vertexAttribL2d);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribL2dv"), &vertexAttribL2dv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribL3d"), &vertexAttribL3d);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribL3dv"), &vertexAttribL3dv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribL4d"), &vertexAttribL4d);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribL4dv"), &vertexAttribL4dv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribLPointer"), &vertexAttribLPointer);
+ AssignGLEntryPoint(loadProcAddress("glViewportArrayv"), &viewportArrayv);
+ AssignGLEntryPoint(loadProcAddress("glViewportIndexedf"), &viewportIndexedf);
+ AssignGLEntryPoint(loadProcAddress("glViewportIndexedfv"), &viewportIndexedfv);
+ }
+
+ // 4.2
+ if (isAtLeastGL(gl::Version(4, 2)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBindImageTexture"), &bindImageTexture);
+ AssignGLEntryPoint(loadProcAddress("glDrawArraysInstancedBaseInstance"), &drawArraysInstancedBaseInstance);
+ AssignGLEntryPoint(loadProcAddress("glDrawElementsInstancedBaseInstance"), &drawElementsInstancedBaseInstance);
+ AssignGLEntryPoint(loadProcAddress("glDrawElementsInstancedBaseVertexBaseInstance"), &drawElementsInstancedBaseVertexBaseInstance);
+ AssignGLEntryPoint(loadProcAddress("glDrawTransformFeedbackInstanced"), &drawTransformFeedbackInstanced);
+ AssignGLEntryPoint(loadProcAddress("glDrawTransformFeedbackStreamInstanced"), &drawTransformFeedbackStreamInstanced);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveAtomicCounterBufferiv"), &getActiveAtomicCounterBufferiv);
+ AssignGLEntryPoint(loadProcAddress("glGetInternalformativ"), &getInternalformativ);
+ AssignGLEntryPoint(loadProcAddress("glMemoryBarrier"), &memoryBarrier);
+ AssignGLEntryPoint(loadProcAddress("glTexStorage1D"), &texStorage1D);
+ AssignGLEntryPoint(loadProcAddress("glTexStorage2D"), &texStorage2D);
+ AssignGLEntryPoint(loadProcAddress("glTexStorage3D"), &texStorage3D);
+ }
+
+ // 4.3
+ if (isAtLeastGL(gl::Version(4, 3)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBindVertexBuffer"), &bindVertexBuffer);
+ AssignGLEntryPoint(loadProcAddress("glClearBufferData"), &clearBufferData);
+ AssignGLEntryPoint(loadProcAddress("glClearBufferSubData"), &clearBufferSubData);
+ AssignGLEntryPoint(loadProcAddress("glCopyImageSubData"), &copyImageSubData);
+ AssignGLEntryPoint(loadProcAddress("glDebugMessageCallback"), &debugMessageCallback);
+ AssignGLEntryPoint(loadProcAddress("glDebugMessageControl"), &debugMessageControl);
+ AssignGLEntryPoint(loadProcAddress("glDebugMessageInsert"), &debugMessageInsert);
+ AssignGLEntryPoint(loadProcAddress("glDispatchCompute"), &dispatchCompute);
+ AssignGLEntryPoint(loadProcAddress("glDispatchComputeIndirect"), &dispatchComputeIndirect);
+ AssignGLEntryPoint(loadProcAddress("glFramebufferParameteri"), &framebufferParameteri);
+ AssignGLEntryPoint(loadProcAddress("glGetDebugMessageLog"), &getDebugMessageLog);
+ AssignGLEntryPoint(loadProcAddress("glGetFramebufferParameteriv"), &getFramebufferParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetInternalformati64v"), &getInternalformati64v);
+ AssignGLEntryPoint(loadProcAddress("glGetPointerv"), &getPointerv);
+ AssignGLEntryPoint(loadProcAddress("glGetObjectLabel"), &getObjectLabel);
+ AssignGLEntryPoint(loadProcAddress("glGetObjectPtrLabel"), &getObjectPtrLabel);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramInterfaceiv"), &getProgramInterfaceiv);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramResourceIndex"), &getProgramResourceIndex);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramResourceLocation"), &getProgramResourceLocation);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramResourceLocationIndex"), &getProgramResourceLocationIndex);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramResourceName"), &getProgramResourceName);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramResourceiv"), &getProgramResourceiv);
+ AssignGLEntryPoint(loadProcAddress("glInvalidateBufferData"), &invalidateBufferData);
+ AssignGLEntryPoint(loadProcAddress("glInvalidateBufferSubData"), &invalidateBufferSubData);
+ AssignGLEntryPoint(loadProcAddress("glInvalidateFramebuffer"), &invalidateFramebuffer);
+ AssignGLEntryPoint(loadProcAddress("glInvalidateSubFramebuffer"), &invalidateSubFramebuffer);
+ AssignGLEntryPoint(loadProcAddress("glInvalidateTexImage"), &invalidateTexImage);
+ AssignGLEntryPoint(loadProcAddress("glInvalidateTexSubImage"), &invalidateTexSubImage);
+ AssignGLEntryPoint(loadProcAddress("glMultiDrawArraysIndirect"), &multiDrawArraysIndirect);
+ AssignGLEntryPoint(loadProcAddress("glMultiDrawElementsIndirect"), &multiDrawElementsIndirect);
+ AssignGLEntryPoint(loadProcAddress("glObjectLabel"), &objectLabel);
+ AssignGLEntryPoint(loadProcAddress("glObjectPtrLabel"), &objectPtrLabel);
+ AssignGLEntryPoint(loadProcAddress("glPopDebugGroup"), &popDebugGroup);
+ AssignGLEntryPoint(loadProcAddress("glPushDebugGroup"), &pushDebugGroup);
+ AssignGLEntryPoint(loadProcAddress("glShaderStorageBlockBinding"), &shaderStorageBlockBinding);
+ AssignGLEntryPoint(loadProcAddress("glTexBufferRange"), &texBufferRange);
+ AssignGLEntryPoint(loadProcAddress("glTexStorage2DMultisample"), &texStorage2DMultisample);
+ AssignGLEntryPoint(loadProcAddress("glTexStorage3DMultisample"), &texStorage3DMultisample);
+ AssignGLEntryPoint(loadProcAddress("glTextureView"), &textureView);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribBinding"), &vertexAttribBinding);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribFormat"), &vertexAttribFormat);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribIFormat"), &vertexAttribIFormat);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribLFormat"), &vertexAttribLFormat);
+ AssignGLEntryPoint(loadProcAddress("glVertexBindingDivisor"), &vertexBindingDivisor);
+ }
+
+ // 4.4
+ if (isAtLeastGL(gl::Version(4, 4)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBindBuffersBase"), &bindBuffersBase);
+ AssignGLEntryPoint(loadProcAddress("glBindBuffersRange"), &bindBuffersRange);
+ AssignGLEntryPoint(loadProcAddress("glBindImageTextures"), &bindImageTextures);
+ AssignGLEntryPoint(loadProcAddress("glBindSamplers"), &bindSamplers);
+ AssignGLEntryPoint(loadProcAddress("glBindTextures"), &bindTextures);
+ AssignGLEntryPoint(loadProcAddress("glBindVertexBuffers"), &bindVertexBuffers);
+ AssignGLEntryPoint(loadProcAddress("glBufferStorage"), &bufferStorage);
+ AssignGLEntryPoint(loadProcAddress("glClearTexImage"), &clearTexImage);
+ AssignGLEntryPoint(loadProcAddress("glClearTexSubImage"), &clearTexSubImage);
+ }
+
+ // 4.5
+ if (isAtLeastGL(gl::Version(4, 5)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBindTextureUnit"), &bindTextureUnit);
+ AssignGLEntryPoint(loadProcAddress("glBlitNamedFramebuffer"), &blitNamedFramebuffer);
+ AssignGLEntryPoint(loadProcAddress("glCheckNamedFramebufferStatus"), &checkNamedFramebufferStatus);
+ AssignGLEntryPoint(loadProcAddress("glClearNamedBufferData"), &clearNamedBufferData);
+ AssignGLEntryPoint(loadProcAddress("glClearNamedBufferSubData"), &clearNamedBufferSubData);
+ AssignGLEntryPoint(loadProcAddress("glClearNamedFramebufferfi"), &clearNamedFramebufferfi);
+ AssignGLEntryPoint(loadProcAddress("glClearNamedFramebufferfv"), &clearNamedFramebufferfv);
+ AssignGLEntryPoint(loadProcAddress("glClearNamedFramebufferiv"), &clearNamedFramebufferiv);
+ AssignGLEntryPoint(loadProcAddress("glClearNamedFramebufferuiv"), &clearNamedFramebufferuiv);
+ AssignGLEntryPoint(loadProcAddress("glClipControl"), &clipControl);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTextureSubImage1D"), &compressedTextureSubImage1D);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTextureSubImage2D"), &compressedTextureSubImage2D);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTextureSubImage3D"), &compressedTextureSubImage3D);
+ AssignGLEntryPoint(loadProcAddress("glCopyNamedBufferSubData"), &copyNamedBufferSubData);
+ AssignGLEntryPoint(loadProcAddress("glCopyTextureSubImage1D"), &copyTextureSubImage1D);
+ AssignGLEntryPoint(loadProcAddress("glCopyTextureSubImage2D"), &copyTextureSubImage2D);
+ AssignGLEntryPoint(loadProcAddress("glCopyTextureSubImage3D"), &copyTextureSubImage3D);
+ AssignGLEntryPoint(loadProcAddress("glCreateBuffers"), &createBuffers);
+ AssignGLEntryPoint(loadProcAddress("glCreateFramebuffers"), &createFramebuffers);
+ AssignGLEntryPoint(loadProcAddress("glCreateProgramPipelines"), &createProgramPipelines);
+ AssignGLEntryPoint(loadProcAddress("glCreateQueries"), &createQueries);
+ AssignGLEntryPoint(loadProcAddress("glCreateRenderbuffers"), &createRenderbuffers);
+ AssignGLEntryPoint(loadProcAddress("glCreateSamplers"), &createSamplers);
+ AssignGLEntryPoint(loadProcAddress("glCreateTextures"), &createTextures);
+ AssignGLEntryPoint(loadProcAddress("glCreateTransformFeedbacks"), &createTransformFeedbacks);
+ AssignGLEntryPoint(loadProcAddress("glCreateVertexArrays"), &createVertexArrays);
+ AssignGLEntryPoint(loadProcAddress("glDisableVertexArrayAttrib"), &disableVertexArrayAttrib);
+ AssignGLEntryPoint(loadProcAddress("glEnableVertexArrayAttrib"), &enableVertexArrayAttrib);
+ AssignGLEntryPoint(loadProcAddress("glFlushMappedNamedBufferRange"), &flushMappedNamedBufferRange);
+ AssignGLEntryPoint(loadProcAddress("glGenerateTextureMipmap"), &generateTextureMipmap);
+ AssignGLEntryPoint(loadProcAddress("glGetCompressedTextureImage"), &getCompressedTextureImage);
+ AssignGLEntryPoint(loadProcAddress("glGetCompressedTextureSubImage"), &getCompressedTextureSubImage);
+ AssignGLEntryPoint(loadProcAddress("glGetGraphicsResetStatus"), &getGraphicsResetStatus);
+ AssignGLEntryPoint(loadProcAddress("glGetNamedBufferParameteri64v"), &getNamedBufferParameteri64v);
+ AssignGLEntryPoint(loadProcAddress("glGetNamedBufferParameteriv"), &getNamedBufferParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetNamedBufferPointerv"), &getNamedBufferPointerv);
+ AssignGLEntryPoint(loadProcAddress("glGetNamedBufferSubData"), &getNamedBufferSubData);
+ AssignGLEntryPoint(loadProcAddress("glGetNamedFramebufferAttachmentParameteriv"), &getNamedFramebufferAttachmentParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetNamedFramebufferParameteriv"), &getNamedFramebufferParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetNamedRenderbufferParameteriv"), &getNamedRenderbufferParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetQueryBufferObjecti64v"), &getQueryBufferObjecti64v);
+ AssignGLEntryPoint(loadProcAddress("glGetQueryBufferObjectiv"), &getQueryBufferObjectiv);
+ AssignGLEntryPoint(loadProcAddress("glGetQueryBufferObjectui64v"), &getQueryBufferObjectui64v);
+ AssignGLEntryPoint(loadProcAddress("glGetQueryBufferObjectuiv"), &getQueryBufferObjectuiv);
+ AssignGLEntryPoint(loadProcAddress("glGetTextureImage"), &getTextureImage);
+ AssignGLEntryPoint(loadProcAddress("glGetTextureLevelParameterfv"), &getTextureLevelParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glGetTextureLevelParameteriv"), &getTextureLevelParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetTextureParameterIiv"), &getTextureParameterIiv);
+ AssignGLEntryPoint(loadProcAddress("glGetTextureParameterIuiv"), &getTextureParameterIuiv);
+ AssignGLEntryPoint(loadProcAddress("glGetTextureParameterfv"), &getTextureParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glGetTextureParameteriv"), &getTextureParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetTextureSubImage"), &getTextureSubImage);
+ AssignGLEntryPoint(loadProcAddress("glGetTransformFeedbacki64_v"), &getTransformFeedbacki64_v);
+ AssignGLEntryPoint(loadProcAddress("glGetTransformFeedbacki_v"), &getTransformFeedbacki_v);
+ AssignGLEntryPoint(loadProcAddress("glGetTransformFeedbackiv"), &getTransformFeedbackiv);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexArrayIndexed64iv"), &getVertexArrayIndexed64iv);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexArrayIndexediv"), &getVertexArrayIndexediv);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexArrayiv"), &getVertexArrayiv);
+ AssignGLEntryPoint(loadProcAddress("glGetnCompressedTexImage"), &getnCompressedTexImage);
+ AssignGLEntryPoint(loadProcAddress("glGetnTexImage"), &getnTexImage);
+ AssignGLEntryPoint(loadProcAddress("glGetnUniformdv"), &getnUniformdv);
+ AssignGLEntryPoint(loadProcAddress("glGetnUniformfv"), &getnUniformfv);
+ AssignGLEntryPoint(loadProcAddress("glGetnUniformiv"), &getnUniformiv);
+ AssignGLEntryPoint(loadProcAddress("glGetnUniformuiv"), &getnUniformuiv);
+ AssignGLEntryPoint(loadProcAddress("glInvalidateNamedFramebufferData"), &invalidateNamedFramebufferData);
+ AssignGLEntryPoint(loadProcAddress("glInvalidateNamedFramebufferSubData"), &invalidateNamedFramebufferSubData);
+ AssignGLEntryPoint(loadProcAddress("glMapNamedBuffer"), &mapNamedBuffer);
+ AssignGLEntryPoint(loadProcAddress("glMapNamedBufferRange"), &mapNamedBufferRange);
+ AssignGLEntryPoint(loadProcAddress("glMemoryBarrierByRegion"), &memoryBarrierByRegion);
+ AssignGLEntryPoint(loadProcAddress("glNamedBufferData"), &namedBufferData);
+ AssignGLEntryPoint(loadProcAddress("glNamedBufferStorage"), &namedBufferStorage);
+ AssignGLEntryPoint(loadProcAddress("glNamedBufferSubData"), &namedBufferSubData);
+ AssignGLEntryPoint(loadProcAddress("glNamedFramebufferDrawBuffer"), &namedFramebufferDrawBuffer);
+ AssignGLEntryPoint(loadProcAddress("glNamedFramebufferDrawBuffers"), &namedFramebufferDrawBuffers);
+ AssignGLEntryPoint(loadProcAddress("glNamedFramebufferParameteri"), &namedFramebufferParameteri);
+ AssignGLEntryPoint(loadProcAddress("glNamedFramebufferReadBuffer"), &namedFramebufferReadBuffer);
+ AssignGLEntryPoint(loadProcAddress("glNamedFramebufferRenderbuffer"), &namedFramebufferRenderbuffer);
+ AssignGLEntryPoint(loadProcAddress("glNamedFramebufferTexture"), &namedFramebufferTexture);
+ AssignGLEntryPoint(loadProcAddress("glNamedFramebufferTextureLayer"), &namedFramebufferTextureLayer);
+ AssignGLEntryPoint(loadProcAddress("glNamedRenderbufferStorage"), &namedRenderbufferStorage);
+ AssignGLEntryPoint(loadProcAddress("glNamedRenderbufferStorageMultisample"), &namedRenderbufferStorageMultisample);
+ AssignGLEntryPoint(loadProcAddress("glReadnPixels"), &readnPixels);
+ AssignGLEntryPoint(loadProcAddress("glTextureBarrier"), &textureBarrier);
+ AssignGLEntryPoint(loadProcAddress("glTextureBuffer"), &textureBuffer);
+ AssignGLEntryPoint(loadProcAddress("glTextureBufferRange"), &textureBufferRange);
+ AssignGLEntryPoint(loadProcAddress("glTextureParameterIiv"), &textureParameterIiv);
+ AssignGLEntryPoint(loadProcAddress("glTextureParameterIuiv"), &textureParameterIuiv);
+ AssignGLEntryPoint(loadProcAddress("glTextureParameterf"), &textureParameterf);
+ AssignGLEntryPoint(loadProcAddress("glTextureParameterfv"), &textureParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glTextureParameteri"), &textureParameteri);
+ AssignGLEntryPoint(loadProcAddress("glTextureParameteriv"), &textureParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glTextureStorage1D"), &textureStorage1D);
+ AssignGLEntryPoint(loadProcAddress("glTextureStorage2D"), &textureStorage2D);
+ AssignGLEntryPoint(loadProcAddress("glTextureStorage2DMultisample"), &textureStorage2DMultisample);
+ AssignGLEntryPoint(loadProcAddress("glTextureStorage3D"), &textureStorage3D);
+ AssignGLEntryPoint(loadProcAddress("glTextureStorage3DMultisample"), &textureStorage3DMultisample);
+ AssignGLEntryPoint(loadProcAddress("glTextureSubImage1D"), &textureSubImage1D);
+ AssignGLEntryPoint(loadProcAddress("glTextureSubImage2D"), &textureSubImage2D);
+ AssignGLEntryPoint(loadProcAddress("glTextureSubImage3D"), &textureSubImage3D);
+ AssignGLEntryPoint(loadProcAddress("glTransformFeedbackBufferBase"), &transformFeedbackBufferBase);
+ AssignGLEntryPoint(loadProcAddress("glTransformFeedbackBufferRange"), &transformFeedbackBufferRange);
+ AssignGLEntryPoint(loadProcAddress("glUnmapNamedBuffer"), &unmapNamedBuffer);
+ AssignGLEntryPoint(loadProcAddress("glVertexArrayAttribBinding"), &vertexArrayAttribBinding);
+ AssignGLEntryPoint(loadProcAddress("glVertexArrayAttribFormat"), &vertexArrayAttribFormat);
+ AssignGLEntryPoint(loadProcAddress("glVertexArrayAttribIFormat"), &vertexArrayAttribIFormat);
+ AssignGLEntryPoint(loadProcAddress("glVertexArrayAttribLFormat"), &vertexArrayAttribLFormat);
+ AssignGLEntryPoint(loadProcAddress("glVertexArrayBindingDivisor"), &vertexArrayBindingDivisor);
+ AssignGLEntryPoint(loadProcAddress("glVertexArrayElementBuffer"), &vertexArrayElementBuffer);
+ AssignGLEntryPoint(loadProcAddress("glVertexArrayVertexBuffer"), &vertexArrayVertexBuffer);
+ AssignGLEntryPoint(loadProcAddress("glVertexArrayVertexBuffers"), &vertexArrayVertexBuffers);
+ }
+
+ // clang-format on
+}
+
+void FunctionsGL::initializeProcsGLES()
+{
+ // No profiles in GLES
+ profile = 0;
+
+ // clang-format off
+
+ // GL_NV_path_rendering
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glMatrixLoadfEXT"), &matrixLoadEXT);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGenPathsNV"), &genPathsNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glDeletePathsNV"), &delPathsNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathCommandsNV"), &pathCommandsNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glIsPathNV"), &isPathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathParameterfNV"), &setPathParameterfNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathParameteriNV"), &setPathParameteriNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGetPathParameterfvNV"), &getPathParameterfNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glGetPathParameterivNV"), &getPathParameteriNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glPathStencilFuncNV"), &pathStencilFuncNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilFillPathNV"), &stencilFillPathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilStrokePathNV"), &stencilStrokePathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverFillPathNV"), &coverFillPathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverStrokePathNV"), &coverStrokePathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverFillPathNV"), &stencilThenCoverFillPathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverStrokePathNV"), &stencilThenCoverStrokePathNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverFillPathInstancedNV"), &coverFillPathInstancedNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glCoverStrokePathInstancedNV"), &coverStrokePathInstancedNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilFillPathInstancedNV"), &stencilFillPathInstancedNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilStrokePathInstancedNV"), &stencilStrokePathInstancedNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverFillPathInstancedNV"), &stencilThenCoverFillPathInstancedNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glStencilThenCoverStrokePathInstancedNV"), &stencilThenCoverStrokePathInstancedNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_path_rendering", loadProcAddress("glProgramPathFragmentInputGenNV"), &programPathFragmentInputGenNV);
+
+ // GL_OES_texture_3D
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_texture_3D", loadProcAddress("glTexImage3DOES"), &texImage3D);
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_texture_3D", loadProcAddress("glTexSubImage3DOES"), &texSubImage3D);
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_texture_3D", loadProcAddress("glCopyTexSubImage3DOES"), &copyTexSubImage3D);
+
+ // GL_NV_framebuffer_mixed_samples
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_framebuffer_mixed_samples", loadProcAddress("glCoverageModulationNV"), &coverageModulationNV);
+
+ // GL_NV_fence
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glDeleteFencesNV"), &deleteFencesNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glGenFencesNV"), &genFencesNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glIsFenceNV"), &isFenceNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glTestFenceNV"), &testFenceNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glGetFenceivNV"), &getFenceivNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glFinishFenceNV"), &finishFenceNV);
+ AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glSetFenceNV"), &setFenceNV);
+
+ // GL_EXT_texture_storage
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage", loadProcAddress("glTexStorage2DEXT"), &texStorage2D);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_texture_storage GL_OES_texture3D", loadProcAddress("glTexStorage3DEXT"), &texStorage3D);
+
+ // GL_OES_vertex_array_object
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_vertex_array_object", loadProcAddress("glBindVertexArray"), &bindVertexArray);
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_vertex_array_object", loadProcAddress("glDeleteVertexArrays"), &deleteVertexArrays);
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_vertex_array_object", loadProcAddress("glGenVertexArrays"), &genVertexArrays);
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_vertex_array_object", loadProcAddress("glIsVertexArray"), &isVertexArray);
+
+ // GL_EXT_map_buffer_range
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_map_buffer_range", loadProcAddress("glMapBufferRangeEXT"), &mapBufferRange);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_map_buffer_range", loadProcAddress("glFlushMappedBufferRangeEXT"), &flushMappedBufferRange);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_map_buffer_range", loadProcAddress("glUnmapBufferOES"), &unmapBuffer);
+
+ // GL_OES_mapbuffer
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_mapbuffer", loadProcAddress("glMapBufferOES"), &mapBuffer);
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_mapbuffer", loadProcAddress("glUnmapBufferOES"), &unmapBuffer);
+
+ // GL_KHR_debug
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glDebugMessageControlKHR"), &debugMessageControl);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glDebugMessageInsertKHR"), &debugMessageInsert);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glDebugMessageCallbackKHR"), &debugMessageCallback);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetDebugMessageLogKHR"), &getDebugMessageLog);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetPointervKHR"), &getPointerv);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glPushDebugGroupKHR"), &pushDebugGroup);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glPopDebugGroupKHR"), &popDebugGroup);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glObjectLabelKHR"), &objectLabel);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetObjectLabelKHR"), &getObjectLabel);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glObjectPtrLabelKHR"), &objectPtrLabel);
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_debug", loadProcAddress("glGetObjectPtrLabelKHR"), &getObjectPtrLabel);
+
+ // GL_EXT_draw_instanced
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glVertexAttribDivisorEXT"), &vertexAttribDivisor);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glDrawArraysInstancedEXT"), &drawArraysInstanced);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glDrawElementsInstancedEXT"), &drawElementsInstanced);
+
+ // GL_EXT_occlusion_query_boolean
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glGenQueriesEXT"), &genQueries);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glDeleteQueriesEXT"), &deleteQueries);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glIsQueryEXT"), &isQuery);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glBeginQueryEXT"), &beginQuery);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glEndQueryEXT"), &endQuery);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glGetQueryivEXT"), &getQueryiv);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_occlusion_query_boolean", loadProcAddress("glGetQueryObjectuivEXT"), &getQueryObjectuiv);
+
+ // GL_EXT_disjoint_timer_query
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glGenQueriesEXT"), &genQueries);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glDeleteQueriesEXT"), &deleteQueries);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glIsQueryEXT"), &isQuery);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glBeginQueryEXT"), &beginQuery);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glEndQueryEXT"), &endQuery);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glQueryCounterEXT"), &queryCounter);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glGetQueryivEXT"), &getQueryiv);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glGetQueryObjectivEXT"), &getQueryObjectiv);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glGetQueryObjectuivEXT"), &getQueryObjectuiv);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glGetQueryObjecti64vEXT"), &getQueryObjecti64v);
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_disjoint_timer_query", loadProcAddress("glGetQueryObjectui64vEXT"), &getQueryObjectui64v);
+
+ // GL_OES_EGL_image
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_EGL_image", loadProcAddress("glEGLImageTargetRenderbufferStorageOES"), &eglImageTargetRenderbufferStorageOES);
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_EGL_image", loadProcAddress("glEGLImageTargetTexture2DOES"), &eglImageTargetTexture2DOES);
+
+ // GL_OES_get_program_binary
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_get_program_binary", loadProcAddress("glGetProgramBinaryOES"), &getProgramBinary);
+ AssignGLExtensionEntryPoint(extensions, "GL_OES_get_program_binary", loadProcAddress("glProgramBinaryOES"), &programBinary);
+
+ // GL_EXT_robustness
+ AssignGLExtensionEntryPoint(extensions, "GL_EXT_robustness", loadProcAddress("glGetGraphicsResetStatusEXT"), &getGraphicsResetStatus);
+
+ // GL_KHR_robustness
+ AssignGLExtensionEntryPoint(extensions, "GL_KHR_robustness", loadProcAddress("glGetGraphicsResetStatusKHR"), &getGraphicsResetStatus);
+
+ // 2.0
+ if (isAtLeastGLES(gl::Version(2, 0)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glActiveTexture"), &activeTexture);
+ AssignGLEntryPoint(loadProcAddress("glAttachShader"), &attachShader);
+ AssignGLEntryPoint(loadProcAddress("glBindAttribLocation"), &bindAttribLocation);
+ AssignGLEntryPoint(loadProcAddress("glBindBuffer"), &bindBuffer);
+ AssignGLEntryPoint(loadProcAddress("glBindFramebuffer"), &bindFramebuffer);
+ AssignGLEntryPoint(loadProcAddress("glBindRenderbuffer"), &bindRenderbuffer);
+ AssignGLEntryPoint(loadProcAddress("glBindTexture"), &bindTexture);
+ AssignGLEntryPoint(loadProcAddress("glBlendColor"), &blendColor);
+ AssignGLEntryPoint(loadProcAddress("glBlendEquation"), &blendEquation);
+ AssignGLEntryPoint(loadProcAddress("glBlendEquationSeparate"), &blendEquationSeparate);
+ AssignGLEntryPoint(loadProcAddress("glBlendFunc"), &blendFunc);
+ AssignGLEntryPoint(loadProcAddress("glBlendFuncSeparate"), &blendFuncSeparate);
+ AssignGLEntryPoint(loadProcAddress("glBufferData"), &bufferData);
+ AssignGLEntryPoint(loadProcAddress("glBufferSubData"), &bufferSubData);
+ AssignGLEntryPoint(loadProcAddress("glCheckFramebufferStatus"), &checkFramebufferStatus);
+ AssignGLEntryPoint(loadProcAddress("glClear"), &clear);
+ AssignGLEntryPoint(loadProcAddress("glClearColor"), &clearColor);
+ AssignGLEntryPoint(loadProcAddress("glClearDepthf"), &clearDepthf);
+ AssignGLEntryPoint(loadProcAddress("glClearStencil"), &clearStencil);
+ AssignGLEntryPoint(loadProcAddress("glColorMask"), &colorMask);
+ AssignGLEntryPoint(loadProcAddress("glCompileShader"), &compileShader);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTexImage2D"), &compressedTexImage2D);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTexSubImage2D"), &compressedTexSubImage2D);
+ AssignGLEntryPoint(loadProcAddress("glCopyTexImage2D"), &copyTexImage2D);
+ AssignGLEntryPoint(loadProcAddress("glCopyTexSubImage2D"), &copyTexSubImage2D);
+ AssignGLEntryPoint(loadProcAddress("glCreateProgram"), &createProgram);
+ AssignGLEntryPoint(loadProcAddress("glCreateShader"), &createShader);
+ AssignGLEntryPoint(loadProcAddress("glCullFace"), &cullFace);
+ AssignGLEntryPoint(loadProcAddress("glDeleteBuffers"), &deleteBuffers);
+ AssignGLEntryPoint(loadProcAddress("glDeleteFramebuffers"), &deleteFramebuffers);
+ AssignGLEntryPoint(loadProcAddress("glDeleteProgram"), &deleteProgram);
+ AssignGLEntryPoint(loadProcAddress("glDeleteRenderbuffers"), &deleteRenderbuffers);
+ AssignGLEntryPoint(loadProcAddress("glDeleteShader"), &deleteShader);
+ AssignGLEntryPoint(loadProcAddress("glDeleteTextures"), &deleteTextures);
+ AssignGLEntryPoint(loadProcAddress("glDepthFunc"), &depthFunc);
+ AssignGLEntryPoint(loadProcAddress("glDepthMask"), &depthMask);
+ AssignGLEntryPoint(loadProcAddress("glDepthRangef"), &depthRangef);
+ AssignGLEntryPoint(loadProcAddress("glDetachShader"), &detachShader);
+ AssignGLEntryPoint(loadProcAddress("glDisable"), &disable);
+ AssignGLEntryPoint(loadProcAddress("glDisableVertexAttribArray"), &disableVertexAttribArray);
+ AssignGLEntryPoint(loadProcAddress("glDrawArrays"), &drawArrays);
+ AssignGLEntryPoint(loadProcAddress("glDrawElements"), &drawElements);
+ AssignGLEntryPoint(loadProcAddress("glEnable"), &enable);
+ AssignGLEntryPoint(loadProcAddress("glEnableVertexAttribArray"), &enableVertexAttribArray);
+ AssignGLEntryPoint(loadProcAddress("glFinish"), &finish);
+ AssignGLEntryPoint(loadProcAddress("glFlush"), &flush);
+ AssignGLEntryPoint(loadProcAddress("glFramebufferRenderbuffer"), &framebufferRenderbuffer);
+ AssignGLEntryPoint(loadProcAddress("glFramebufferTexture2D"), &framebufferTexture2D);
+ AssignGLEntryPoint(loadProcAddress("glFrontFace"), &frontFace);
+ AssignGLEntryPoint(loadProcAddress("glGenBuffers"), &genBuffers);
+ AssignGLEntryPoint(loadProcAddress("glGenerateMipmap"), &generateMipmap);
+ AssignGLEntryPoint(loadProcAddress("glGenFramebuffers"), &genFramebuffers);
+ AssignGLEntryPoint(loadProcAddress("glGenRenderbuffers"), &genRenderbuffers);
+ AssignGLEntryPoint(loadProcAddress("glGenTextures"), &genTextures);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveAttrib"), &getActiveAttrib);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveUniform"), &getActiveUniform);
+ AssignGLEntryPoint(loadProcAddress("glGetAttachedShaders"), &getAttachedShaders);
+ AssignGLEntryPoint(loadProcAddress("glGetAttribLocation"), &getAttribLocation);
+ AssignGLEntryPoint(loadProcAddress("glGetBooleanv"), &getBooleanv);
+ AssignGLEntryPoint(loadProcAddress("glGetBufferParameteriv"), &getBufferParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetError"), &getError);
+ AssignGLEntryPoint(loadProcAddress("glGetFloatv"), &getFloatv);
+ AssignGLEntryPoint(loadProcAddress("glGetFramebufferAttachmentParameteriv"), &getFramebufferAttachmentParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetIntegerv"), &getIntegerv);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramiv"), &getProgramiv);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramInfoLog"), &getProgramInfoLog);
+ AssignGLEntryPoint(loadProcAddress("glGetRenderbufferParameteriv"), &getRenderbufferParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetShaderiv"), &getShaderiv);
+ AssignGLEntryPoint(loadProcAddress("glGetShaderInfoLog"), &getShaderInfoLog);
+ AssignGLEntryPoint(loadProcAddress("glGetShaderPrecisionFormat"), &getShaderPrecisionFormat);
+ AssignGLEntryPoint(loadProcAddress("glGetShaderSource"), &getShaderSource);
+ AssignGLEntryPoint(loadProcAddress("glGetString"), &getString);
+ AssignGLEntryPoint(loadProcAddress("glGetTexParameterfv"), &getTexParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glGetTexParameteriv"), &getTexParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformfv"), &getUniformfv);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformiv"), &getUniformiv);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformLocation"), &getUniformLocation);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexAttribfv"), &getVertexAttribfv);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexAttribiv"), &getVertexAttribiv);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexAttribPointerv"), &getVertexAttribPointerv);
+ AssignGLEntryPoint(loadProcAddress("glHint"), &hint);
+ AssignGLEntryPoint(loadProcAddress("glIsBuffer"), &isBuffer);
+ AssignGLEntryPoint(loadProcAddress("glIsEnabled"), &isEnabled);
+ AssignGLEntryPoint(loadProcAddress("glIsFramebuffer"), &isFramebuffer);
+ AssignGLEntryPoint(loadProcAddress("glIsProgram"), &isProgram);
+ AssignGLEntryPoint(loadProcAddress("glIsRenderbuffer"), &isRenderbuffer);
+ AssignGLEntryPoint(loadProcAddress("glIsShader"), &isShader);
+ AssignGLEntryPoint(loadProcAddress("glIsTexture"), &isTexture);
+ AssignGLEntryPoint(loadProcAddress("glLineWidth"), &lineWidth);
+ AssignGLEntryPoint(loadProcAddress("glLinkProgram"), &linkProgram);
+ AssignGLEntryPoint(loadProcAddress("glPixelStorei"), &pixelStorei);
+ AssignGLEntryPoint(loadProcAddress("glPolygonOffset"), &polygonOffset);
+ AssignGLEntryPoint(loadProcAddress("glReadPixels"), &readPixels);
+ AssignGLEntryPoint(loadProcAddress("glReleaseShaderCompiler"), &releaseShaderCompiler);
+ AssignGLEntryPoint(loadProcAddress("glRenderbufferStorage"), &renderbufferStorage);
+ AssignGLEntryPoint(loadProcAddress("glSampleCoverage"), &sampleCoverage);
+ AssignGLEntryPoint(loadProcAddress("glScissor"), &scissor);
+ AssignGLEntryPoint(loadProcAddress("glShaderBinary"), &shaderBinary);
+ AssignGLEntryPoint(loadProcAddress("glShaderSource"), &shaderSource);
+ AssignGLEntryPoint(loadProcAddress("glStencilFunc"), &stencilFunc);
+ AssignGLEntryPoint(loadProcAddress("glStencilFuncSeparate"), &stencilFuncSeparate);
+ AssignGLEntryPoint(loadProcAddress("glStencilMask"), &stencilMask);
+ AssignGLEntryPoint(loadProcAddress("glStencilMaskSeparate"), &stencilMaskSeparate);
+ AssignGLEntryPoint(loadProcAddress("glStencilOp"), &stencilOp);
+ AssignGLEntryPoint(loadProcAddress("glStencilOpSeparate"), &stencilOpSeparate);
+ AssignGLEntryPoint(loadProcAddress("glTexImage2D"), &texImage2D);
+ AssignGLEntryPoint(loadProcAddress("glTexParameterf"), &texParameterf);
+ AssignGLEntryPoint(loadProcAddress("glTexParameterfv"), &texParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glTexParameteri"), &texParameteri);
+ AssignGLEntryPoint(loadProcAddress("glTexParameteriv"), &texParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glTexSubImage2D"), &texSubImage2D);
+ AssignGLEntryPoint(loadProcAddress("glUniform1f"), &uniform1f);
+ AssignGLEntryPoint(loadProcAddress("glUniform1fv"), &uniform1fv);
+ AssignGLEntryPoint(loadProcAddress("glUniform1i"), &uniform1i);
+ AssignGLEntryPoint(loadProcAddress("glUniform1iv"), &uniform1iv);
+ AssignGLEntryPoint(loadProcAddress("glUniform2f"), &uniform2f);
+ AssignGLEntryPoint(loadProcAddress("glUniform2fv"), &uniform2fv);
+ AssignGLEntryPoint(loadProcAddress("glUniform2i"), &uniform2i);
+ AssignGLEntryPoint(loadProcAddress("glUniform2iv"), &uniform2iv);
+ AssignGLEntryPoint(loadProcAddress("glUniform3f"), &uniform3f);
+ AssignGLEntryPoint(loadProcAddress("glUniform3fv"), &uniform3fv);
+ AssignGLEntryPoint(loadProcAddress("glUniform3i"), &uniform3i);
+ AssignGLEntryPoint(loadProcAddress("glUniform3iv"), &uniform3iv);
+ AssignGLEntryPoint(loadProcAddress("glUniform4f"), &uniform4f);
+ AssignGLEntryPoint(loadProcAddress("glUniform4fv"), &uniform4fv);
+ AssignGLEntryPoint(loadProcAddress("glUniform4i"), &uniform4i);
+ AssignGLEntryPoint(loadProcAddress("glUniform4iv"), &uniform4iv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix2fv"), &uniformMatrix2fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix3fv"), &uniformMatrix3fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix4fv"), &uniformMatrix4fv);
+ AssignGLEntryPoint(loadProcAddress("glUseProgram"), &useProgram);
+ AssignGLEntryPoint(loadProcAddress("glValidateProgram"), &validateProgram);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib1f"), &vertexAttrib1f);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib1fv"), &vertexAttrib1fv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib2f"), &vertexAttrib2f);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib2fv"), &vertexAttrib2fv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib3f"), &vertexAttrib3f);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib3fv"), &vertexAttrib3fv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4f"), &vertexAttrib4f);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttrib4fv"), &vertexAttrib4fv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribPointer"), &vertexAttribPointer);
+ AssignGLEntryPoint(loadProcAddress("glViewport"), &viewport);
+ }
+
+ // 3.0
+ if (isAtLeastGLES(gl::Version(3, 0)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glReadBuffer"), &readBuffer);
+ AssignGLEntryPoint(loadProcAddress("glDrawRangeElements"), &drawRangeElements);
+ AssignGLEntryPoint(loadProcAddress("glTexImage3D"), &texImage3D);
+ AssignGLEntryPoint(loadProcAddress("glTexSubImage3D"), &texSubImage3D);
+ AssignGLEntryPoint(loadProcAddress("glCopyTexSubImage3D"), &copyTexSubImage3D);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTexImage3D"), &compressedTexImage3D);
+ AssignGLEntryPoint(loadProcAddress("glCompressedTexSubImage3D"), &compressedTexSubImage3D);
+ AssignGLEntryPoint(loadProcAddress("glGenQueries"), &genQueries);
+ AssignGLEntryPoint(loadProcAddress("glDeleteQueries"), &deleteQueries);
+ AssignGLEntryPoint(loadProcAddress("glIsQuery"), &isQuery);
+ AssignGLEntryPoint(loadProcAddress("glBeginQuery"), &beginQuery);
+ AssignGLEntryPoint(loadProcAddress("glEndQuery"), &endQuery);
+ AssignGLEntryPoint(loadProcAddress("glGetQueryiv"), &getQueryiv);
+ AssignGLEntryPoint(loadProcAddress("glGetQueryObjectuiv"), &getQueryObjectuiv);
+ AssignGLEntryPoint(loadProcAddress("glUnmapBuffer"), &unmapBuffer);
+ AssignGLEntryPoint(loadProcAddress("glGetBufferPointerv"), &getBufferPointerv);
+ AssignGLEntryPoint(loadProcAddress("glDrawBuffers"), &drawBuffers);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix2x3fv"), &uniformMatrix2x3fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix3x2fv"), &uniformMatrix3x2fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix2x4fv"), &uniformMatrix2x4fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix4x2fv"), &uniformMatrix4x2fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix3x4fv"), &uniformMatrix3x4fv);
+ AssignGLEntryPoint(loadProcAddress("glUniformMatrix4x3fv"), &uniformMatrix4x3fv);
+ AssignGLEntryPoint(loadProcAddress("glBlitFramebuffer"), &blitFramebuffer);
+ AssignGLEntryPoint(loadProcAddress("glRenderbufferStorageMultisample"), &renderbufferStorageMultisample);
+ AssignGLEntryPoint(loadProcAddress("glFramebufferTextureLayer"), &framebufferTextureLayer);
+ AssignGLEntryPoint(loadProcAddress("glMapBufferRange"), &mapBufferRange);
+ AssignGLEntryPoint(loadProcAddress("glFlushMappedBufferRange"), &flushMappedBufferRange);
+ AssignGLEntryPoint(loadProcAddress("glBindVertexArray"), &bindVertexArray);
+ AssignGLEntryPoint(loadProcAddress("glDeleteVertexArrays"), &deleteVertexArrays);
+ AssignGLEntryPoint(loadProcAddress("glGenVertexArrays"), &genVertexArrays);
+ AssignGLEntryPoint(loadProcAddress("glIsVertexArray"), &isVertexArray);
+ AssignGLEntryPoint(loadProcAddress("glGetIntegeri_v"), &getIntegeri_v);
+ AssignGLEntryPoint(loadProcAddress("glBeginTransformFeedback"), &beginTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glEndTransformFeedback"), &endTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glBindBufferRange"), &bindBufferRange);
+ AssignGLEntryPoint(loadProcAddress("glBindBufferBase"), &bindBufferBase);
+ AssignGLEntryPoint(loadProcAddress("glTransformFeedbackVaryings"), &transformFeedbackVaryings);
+ AssignGLEntryPoint(loadProcAddress("glGetTransformFeedbackVarying"), &getTransformFeedbackVarying);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribIPointer"), &vertexAttribIPointer);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexAttribIiv"), &getVertexAttribIiv);
+ AssignGLEntryPoint(loadProcAddress("glGetVertexAttribIuiv"), &getVertexAttribIuiv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI4i"), &vertexAttribI4i);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI4ui"), &vertexAttribI4ui);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI4iv"), &vertexAttribI4iv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribI4uiv"), &vertexAttribI4uiv);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformuiv"), &getUniformuiv);
+ AssignGLEntryPoint(loadProcAddress("glGetFragDataLocation"), &getFragDataLocation);
+ AssignGLEntryPoint(loadProcAddress("glUniform1ui"), &uniform1ui);
+ AssignGLEntryPoint(loadProcAddress("glUniform2ui"), &uniform2ui);
+ AssignGLEntryPoint(loadProcAddress("glUniform3ui"), &uniform3ui);
+ AssignGLEntryPoint(loadProcAddress("glUniform4ui"), &uniform4ui);
+ AssignGLEntryPoint(loadProcAddress("glUniform1uiv"), &uniform1uiv);
+ AssignGLEntryPoint(loadProcAddress("glUniform2uiv"), &uniform2uiv);
+ AssignGLEntryPoint(loadProcAddress("glUniform3uiv"), &uniform3uiv);
+ AssignGLEntryPoint(loadProcAddress("glUniform4uiv"), &uniform4uiv);
+ AssignGLEntryPoint(loadProcAddress("glClearBufferiv"), &clearBufferiv);
+ AssignGLEntryPoint(loadProcAddress("glClearBufferuiv"), &clearBufferuiv);
+ AssignGLEntryPoint(loadProcAddress("glClearBufferfv"), &clearBufferfv);
+ AssignGLEntryPoint(loadProcAddress("glClearBufferfi"), &clearBufferfi);
+ AssignGLEntryPoint(loadProcAddress("glGetStringi"), &getStringi);
+ AssignGLEntryPoint(loadProcAddress("glCopyBufferSubData"), &copyBufferSubData);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformIndices"), &getUniformIndices);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveUniformsiv"), &getActiveUniformsiv);
+ AssignGLEntryPoint(loadProcAddress("glGetUniformBlockIndex"), &getUniformBlockIndex);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveUniformBlockiv"), &getActiveUniformBlockiv);
+ AssignGLEntryPoint(loadProcAddress("glGetActiveUniformBlockName"), &getActiveUniformBlockName);
+ AssignGLEntryPoint(loadProcAddress("glUniformBlockBinding"), &uniformBlockBinding);
+ AssignGLEntryPoint(loadProcAddress("glDrawArraysInstanced"), &drawArraysInstanced);
+ AssignGLEntryPoint(loadProcAddress("glDrawElementsInstanced"), &drawElementsInstanced);
+ AssignGLEntryPoint(loadProcAddress("glFenceSync"), &fenceSync);
+ AssignGLEntryPoint(loadProcAddress("glIsSync"), &isSync);
+ AssignGLEntryPoint(loadProcAddress("glDeleteSync"), &deleteSync);
+ AssignGLEntryPoint(loadProcAddress("glClientWaitSync"), &clientWaitSync);
+ AssignGLEntryPoint(loadProcAddress("glWaitSync"), &waitSync);
+ AssignGLEntryPoint(loadProcAddress("glGetInteger64v"), &getInteger64v);
+ AssignGLEntryPoint(loadProcAddress("glGetSynciv"), &getSynciv);
+ AssignGLEntryPoint(loadProcAddress("glGetInteger64i_v"), &getInteger64i_v);
+ AssignGLEntryPoint(loadProcAddress("glGetBufferParameteri64v"), &getBufferParameteri64v);
+ AssignGLEntryPoint(loadProcAddress("glGenSamplers"), &genSamplers);
+ AssignGLEntryPoint(loadProcAddress("glDeleteSamplers"), &deleteSamplers);
+ AssignGLEntryPoint(loadProcAddress("glIsSampler"), &isSampler);
+ AssignGLEntryPoint(loadProcAddress("glBindSampler"), &bindSampler);
+ AssignGLEntryPoint(loadProcAddress("glSamplerParameteri"), &samplerParameteri);
+ AssignGLEntryPoint(loadProcAddress("glSamplerParameteriv"), &samplerParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glSamplerParameterf"), &samplerParameterf);
+ AssignGLEntryPoint(loadProcAddress("glSamplerParameterfv"), &samplerParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glGetSamplerParameteriv"), &getSamplerParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetSamplerParameterfv"), &getSamplerParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribDivisor"), &vertexAttribDivisor);
+ AssignGLEntryPoint(loadProcAddress("glBindTransformFeedback"), &bindTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glDeleteTransformFeedbacks"), &deleteTransformFeedbacks);
+ AssignGLEntryPoint(loadProcAddress("glGenTransformFeedbacks"), &genTransformFeedbacks);
+ AssignGLEntryPoint(loadProcAddress("glIsTransformFeedback"), &isTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glPauseTransformFeedback"), &pauseTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glResumeTransformFeedback"), &resumeTransformFeedback);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramBinary"), &getProgramBinary);
+ AssignGLEntryPoint(loadProcAddress("glProgramBinary"), &programBinary);
+ AssignGLEntryPoint(loadProcAddress("glProgramParameteri"), &programParameteri);
+ AssignGLEntryPoint(loadProcAddress("glInvalidateFramebuffer"), &invalidateFramebuffer);
+ AssignGLEntryPoint(loadProcAddress("glInvalidateSubFramebuffer"), &invalidateSubFramebuffer);
+ AssignGLEntryPoint(loadProcAddress("glTexStorage2D"), &texStorage2D);
+ AssignGLEntryPoint(loadProcAddress("glTexStorage3D"), &texStorage3D);
+ AssignGLEntryPoint(loadProcAddress("glGetInternalformativ"), &getInternalformativ);
+ }
+
+ // 3.1
+ if (isAtLeastGLES(gl::Version(3, 1)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glDispatchCompute"), &dispatchCompute);
+ AssignGLEntryPoint(loadProcAddress("glDispatchComputeIndirect"), &dispatchComputeIndirect);
+ AssignGLEntryPoint(loadProcAddress("glDrawArraysIndirect"), &drawArraysIndirect);
+ AssignGLEntryPoint(loadProcAddress("glDrawElementsIndirect"), &drawElementsIndirect);
+ AssignGLEntryPoint(loadProcAddress("glFramebufferParameteri"), &framebufferParameteri);
+ AssignGLEntryPoint(loadProcAddress("glGetFramebufferParameteriv"), &getFramebufferParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramInterfaceiv"), &getProgramInterfaceiv);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramResourceIndex"), &getProgramResourceIndex);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramResourceName"), &getProgramResourceName);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramResourceiv"), &getProgramResourceiv);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramResourceLocation"), &getProgramResourceLocation);
+ AssignGLEntryPoint(loadProcAddress("glUseProgramStages"), &useProgramStages);
+ AssignGLEntryPoint(loadProcAddress("glActiveShaderProgram"), &activeShaderProgram);
+ AssignGLEntryPoint(loadProcAddress("glCreateShaderProgramv"), &createShaderProgramv);
+ AssignGLEntryPoint(loadProcAddress("glBindProgramPipeline"), &bindProgramPipeline);
+ AssignGLEntryPoint(loadProcAddress("glDeleteProgramPipelines"), &deleteProgramPipelines);
+ AssignGLEntryPoint(loadProcAddress("glGenProgramPipelines"), &genProgramPipelines);
+ AssignGLEntryPoint(loadProcAddress("glIsProgramPipeline"), &isProgramPipeline);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramPipelineiv"), &getProgramPipelineiv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1i"), &programUniform1i);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2i"), &programUniform2i);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3i"), &programUniform3i);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4i"), &programUniform4i);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1ui"), &programUniform1ui);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2ui"), &programUniform2ui);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3ui"), &programUniform3ui);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4ui"), &programUniform4ui);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1f"), &programUniform1f);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2f"), &programUniform2f);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3f"), &programUniform3f);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4f"), &programUniform4f);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1iv"), &programUniform1iv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2iv"), &programUniform2iv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3iv"), &programUniform3iv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4iv"), &programUniform4iv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1uiv"), &programUniform1uiv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2uiv"), &programUniform2uiv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3uiv"), &programUniform3uiv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4uiv"), &programUniform4uiv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform1fv"), &programUniform1fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform2fv"), &programUniform2fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform3fv"), &programUniform3fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniform4fv"), &programUniform4fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2fv"), &programUniformMatrix2fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3fv"), &programUniformMatrix3fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4fv"), &programUniformMatrix4fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2x3fv"), &programUniformMatrix2x3fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3x2fv"), &programUniformMatrix3x2fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix2x4fv"), &programUniformMatrix2x4fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4x2fv"), &programUniformMatrix4x2fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix3x4fv"), &programUniformMatrix3x4fv);
+ AssignGLEntryPoint(loadProcAddress("glProgramUniformMatrix4x3fv"), &programUniformMatrix4x3fv);
+ AssignGLEntryPoint(loadProcAddress("glValidateProgramPipeline"), &validateProgramPipeline);
+ AssignGLEntryPoint(loadProcAddress("glGetProgramPipelineInfoLog"), &getProgramPipelineInfoLog);
+ AssignGLEntryPoint(loadProcAddress("glBindImageTexture"), &bindImageTexture);
+ AssignGLEntryPoint(loadProcAddress("glGetBooleani_v"), &getBooleani_v);
+ AssignGLEntryPoint(loadProcAddress("glMemoryBarrier"), &memoryBarrier);
+ AssignGLEntryPoint(loadProcAddress("glMemoryBarrierByRegion"), &memoryBarrierByRegion);
+ AssignGLEntryPoint(loadProcAddress("glTexStorage2DMultisample"), &texStorage2DMultisample);
+ AssignGLEntryPoint(loadProcAddress("glGetMultisamplefv"), &getMultisamplefv);
+ AssignGLEntryPoint(loadProcAddress("glSampleMaski"), &sampleMaski);
+ AssignGLEntryPoint(loadProcAddress("glGetTexLevelParameteriv"), &getTexLevelParameteriv);
+ AssignGLEntryPoint(loadProcAddress("glGetTexLevelParameterfv"), &getTexLevelParameterfv);
+ AssignGLEntryPoint(loadProcAddress("glBindVertexBuffer"), &bindVertexBuffer);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribFormat"), &vertexAttribFormat);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribIFormat"), &vertexAttribIFormat);
+ AssignGLEntryPoint(loadProcAddress("glVertexAttribBinding"), &vertexAttribBinding);
+ AssignGLEntryPoint(loadProcAddress("glVertexBindingDivisor"), &vertexBindingDivisor);
+ }
+
+ // 3.2
+ if (isAtLeastGLES(gl::Version(3, 2)))
+ {
+ AssignGLEntryPoint(loadProcAddress("glBlendBarrier"), &blendBarrier);
+ AssignGLEntryPoint(loadProcAddress("glCopyImageSubData"), &copyImageSubData);
+ AssignGLEntryPoint(loadProcAddress("glDebugMessageControl"), &debugMessageControl);
+ AssignGLEntryPoint(loadProcAddress("glDebugMessageInsert"), &debugMessageInsert);
+ AssignGLEntryPoint(loadProcAddress("glDebugMessageCallback"), &debugMessageCallback);
+ AssignGLEntryPoint(loadProcAddress("glGetDebugMessageLog"), &getDebugMessageLog);
+ AssignGLEntryPoint(loadProcAddress("glPushDebugGroup"), &pushDebugGroup);
+ AssignGLEntryPoint(loadProcAddress("glPopDebugGroup"), &popDebugGroup);
+ AssignGLEntryPoint(loadProcAddress("glObjectLabel"), &objectLabel);
+ AssignGLEntryPoint(loadProcAddress("glGetObjectLabel"), &getObjectLabel);
+ AssignGLEntryPoint(loadProcAddress("glObjectPtrLabel"), &objectPtrLabel);
+ AssignGLEntryPoint(loadProcAddress("glGetObjectPtrLabel"), &getObjectPtrLabel);
+ AssignGLEntryPoint(loadProcAddress("glGetPointerv"), &getPointerv);
+ AssignGLEntryPoint(loadProcAddress("glEnablei"), &enablei);
+ AssignGLEntryPoint(loadProcAddress("glDisablei"), &disablei);
+ AssignGLEntryPoint(loadProcAddress("glBlendEquationi"), &blendEquationi);
+ AssignGLEntryPoint(loadProcAddress("glBlendEquationSeparatei"), &blendEquationSeparatei);
+ AssignGLEntryPoint(loadProcAddress("glBlendFunci"), &blendFunci);
+ AssignGLEntryPoint(loadProcAddress("glBlendFuncSeparatei"), &blendFuncSeparatei);
+ AssignGLEntryPoint(loadProcAddress("glColorMaski"), &colorMaski);
+ AssignGLEntryPoint(loadProcAddress("glIsEnabledi"), &isEnabledi);
+ AssignGLEntryPoint(loadProcAddress("glDrawElementsBaseVertex"), &drawElementsBaseVertex);
+ AssignGLEntryPoint(loadProcAddress("glDrawRangeElementsBaseVertex"), &drawRangeElementsBaseVertex);
+ AssignGLEntryPoint(loadProcAddress("glDrawElementsInstancedBaseVertex"), &drawElementsInstancedBaseVertex);
+ AssignGLEntryPoint(loadProcAddress("glFramebufferTexture"), &framebufferTexture);
+ AssignGLEntryPoint(loadProcAddress("glPrimitiveBoundingBox"), &primitiveBoundingBox);
+ AssignGLEntryPoint(loadProcAddress("glGetGraphicsResetStatus"), &getGraphicsResetStatus);
+ AssignGLEntryPoint(loadProcAddress("glReadnPixels"), &readnPixels);
+ AssignGLEntryPoint(loadProcAddress("glGetnUniformfv"), &getnUniformfv);
+ AssignGLEntryPoint(loadProcAddress("glGetnUniformiv"), &getnUniformiv);
+ AssignGLEntryPoint(loadProcAddress("glGetnUniformuiv"), &getnUniformuiv);
+ AssignGLEntryPoint(loadProcAddress("glMinSampleShading"), &minSampleShading);
+ AssignGLEntryPoint(loadProcAddress("glPatchParameteri"), &patchParameteri);
+ AssignGLEntryPoint(loadProcAddress("glTexParameterIiv"), &texParameterIiv);
+ AssignGLEntryPoint(loadProcAddress("glTexParameterIuiv"), &texParameterIuiv);
+ AssignGLEntryPoint(loadProcAddress("glGetTexParameterIiv"), &getTexParameterIiv);
+ AssignGLEntryPoint(loadProcAddress("glGetTexParameterIuiv"), &getTexParameterIuiv);
+ AssignGLEntryPoint(loadProcAddress("glSamplerParameterIiv"), &samplerParameterIiv);
+ AssignGLEntryPoint(loadProcAddress("glSamplerParameterIuiv"), &samplerParameterIuiv);
+ AssignGLEntryPoint(loadProcAddress("glGetSamplerParameterIiv"), &getSamplerParameterIiv);
+ AssignGLEntryPoint(loadProcAddress("glGetSamplerParameterIuiv"), &getSamplerParameterIuiv);
+ AssignGLEntryPoint(loadProcAddress("glTexBuffer"), &texBuffer);
+ AssignGLEntryPoint(loadProcAddress("glTexBufferRange"), &texBufferRange);
+ AssignGLEntryPoint(loadProcAddress("glTexStorage3DMultisample"), &texStorage3DMultisample);
+ }
+
+ // clang-format on
+}
+
+bool FunctionsGL::isAtLeastGL(const gl::Version &glVersion) const
+{
+ return standard == STANDARD_GL_DESKTOP && version >= glVersion;
+}
+
+bool FunctionsGL::isAtMostGL(const gl::Version &glVersion) const
+{
+ return standard == STANDARD_GL_DESKTOP && glVersion >= version;
+}
+
+bool FunctionsGL::isAtLeastGLES(const gl::Version &glesVersion) const
+{
+ return standard == STANDARD_GL_ES && version >= glesVersion;
+}
+
+bool FunctionsGL::isAtMostGLES(const gl::Version &glesVersion) const
+{
+ return standard == STANDARD_GL_ES && glesVersion >= version;
+}
+
+bool FunctionsGL::hasExtension(const std::string &ext) const
+{
+ return std::find(extensions.begin(), extensions.end(), ext) != extensions.end();
+}
+
+bool FunctionsGL::hasGLExtension(const std::string &ext) const
+{
+ return standard == STANDARD_GL_DESKTOP && hasExtension(ext);
+}
+
+bool FunctionsGL::hasGLESExtension(const std::string &ext) const
+{
+ return standard == STANDARD_GL_ES && hasExtension(ext);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.h b/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.h
new file mode 100755
index 000000000..fa8634e57
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.h
@@ -0,0 +1,791 @@
+//
+// Copyright (c) 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.h: Defines the FuntionsGL class to contain loaded GL functions
+
+#ifndef LIBANGLE_RENDERER_GL_FUNCTIONSGL_H_
+#define LIBANGLE_RENDERER_GL_FUNCTIONSGL_H_
+
+#include "common/debug.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/renderer/gl/functionsgl_enums.h"
+#include "libANGLE/renderer/gl/functionsgl_typedefs.h"
+
+namespace rx
+{
+
+enum StandardGL
+{
+ STANDARD_GL_DESKTOP,
+ STANDARD_GL_ES,
+};
+
+class FunctionsGL
+{
+ public:
+ FunctionsGL();
+ virtual ~FunctionsGL();
+
+ void initialize();
+
+ // Version information
+ gl::Version version;
+ StandardGL standard;
+ GLint profile;
+ bool isAtLeastGL(const gl::Version &glVersion) const;
+ bool isAtMostGL(const gl::Version &glVersion) const;
+ bool isAtLeastGLES(const gl::Version &glesVersion) const;
+ bool isAtMostGLES(const gl::Version &glesVersion) const;
+
+ // Extensions
+ std::vector<std::string> extensions;
+ bool hasExtension(const std::string &ext) const;
+ bool hasGLExtension(const std::string &ext) const;
+ bool hasGLESExtension(const std::string &ext) const;
+
+ // Entry Points
+ // 1.0
+ PFNGLBLENDFUNCPROC blendFunc;
+ PFNGLCLEARPROC clear;
+ PFNGLCLEARCOLORPROC clearColor;
+ PFNGLCLEARDEPTHPROC clearDepth;
+ PFNGLCLEARSTENCILPROC clearStencil;
+ PFNGLCOLORMASKPROC colorMask;
+ PFNGLCULLFACEPROC cullFace;
+ PFNGLDEPTHFUNCPROC depthFunc;
+ PFNGLDEPTHMASKPROC depthMask;
+ PFNGLDEPTHRANGEPROC depthRange;
+ PFNGLDISABLEPROC disable;
+ PFNGLDRAWBUFFERPROC drawBuffer;
+ PFNGLENABLEPROC enable;
+ PFNGLFINISHPROC finish;
+ PFNGLFLUSHPROC flush;
+ PFNGLFRONTFACEPROC frontFace;
+ PFNGLGETBOOLEANVPROC getBooleanv;
+ PFNGLGETDOUBLEVPROC getDoublev;
+ PFNGLGETERRORPROC getError;
+ PFNGLGETFLOATVPROC getFloatv;
+ PFNGLGETINTEGERVPROC getIntegerv;
+ PFNGLGETSTRINGPROC getString;
+ PFNGLGETTEXIMAGEPROC getTexImage;
+ PFNGLGETTEXLEVELPARAMETERFVPROC getTexLevelParameterfv;
+ PFNGLGETTEXLEVELPARAMETERIVPROC getTexLevelParameteriv;
+ PFNGLGETTEXPARAMETERFVPROC getTexParameterfv;
+ PFNGLGETTEXPARAMETERIVPROC getTexParameteriv;
+ PFNGLHINTPROC hint;
+ PFNGLISENABLEDPROC isEnabled;
+ PFNGLLINEWIDTHPROC lineWidth;
+ PFNGLLOGICOPPROC logicOp;
+ PFNGLPIXELSTOREFPROC pixelStoref;
+ PFNGLPIXELSTOREIPROC pixelStorei;
+ PFNGLPOINTSIZEPROC pointSize;
+ PFNGLPOLYGONMODEPROC polygonMode;
+ PFNGLREADBUFFERPROC readBuffer;
+ PFNGLREADPIXELSPROC readPixels;
+ PFNGLSCISSORPROC scissor;
+ PFNGLSTENCILFUNCPROC stencilFunc;
+ PFNGLSTENCILMASKPROC stencilMask;
+ PFNGLSTENCILOPPROC stencilOp;
+ PFNGLTEXIMAGE1DPROC texImage1D;
+ PFNGLTEXIMAGE2DPROC texImage2D;
+ PFNGLTEXPARAMETERFPROC texParameterf;
+ PFNGLTEXPARAMETERFVPROC texParameterfv;
+ PFNGLTEXPARAMETERIPROC texParameteri;
+ PFNGLTEXPARAMETERIVPROC texParameteriv;
+ PFNGLVIEWPORTPROC viewport;
+
+ // 1.1
+ PFNGLBINDTEXTUREPROC bindTexture;
+ PFNGLCOPYTEXIMAGE1DPROC copyTexImage1D;
+ PFNGLCOPYTEXIMAGE2DPROC copyTexImage2D;
+ PFNGLCOPYTEXSUBIMAGE1DPROC copyTexSubImage1D;
+ PFNGLCOPYTEXSUBIMAGE2DPROC copyTexSubImage2D;
+ PFNGLDELETETEXTURESPROC deleteTextures;
+ PFNGLDRAWARRAYSPROC drawArrays;
+ PFNGLDRAWELEMENTSPROC drawElements;
+ PFNGLGENTEXTURESPROC genTextures;
+ PFNGLISTEXTUREPROC isTexture;
+ PFNGLPOLYGONOFFSETPROC polygonOffset;
+ PFNGLTEXSUBIMAGE1DPROC texSubImage1D;
+ PFNGLTEXSUBIMAGE2DPROC texSubImage2D;
+
+ // 1.2
+ PFNGLBLENDCOLORPROC blendColor;
+ PFNGLBLENDEQUATIONPROC blendEquation;
+ PFNGLCOPYTEXSUBIMAGE3DPROC copyTexSubImage3D;
+ PFNGLDRAWRANGEELEMENTSPROC drawRangeElements;
+ PFNGLTEXIMAGE3DPROC texImage3D;
+ PFNGLTEXSUBIMAGE3DPROC texSubImage3D;
+
+ // 1.2 Extensions
+ PFNGLDELETEFENCESNVPROC deleteFencesNV;
+ PFNGLGENFENCESNVPROC genFencesNV;
+ PFNGLISFENCENVPROC isFenceNV;
+ PFNGLTESTFENCENVPROC testFenceNV;
+ PFNGLGETFENCEIVNVPROC getFenceivNV;
+ PFNGLFINISHFENCENVPROC finishFenceNV;
+ PFNGLSETFENCENVPROC setFenceNV;
+
+ // 1.3
+ PFNGLACTIVETEXTUREPROC activeTexture;
+ PFNGLCOMPRESSEDTEXIMAGE1DPROC compressedTexImage1D;
+ PFNGLCOMPRESSEDTEXIMAGE2DPROC compressedTexImage2D;
+ PFNGLCOMPRESSEDTEXIMAGE3DPROC compressedTexImage3D;
+ PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC compressedTexSubImage1D;
+ PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC compressedTexSubImage2D;
+ PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC compressedTexSubImage3D;
+ PFNGLGETCOMPRESSEDTEXIMAGEPROC getCompressedTexImage;
+ PFNGLSAMPLECOVERAGEPROC sampleCoverage;
+
+ // 1.4
+ PFNGLBLENDFUNCSEPARATEPROC blendFuncSeparate;
+ PFNGLMULTIDRAWARRAYSPROC multiDrawArrays;
+ PFNGLMULTIDRAWELEMENTSPROC multiDrawElements;
+ PFNGLPOINTPARAMETERFPROC pointParameterf;
+ PFNGLPOINTPARAMETERFVPROC pointParameterfv;
+ PFNGLPOINTPARAMETERIPROC pointParameteri;
+ PFNGLPOINTPARAMETERIVPROC pointParameteriv;
+
+ // 1.5
+ PFNGLBEGINQUERYPROC beginQuery;
+ PFNGLBINDBUFFERPROC bindBuffer;
+ PFNGLBUFFERDATAPROC bufferData;
+ PFNGLBUFFERSUBDATAPROC bufferSubData;
+ PFNGLDELETEBUFFERSPROC deleteBuffers;
+ PFNGLDELETEQUERIESPROC deleteQueries;
+ PFNGLENDQUERYPROC endQuery;
+ PFNGLGENBUFFERSPROC genBuffers;
+ PFNGLGENQUERIESPROC genQueries;
+ PFNGLGETBUFFERPARAMETERIVPROC getBufferParameteriv;
+ PFNGLGETBUFFERPOINTERVPROC getBufferPointerv;
+ PFNGLGETBUFFERSUBDATAPROC getBufferSubData;
+ PFNGLGETQUERYOBJECTIVPROC getQueryObjectiv;
+ PFNGLGETQUERYOBJECTUIVPROC getQueryObjectuiv;
+ PFNGLGETQUERYIVPROC getQueryiv;
+ PFNGLISBUFFERPROC isBuffer;
+ PFNGLISQUERYPROC isQuery;
+ PFNGLMAPBUFFERPROC mapBuffer;
+ PFNGLUNMAPBUFFERPROC unmapBuffer;
+
+ // 2.0
+ PFNGLATTACHSHADERPROC attachShader;
+ PFNGLBINDATTRIBLOCATIONPROC bindAttribLocation;
+ PFNGLBLENDEQUATIONSEPARATEPROC blendEquationSeparate;
+ PFNGLCOMPILESHADERPROC compileShader;
+ PFNGLCREATEPROGRAMPROC createProgram;
+ PFNGLCREATESHADERPROC createShader;
+ PFNGLDELETEPROGRAMPROC deleteProgram;
+ PFNGLDELETESHADERPROC deleteShader;
+ PFNGLDETACHSHADERPROC detachShader;
+ PFNGLDISABLEVERTEXATTRIBARRAYPROC disableVertexAttribArray;
+ PFNGLDRAWBUFFERSPROC drawBuffers;
+ PFNGLENABLEVERTEXATTRIBARRAYPROC enableVertexAttribArray;
+ PFNGLGETACTIVEATTRIBPROC getActiveAttrib;
+ PFNGLGETACTIVEUNIFORMPROC getActiveUniform;
+ PFNGLGETATTACHEDSHADERSPROC getAttachedShaders;
+ PFNGLGETATTRIBLOCATIONPROC getAttribLocation;
+ PFNGLGETPROGRAMINFOLOGPROC getProgramInfoLog;
+ PFNGLGETPROGRAMIVPROC getProgramiv;
+ PFNGLGETSHADERINFOLOGPROC getShaderInfoLog;
+ PFNGLGETSHADERSOURCEPROC getShaderSource;
+ PFNGLGETSHADERIVPROC getShaderiv;
+ PFNGLGETUNIFORMLOCATIONPROC getUniformLocation;
+ PFNGLGETUNIFORMFVPROC getUniformfv;
+ PFNGLGETUNIFORMIVPROC getUniformiv;
+ PFNGLGETVERTEXATTRIBPOINTERVPROC getVertexAttribPointerv;
+ PFNGLGETVERTEXATTRIBDVPROC getVertexAttribdv;
+ PFNGLGETVERTEXATTRIBFVPROC getVertexAttribfv;
+ PFNGLGETVERTEXATTRIBIVPROC getVertexAttribiv;
+ PFNGLISPROGRAMPROC isProgram;
+ PFNGLISSHADERPROC isShader;
+ PFNGLLINKPROGRAMPROC linkProgram;
+ PFNGLSHADERSOURCEPROC shaderSource;
+ PFNGLSTENCILFUNCSEPARATEPROC stencilFuncSeparate;
+ PFNGLSTENCILMASKSEPARATEPROC stencilMaskSeparate;
+ PFNGLSTENCILOPSEPARATEPROC stencilOpSeparate;
+ PFNGLUNIFORM1FPROC uniform1f;
+ PFNGLUNIFORM1FVPROC uniform1fv;
+ PFNGLUNIFORM1IPROC uniform1i;
+ PFNGLUNIFORM1IVPROC uniform1iv;
+ PFNGLUNIFORM2FPROC uniform2f;
+ PFNGLUNIFORM2FVPROC uniform2fv;
+ PFNGLUNIFORM2IPROC uniform2i;
+ PFNGLUNIFORM2IVPROC uniform2iv;
+ PFNGLUNIFORM3FPROC uniform3f;
+ PFNGLUNIFORM3FVPROC uniform3fv;
+ PFNGLUNIFORM3IPROC uniform3i;
+ PFNGLUNIFORM3IVPROC uniform3iv;
+ PFNGLUNIFORM4FPROC uniform4f;
+ PFNGLUNIFORM4FVPROC uniform4fv;
+ PFNGLUNIFORM4IPROC uniform4i;
+ PFNGLUNIFORM4IVPROC uniform4iv;
+ PFNGLUNIFORMMATRIX2FVPROC uniformMatrix2fv;
+ PFNGLUNIFORMMATRIX3FVPROC uniformMatrix3fv;
+ PFNGLUNIFORMMATRIX4FVPROC uniformMatrix4fv;
+ PFNGLUSEPROGRAMPROC useProgram;
+ PFNGLVALIDATEPROGRAMPROC validateProgram;
+ PFNGLVERTEXATTRIB1DPROC vertexAttrib1d;
+ PFNGLVERTEXATTRIB1DVPROC vertexAttrib1dv;
+ PFNGLVERTEXATTRIB1FPROC vertexAttrib1f;
+ PFNGLVERTEXATTRIB1FVPROC vertexAttrib1fv;
+ PFNGLVERTEXATTRIB1SPROC vertexAttrib1s;
+ PFNGLVERTEXATTRIB1SVPROC vertexAttrib1sv;
+ PFNGLVERTEXATTRIB2DPROC vertexAttrib2d;
+ PFNGLVERTEXATTRIB2DVPROC vertexAttrib2dv;
+ PFNGLVERTEXATTRIB2FPROC vertexAttrib2f;
+ PFNGLVERTEXATTRIB2FVPROC vertexAttrib2fv;
+ PFNGLVERTEXATTRIB2SPROC vertexAttrib2s;
+ PFNGLVERTEXATTRIB2SVPROC vertexAttrib2sv;
+ PFNGLVERTEXATTRIB3DPROC vertexAttrib3d;
+ PFNGLVERTEXATTRIB3DVPROC vertexAttrib3dv;
+ PFNGLVERTEXATTRIB3FPROC vertexAttrib3f;
+ PFNGLVERTEXATTRIB3FVPROC vertexAttrib3fv;
+ PFNGLVERTEXATTRIB3SPROC vertexAttrib3s;
+ PFNGLVERTEXATTRIB3SVPROC vertexAttrib3sv;
+ PFNGLVERTEXATTRIB4NBVPROC vertexAttrib4Nbv;
+ PFNGLVERTEXATTRIB4NIVPROC vertexAttrib4Niv;
+ PFNGLVERTEXATTRIB4NSVPROC vertexAttrib4Nsv;
+ PFNGLVERTEXATTRIB4NUBPROC vertexAttrib4Nub;
+ PFNGLVERTEXATTRIB4NUBVPROC vertexAttrib4Nubv;
+ PFNGLVERTEXATTRIB4NUIVPROC vertexAttrib4Nuiv;
+ PFNGLVERTEXATTRIB4NUSVPROC vertexAttrib4Nusv;
+ PFNGLVERTEXATTRIB4BVPROC vertexAttrib4bv;
+ PFNGLVERTEXATTRIB4DPROC vertexAttrib4d;
+ PFNGLVERTEXATTRIB4DVPROC vertexAttrib4dv;
+ PFNGLVERTEXATTRIB4FPROC vertexAttrib4f;
+ PFNGLVERTEXATTRIB4FVPROC vertexAttrib4fv;
+ PFNGLVERTEXATTRIB4IVPROC vertexAttrib4iv;
+ PFNGLVERTEXATTRIB4SPROC vertexAttrib4s;
+ PFNGLVERTEXATTRIB4SVPROC vertexAttrib4sv;
+ PFNGLVERTEXATTRIB4UBVPROC vertexAttrib4ubv;
+ PFNGLVERTEXATTRIB4UIVPROC vertexAttrib4uiv;
+ PFNGLVERTEXATTRIB4USVPROC vertexAttrib4usv;
+ PFNGLVERTEXATTRIBPOINTERPROC vertexAttribPointer;
+
+ // 2.1
+ PFNGLUNIFORMMATRIX2X3FVPROC uniformMatrix2x3fv;
+ PFNGLUNIFORMMATRIX2X4FVPROC uniformMatrix2x4fv;
+ PFNGLUNIFORMMATRIX3X2FVPROC uniformMatrix3x2fv;
+ PFNGLUNIFORMMATRIX3X4FVPROC uniformMatrix3x4fv;
+ PFNGLUNIFORMMATRIX4X2FVPROC uniformMatrix4x2fv;
+ PFNGLUNIFORMMATRIX4X3FVPROC uniformMatrix4x3fv;
+
+ // 3.0
+ PFNGLBEGINCONDITIONALRENDERPROC beginConditionalRender;
+ PFNGLBEGINTRANSFORMFEEDBACKPROC beginTransformFeedback;
+ PFNGLBINDBUFFERBASEPROC bindBufferBase;
+ PFNGLBINDBUFFERRANGEPROC bindBufferRange;
+ PFNGLBINDFRAGDATALOCATIONPROC bindFragDataLocation;
+ PFNGLBINDFRAMEBUFFERPROC bindFramebuffer;
+ PFNGLBINDRENDERBUFFERPROC bindRenderbuffer;
+ PFNGLBINDVERTEXARRAYPROC bindVertexArray;
+ PFNGLBLITFRAMEBUFFERPROC blitFramebuffer;
+ PFNGLCHECKFRAMEBUFFERSTATUSPROC checkFramebufferStatus;
+ PFNGLCLAMPCOLORPROC clampColor;
+ PFNGLCLEARBUFFERFIPROC clearBufferfi;
+ PFNGLCLEARBUFFERFVPROC clearBufferfv;
+ PFNGLCLEARBUFFERIVPROC clearBufferiv;
+ PFNGLCLEARBUFFERUIVPROC clearBufferuiv;
+ PFNGLCOLORMASKIPROC colorMaski;
+ PFNGLDELETEFRAMEBUFFERSPROC deleteFramebuffers;
+ PFNGLDELETERENDERBUFFERSPROC deleteRenderbuffers;
+ PFNGLDELETEVERTEXARRAYSPROC deleteVertexArrays;
+ PFNGLDISABLEIPROC disablei;
+ PFNGLENABLEIPROC enablei;
+ PFNGLENDCONDITIONALRENDERPROC endConditionalRender;
+ PFNGLENDTRANSFORMFEEDBACKPROC endTransformFeedback;
+ PFNGLFLUSHMAPPEDBUFFERRANGEPROC flushMappedBufferRange;
+ PFNGLFRAMEBUFFERRENDERBUFFERPROC framebufferRenderbuffer;
+ PFNGLFRAMEBUFFERTEXTURE1DPROC framebufferTexture1D;
+ PFNGLFRAMEBUFFERTEXTURE2DPROC framebufferTexture2D;
+ PFNGLFRAMEBUFFERTEXTURE3DPROC framebufferTexture3D;
+ PFNGLFRAMEBUFFERTEXTURELAYERPROC framebufferTextureLayer;
+ PFNGLGENFRAMEBUFFERSPROC genFramebuffers;
+ PFNGLGENRENDERBUFFERSPROC genRenderbuffers;
+ PFNGLGENVERTEXARRAYSPROC genVertexArrays;
+ PFNGLGENERATEMIPMAPPROC generateMipmap;
+ PFNGLGETBOOLEANI_VPROC getBooleani_v;
+ PFNGLGETFRAGDATALOCATIONPROC getFragDataLocation;
+ PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC getFramebufferAttachmentParameteriv;
+ PFNGLGETINTEGERI_VPROC getIntegeri_v;
+ PFNGLGETRENDERBUFFERPARAMETERIVPROC getRenderbufferParameteriv;
+ PFNGLGETSTRINGIPROC getStringi;
+ PFNGLGETTEXPARAMETERIIVPROC getTexParameterIiv;
+ PFNGLGETTEXPARAMETERIUIVPROC getTexParameterIuiv;
+ PFNGLGETTRANSFORMFEEDBACKVARYINGPROC getTransformFeedbackVarying;
+ PFNGLGETUNIFORMUIVPROC getUniformuiv;
+ PFNGLGETVERTEXATTRIBIIVPROC getVertexAttribIiv;
+ PFNGLGETVERTEXATTRIBIUIVPROC getVertexAttribIuiv;
+ PFNGLISENABLEDIPROC isEnabledi;
+ PFNGLISFRAMEBUFFERPROC isFramebuffer;
+ PFNGLISRENDERBUFFERPROC isRenderbuffer;
+ PFNGLISVERTEXARRAYPROC isVertexArray;
+ PFNGLMAPBUFFERRANGEPROC mapBufferRange;
+ PFNGLRENDERBUFFERSTORAGEPROC renderbufferStorage;
+ PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC renderbufferStorageMultisample;
+ PFNGLTEXPARAMETERIIVPROC texParameterIiv;
+ PFNGLTEXPARAMETERIUIVPROC texParameterIuiv;
+ PFNGLTRANSFORMFEEDBACKVARYINGSPROC transformFeedbackVaryings;
+ PFNGLUNIFORM1UIPROC uniform1ui;
+ PFNGLUNIFORM1UIVPROC uniform1uiv;
+ PFNGLUNIFORM2UIPROC uniform2ui;
+ PFNGLUNIFORM2UIVPROC uniform2uiv;
+ PFNGLUNIFORM3UIPROC uniform3ui;
+ PFNGLUNIFORM3UIVPROC uniform3uiv;
+ PFNGLUNIFORM4UIPROC uniform4ui;
+ PFNGLUNIFORM4UIVPROC uniform4uiv;
+ PFNGLVERTEXATTRIBI1IPROC vertexAttribI1i;
+ PFNGLVERTEXATTRIBI1IVPROC vertexAttribI1iv;
+ PFNGLVERTEXATTRIBI1UIPROC vertexAttribI1ui;
+ PFNGLVERTEXATTRIBI1UIVPROC vertexAttribI1uiv;
+ PFNGLVERTEXATTRIBI2IPROC vertexAttribI2i;
+ PFNGLVERTEXATTRIBI2IVPROC vertexAttribI2iv;
+ PFNGLVERTEXATTRIBI2UIPROC vertexAttribI2ui;
+ PFNGLVERTEXATTRIBI2UIVPROC vertexAttribI2uiv;
+ PFNGLVERTEXATTRIBI3IPROC vertexAttribI3i;
+ PFNGLVERTEXATTRIBI3IVPROC vertexAttribI3iv;
+ PFNGLVERTEXATTRIBI3UIPROC vertexAttribI3ui;
+ PFNGLVERTEXATTRIBI3UIVPROC vertexAttribI3uiv;
+ PFNGLVERTEXATTRIBI4BVPROC vertexAttribI4bv;
+ PFNGLVERTEXATTRIBI4IPROC vertexAttribI4i;
+ PFNGLVERTEXATTRIBI4IVPROC vertexAttribI4iv;
+ PFNGLVERTEXATTRIBI4SVPROC vertexAttribI4sv;
+ PFNGLVERTEXATTRIBI4UBVPROC vertexAttribI4ubv;
+ PFNGLVERTEXATTRIBI4UIPROC vertexAttribI4ui;
+ PFNGLVERTEXATTRIBI4UIVPROC vertexAttribI4uiv;
+ PFNGLVERTEXATTRIBI4USVPROC vertexAttribI4usv;
+ PFNGLVERTEXATTRIBIPOINTERPROC vertexAttribIPointer;
+
+ // 3.1
+ PFNGLCOPYBUFFERSUBDATAPROC copyBufferSubData;
+ PFNGLDRAWARRAYSINSTANCEDPROC drawArraysInstanced;
+ PFNGLDRAWELEMENTSINSTANCEDPROC drawElementsInstanced;
+ PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC getActiveUniformBlockName;
+ PFNGLGETACTIVEUNIFORMBLOCKIVPROC getActiveUniformBlockiv;
+ PFNGLGETACTIVEUNIFORMNAMEPROC getActiveUniformName;
+ PFNGLGETACTIVEUNIFORMSIVPROC getActiveUniformsiv;
+ PFNGLGETUNIFORMBLOCKINDEXPROC getUniformBlockIndex;
+ PFNGLGETUNIFORMINDICESPROC getUniformIndices;
+ PFNGLPRIMITIVERESTARTINDEXPROC primitiveRestartIndex;
+ PFNGLTEXBUFFERPROC texBuffer;
+ PFNGLUNIFORMBLOCKBINDINGPROC uniformBlockBinding;
+
+ // 3.2
+ PFNGLCLIENTWAITSYNCPROC clientWaitSync;
+ PFNGLDELETESYNCPROC deleteSync;
+ PFNGLDRAWELEMENTSBASEVERTEXPROC drawElementsBaseVertex;
+ PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC drawElementsInstancedBaseVertex;
+ PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC drawRangeElementsBaseVertex;
+ PFNGLFENCESYNCPROC fenceSync;
+ PFNGLFRAMEBUFFERTEXTUREPROC framebufferTexture;
+ PFNGLGETBUFFERPARAMETERI64VPROC getBufferParameteri64v;
+ PFNGLGETINTEGER64I_VPROC getInteger64i_v;
+ PFNGLGETINTEGER64VPROC getInteger64v;
+ PFNGLGETMULTISAMPLEFVPROC getMultisamplefv;
+ PFNGLGETSYNCIVPROC getSynciv;
+ PFNGLISSYNCPROC isSync;
+ PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC multiDrawElementsBaseVertex;
+ PFNGLPROVOKINGVERTEXPROC provokingVertex;
+ PFNGLSAMPLEMASKIPROC sampleMaski;
+ PFNGLTEXIMAGE2DMULTISAMPLEPROC texImage2DMultisample;
+ PFNGLTEXIMAGE3DMULTISAMPLEPROC texImage3DMultisample;
+ PFNGLWAITSYNCPROC waitSync;
+
+ // NV_path_rendering (originally written against 3.2 compatibility profile)
+ PFNGLMATRIXLOADFEXTPROC matrixLoadEXT;
+ PFNGLGENPATHSNVPROC genPathsNV;
+ PFNGLDELETEPATHSNVPROC delPathsNV;
+ PFNGLPATHCOMMANDSNVPROC pathCommandsNV;
+ PFNGLISPATHNVPROC isPathNV;
+ PFNGLPATHPARAMETERFNVPROC setPathParameterfNV;
+ PFNGLPATHPARAMETERINVPROC setPathParameteriNV;
+ PFNGLGETPATHPARAMETERFVNVPROC getPathParameterfNV;
+ PFNGLGETPATHPARAMETERIVNVPROC getPathParameteriNV;
+ PFNGLPATHSTENCILFUNCNVPROC pathStencilFuncNV;
+ PFNGLSTENCILFILLPATHNVPROC stencilFillPathNV;
+ PFNGLSTENCILSTROKEPATHNVPROC stencilStrokePathNV;
+ PFNGLCOVERFILLPATHNVPROC coverFillPathNV;
+ PFNGLCOVERSTROKEPATHNVPROC coverStrokePathNV;
+ PFNGLSTENCILTHENCOVERFILLPATHNVPROC stencilThenCoverFillPathNV;
+ PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC stencilThenCoverStrokePathNV;
+ PFNGLCOVERFILLPATHINSTANCEDNVPROC coverFillPathInstancedNV;
+ PFNGLCOVERSTROKEPATHINSTANCEDNVPROC coverStrokePathInstancedNV;
+ PFNGLSTENCILFILLPATHINSTANCEDNVPROC stencilFillPathInstancedNV;
+ PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC stencilStrokePathInstancedNV;
+ PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC stencilThenCoverFillPathInstancedNV;
+ PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC stencilThenCoverStrokePathInstancedNV;
+ PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC programPathFragmentInputGenNV;
+
+ // 3.3
+ PFNGLBINDFRAGDATALOCATIONINDEXEDPROC bindFragDataLocationIndexed;
+ PFNGLBINDSAMPLERPROC bindSampler;
+ PFNGLDELETESAMPLERSPROC deleteSamplers;
+ PFNGLGENSAMPLERSPROC genSamplers;
+ PFNGLGETFRAGDATAINDEXPROC getFragDataIndex;
+ PFNGLGETQUERYOBJECTI64VPROC getQueryObjecti64v;
+ PFNGLGETQUERYOBJECTUI64VPROC getQueryObjectui64v;
+ PFNGLGETSAMPLERPARAMETERIIVPROC getSamplerParameterIiv;
+ PFNGLGETSAMPLERPARAMETERIUIVPROC getSamplerParameterIuiv;
+ PFNGLGETSAMPLERPARAMETERFVPROC getSamplerParameterfv;
+ PFNGLGETSAMPLERPARAMETERIVPROC getSamplerParameteriv;
+ PFNGLISSAMPLERPROC isSampler;
+ PFNGLQUERYCOUNTERPROC queryCounter;
+ PFNGLSAMPLERPARAMETERIIVPROC samplerParameterIiv;
+ PFNGLSAMPLERPARAMETERIUIVPROC samplerParameterIuiv;
+ PFNGLSAMPLERPARAMETERFPROC samplerParameterf;
+ PFNGLSAMPLERPARAMETERFVPROC samplerParameterfv;
+ PFNGLSAMPLERPARAMETERIPROC samplerParameteri;
+ PFNGLSAMPLERPARAMETERIVPROC samplerParameteriv;
+ PFNGLVERTEXATTRIBDIVISORPROC vertexAttribDivisor;
+ PFNGLVERTEXATTRIBP1UIPROC vertexAttribP1ui;
+ PFNGLVERTEXATTRIBP1UIVPROC vertexAttribP1uiv;
+ PFNGLVERTEXATTRIBP2UIPROC vertexAttribP2ui;
+ PFNGLVERTEXATTRIBP2UIVPROC vertexAttribP2uiv;
+ PFNGLVERTEXATTRIBP3UIPROC vertexAttribP3ui;
+ PFNGLVERTEXATTRIBP3UIVPROC vertexAttribP3uiv;
+ PFNGLVERTEXATTRIBP4UIPROC vertexAttribP4ui;
+ PFNGLVERTEXATTRIBP4UIVPROC vertexAttribP4uiv;
+
+ // 4.0
+ PFNGLBEGINQUERYINDEXEDPROC beginQueryIndexed;
+ PFNGLBINDTRANSFORMFEEDBACKPROC bindTransformFeedback;
+ PFNGLBLENDEQUATIONSEPARATEIPROC blendEquationSeparatei;
+ PFNGLBLENDEQUATIONIPROC blendEquationi;
+ PFNGLBLENDFUNCSEPARATEIPROC blendFuncSeparatei;
+ PFNGLBLENDFUNCIPROC blendFunci;
+ PFNGLDELETETRANSFORMFEEDBACKSPROC deleteTransformFeedbacks;
+ PFNGLDRAWARRAYSINDIRECTPROC drawArraysIndirect;
+ PFNGLDRAWELEMENTSINDIRECTPROC drawElementsIndirect;
+ PFNGLDRAWTRANSFORMFEEDBACKPROC drawTransformFeedback;
+ PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC drawTransformFeedbackStream;
+ PFNGLENDQUERYINDEXEDPROC endQueryIndexed;
+ PFNGLGENTRANSFORMFEEDBACKSPROC genTransformFeedbacks;
+ PFNGLGETACTIVESUBROUTINENAMEPROC getActiveSubroutineName;
+ PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC getActiveSubroutineUniformName;
+ PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC getActiveSubroutineUniformiv;
+ PFNGLGETPROGRAMSTAGEIVPROC getProgramStageiv;
+ PFNGLGETQUERYINDEXEDIVPROC getQueryIndexediv;
+ PFNGLGETSUBROUTINEINDEXPROC getSubroutineIndex;
+ PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC getSubroutineUniformLocation;
+ PFNGLGETUNIFORMSUBROUTINEUIVPROC getUniformSubroutineuiv;
+ PFNGLGETUNIFORMDVPROC getUniformdv;
+ PFNGLISTRANSFORMFEEDBACKPROC isTransformFeedback;
+ PFNGLMINSAMPLESHADINGPROC minSampleShading;
+ PFNGLPATCHPARAMETERFVPROC patchParameterfv;
+ PFNGLPATCHPARAMETERIPROC patchParameteri;
+ PFNGLPAUSETRANSFORMFEEDBACKPROC pauseTransformFeedback;
+ PFNGLRESUMETRANSFORMFEEDBACKPROC resumeTransformFeedback;
+ PFNGLUNIFORM1DPROC uniform1d;
+ PFNGLUNIFORM1DVPROC uniform1dv;
+ PFNGLUNIFORM2DPROC uniform2d;
+ PFNGLUNIFORM2DVPROC uniform2dv;
+ PFNGLUNIFORM3DPROC uniform3d;
+ PFNGLUNIFORM3DVPROC uniform3dv;
+ PFNGLUNIFORM4DPROC uniform4d;
+ PFNGLUNIFORM4DVPROC uniform4dv;
+ PFNGLUNIFORMMATRIX2DVPROC uniformMatrix2dv;
+ PFNGLUNIFORMMATRIX2X3DVPROC uniformMatrix2x3dv;
+ PFNGLUNIFORMMATRIX2X4DVPROC uniformMatrix2x4dv;
+ PFNGLUNIFORMMATRIX3DVPROC uniformMatrix3dv;
+ PFNGLUNIFORMMATRIX3X2DVPROC uniformMatrix3x2dv;
+ PFNGLUNIFORMMATRIX3X4DVPROC uniformMatrix3x4dv;
+ PFNGLUNIFORMMATRIX4DVPROC uniformMatrix4dv;
+ PFNGLUNIFORMMATRIX4X2DVPROC uniformMatrix4x2dv;
+ PFNGLUNIFORMMATRIX4X3DVPROC uniformMatrix4x3dv;
+ PFNGLUNIFORMSUBROUTINESUIVPROC uniformSubroutinesuiv;
+
+ // 4.1
+ PFNGLACTIVESHADERPROGRAMPROC activeShaderProgram;
+ PFNGLBINDPROGRAMPIPELINEPROC bindProgramPipeline;
+ PFNGLCLEARDEPTHFPROC clearDepthf;
+ PFNGLCREATESHADERPROGRAMVPROC createShaderProgramv;
+ PFNGLDELETEPROGRAMPIPELINESPROC deleteProgramPipelines;
+ PFNGLDEPTHRANGEARRAYVPROC depthRangeArrayv;
+ PFNGLDEPTHRANGEINDEXEDPROC depthRangeIndexed;
+ PFNGLDEPTHRANGEFPROC depthRangef;
+ PFNGLGENPROGRAMPIPELINESPROC genProgramPipelines;
+ PFNGLGETDOUBLEI_VPROC getDoublei_v;
+ PFNGLGETFLOATI_VPROC getFloati_v;
+ PFNGLGETPROGRAMBINARYPROC getProgramBinary;
+ PFNGLGETPROGRAMPIPELINEINFOLOGPROC getProgramPipelineInfoLog;
+ PFNGLGETPROGRAMPIPELINEIVPROC getProgramPipelineiv;
+ PFNGLGETSHADERPRECISIONFORMATPROC getShaderPrecisionFormat;
+ PFNGLGETVERTEXATTRIBLDVPROC getVertexAttribLdv;
+ PFNGLISPROGRAMPIPELINEPROC isProgramPipeline;
+ PFNGLPROGRAMBINARYPROC programBinary;
+ PFNGLPROGRAMPARAMETERIPROC programParameteri;
+ PFNGLPROGRAMUNIFORM1DPROC programUniform1d;
+ PFNGLPROGRAMUNIFORM1DVPROC programUniform1dv;
+ PFNGLPROGRAMUNIFORM1FPROC programUniform1f;
+ PFNGLPROGRAMUNIFORM1FVPROC programUniform1fv;
+ PFNGLPROGRAMUNIFORM1IPROC programUniform1i;
+ PFNGLPROGRAMUNIFORM1IVPROC programUniform1iv;
+ PFNGLPROGRAMUNIFORM1UIPROC programUniform1ui;
+ PFNGLPROGRAMUNIFORM1UIVPROC programUniform1uiv;
+ PFNGLPROGRAMUNIFORM2DPROC programUniform2d;
+ PFNGLPROGRAMUNIFORM2DVPROC programUniform2dv;
+ PFNGLPROGRAMUNIFORM2FPROC programUniform2f;
+ PFNGLPROGRAMUNIFORM2FVPROC programUniform2fv;
+ PFNGLPROGRAMUNIFORM2IPROC programUniform2i;
+ PFNGLPROGRAMUNIFORM2IVPROC programUniform2iv;
+ PFNGLPROGRAMUNIFORM2UIPROC programUniform2ui;
+ PFNGLPROGRAMUNIFORM2UIVPROC programUniform2uiv;
+ PFNGLPROGRAMUNIFORM3DPROC programUniform3d;
+ PFNGLPROGRAMUNIFORM3DVPROC programUniform3dv;
+ PFNGLPROGRAMUNIFORM3FPROC programUniform3f;
+ PFNGLPROGRAMUNIFORM3FVPROC programUniform3fv;
+ PFNGLPROGRAMUNIFORM3IPROC programUniform3i;
+ PFNGLPROGRAMUNIFORM3IVPROC programUniform3iv;
+ PFNGLPROGRAMUNIFORM3UIPROC programUniform3ui;
+ PFNGLPROGRAMUNIFORM3UIVPROC programUniform3uiv;
+ PFNGLPROGRAMUNIFORM4DPROC programUniform4d;
+ PFNGLPROGRAMUNIFORM4DVPROC programUniform4dv;
+ PFNGLPROGRAMUNIFORM4FPROC programUniform4f;
+ PFNGLPROGRAMUNIFORM4FVPROC programUniform4fv;
+ PFNGLPROGRAMUNIFORM4IPROC programUniform4i;
+ PFNGLPROGRAMUNIFORM4IVPROC programUniform4iv;
+ PFNGLPROGRAMUNIFORM4UIPROC programUniform4ui;
+ PFNGLPROGRAMUNIFORM4UIVPROC programUniform4uiv;
+ PFNGLPROGRAMUNIFORMMATRIX2DVPROC programUniformMatrix2dv;
+ PFNGLPROGRAMUNIFORMMATRIX2FVPROC programUniformMatrix2fv;
+ PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC programUniformMatrix2x3dv;
+ PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC programUniformMatrix2x3fv;
+ PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC programUniformMatrix2x4dv;
+ PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC programUniformMatrix2x4fv;
+ PFNGLPROGRAMUNIFORMMATRIX3DVPROC programUniformMatrix3dv;
+ PFNGLPROGRAMUNIFORMMATRIX3FVPROC programUniformMatrix3fv;
+ PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC programUniformMatrix3x2dv;
+ PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC programUniformMatrix3x2fv;
+ PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC programUniformMatrix3x4dv;
+ PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC programUniformMatrix3x4fv;
+ PFNGLPROGRAMUNIFORMMATRIX4DVPROC programUniformMatrix4dv;
+ PFNGLPROGRAMUNIFORMMATRIX4FVPROC programUniformMatrix4fv;
+ PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC programUniformMatrix4x2dv;
+ PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC programUniformMatrix4x2fv;
+ PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC programUniformMatrix4x3dv;
+ PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC programUniformMatrix4x3fv;
+ PFNGLRELEASESHADERCOMPILERPROC releaseShaderCompiler;
+ PFNGLSCISSORARRAYVPROC scissorArrayv;
+ PFNGLSCISSORINDEXEDPROC scissorIndexed;
+ PFNGLSCISSORINDEXEDVPROC scissorIndexedv;
+ PFNGLSHADERBINARYPROC shaderBinary;
+ PFNGLUSEPROGRAMSTAGESPROC useProgramStages;
+ PFNGLVALIDATEPROGRAMPIPELINEPROC validateProgramPipeline;
+ PFNGLVERTEXATTRIBL1DPROC vertexAttribL1d;
+ PFNGLVERTEXATTRIBL1DVPROC vertexAttribL1dv;
+ PFNGLVERTEXATTRIBL2DPROC vertexAttribL2d;
+ PFNGLVERTEXATTRIBL2DVPROC vertexAttribL2dv;
+ PFNGLVERTEXATTRIBL3DPROC vertexAttribL3d;
+ PFNGLVERTEXATTRIBL3DVPROC vertexAttribL3dv;
+ PFNGLVERTEXATTRIBL4DPROC vertexAttribL4d;
+ PFNGLVERTEXATTRIBL4DVPROC vertexAttribL4dv;
+ PFNGLVERTEXATTRIBLPOINTERPROC vertexAttribLPointer;
+ PFNGLVIEWPORTARRAYVPROC viewportArrayv;
+ PFNGLVIEWPORTINDEXEDFPROC viewportIndexedf;
+ PFNGLVIEWPORTINDEXEDFVPROC viewportIndexedfv;
+
+ // 4.2
+ PFNGLBINDIMAGETEXTUREPROC bindImageTexture;
+ PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC drawArraysInstancedBaseInstance;
+ PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC drawElementsInstancedBaseInstance;
+ PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC drawElementsInstancedBaseVertexBaseInstance;
+ PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC drawTransformFeedbackInstanced;
+ PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC drawTransformFeedbackStreamInstanced;
+ PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC getActiveAtomicCounterBufferiv;
+ PFNGLGETINTERNALFORMATIVPROC getInternalformativ;
+ PFNGLMEMORYBARRIERPROC memoryBarrier;
+ PFNGLTEXSTORAGE1DPROC texStorage1D;
+ PFNGLTEXSTORAGE2DPROC texStorage2D;
+ PFNGLTEXSTORAGE3DPROC texStorage3D;
+
+ // 4.3
+ PFNGLBINDVERTEXBUFFERPROC bindVertexBuffer;
+ PFNGLCLEARBUFFERDATAPROC clearBufferData;
+ PFNGLCLEARBUFFERSUBDATAPROC clearBufferSubData;
+ PFNGLCOPYIMAGESUBDATAPROC copyImageSubData;
+ PFNGLDEBUGMESSAGECALLBACKPROC debugMessageCallback;
+ PFNGLDEBUGMESSAGECONTROLPROC debugMessageControl;
+ PFNGLDEBUGMESSAGEINSERTPROC debugMessageInsert;
+ PFNGLDISPATCHCOMPUTEPROC dispatchCompute;
+ PFNGLDISPATCHCOMPUTEINDIRECTPROC dispatchComputeIndirect;
+ PFNGLFRAMEBUFFERPARAMETERIPROC framebufferParameteri;
+ PFNGLGETDEBUGMESSAGELOGPROC getDebugMessageLog;
+ PFNGLGETFRAMEBUFFERPARAMETERIVPROC getFramebufferParameteriv;
+ PFNGLGETINTERNALFORMATI64VPROC getInternalformati64v;
+ PFNGLGETPOINTERVPROC getPointerv;
+ PFNGLGETOBJECTLABELPROC getObjectLabel;
+ PFNGLGETOBJECTPTRLABELPROC getObjectPtrLabel;
+ PFNGLGETPROGRAMINTERFACEIVPROC getProgramInterfaceiv;
+ PFNGLGETPROGRAMRESOURCEINDEXPROC getProgramResourceIndex;
+ PFNGLGETPROGRAMRESOURCELOCATIONPROC getProgramResourceLocation;
+ PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC getProgramResourceLocationIndex;
+ PFNGLGETPROGRAMRESOURCENAMEPROC getProgramResourceName;
+ PFNGLGETPROGRAMRESOURCEIVPROC getProgramResourceiv;
+ PFNGLINVALIDATEBUFFERDATAPROC invalidateBufferData;
+ PFNGLINVALIDATEBUFFERSUBDATAPROC invalidateBufferSubData;
+ PFNGLINVALIDATEFRAMEBUFFERPROC invalidateFramebuffer;
+ PFNGLINVALIDATESUBFRAMEBUFFERPROC invalidateSubFramebuffer;
+ PFNGLINVALIDATETEXIMAGEPROC invalidateTexImage;
+ PFNGLINVALIDATETEXSUBIMAGEPROC invalidateTexSubImage;
+ PFNGLMULTIDRAWARRAYSINDIRECTPROC multiDrawArraysIndirect;
+ PFNGLMULTIDRAWELEMENTSINDIRECTPROC multiDrawElementsIndirect;
+ PFNGLOBJECTLABELPROC objectLabel;
+ PFNGLOBJECTPTRLABELPROC objectPtrLabel;
+ PFNGLPOPDEBUGGROUPPROC popDebugGroup;
+ PFNGLPUSHDEBUGGROUPPROC pushDebugGroup;
+ PFNGLSHADERSTORAGEBLOCKBINDINGPROC shaderStorageBlockBinding;
+ PFNGLTEXBUFFERRANGEPROC texBufferRange;
+ PFNGLTEXSTORAGE2DMULTISAMPLEPROC texStorage2DMultisample;
+ PFNGLTEXSTORAGE3DMULTISAMPLEPROC texStorage3DMultisample;
+ PFNGLTEXTUREVIEWPROC textureView;
+ PFNGLVERTEXATTRIBBINDINGPROC vertexAttribBinding;
+ PFNGLVERTEXATTRIBFORMATPROC vertexAttribFormat;
+ PFNGLVERTEXATTRIBIFORMATPROC vertexAttribIFormat;
+ PFNGLVERTEXATTRIBLFORMATPROC vertexAttribLFormat;
+ PFNGLVERTEXBINDINGDIVISORPROC vertexBindingDivisor;
+ PFNGLCOVERAGEMODULATIONNVPROC coverageModulationNV;
+
+ // 4.4
+ PFNGLBINDBUFFERSBASEPROC bindBuffersBase;
+ PFNGLBINDBUFFERSRANGEPROC bindBuffersRange;
+ PFNGLBINDIMAGETEXTURESPROC bindImageTextures;
+ PFNGLBINDSAMPLERSPROC bindSamplers;
+ PFNGLBINDTEXTURESPROC bindTextures;
+ PFNGLBINDVERTEXBUFFERSPROC bindVertexBuffers;
+ PFNGLBUFFERSTORAGEPROC bufferStorage;
+ PFNGLCLEARTEXIMAGEPROC clearTexImage;
+ PFNGLCLEARTEXSUBIMAGEPROC clearTexSubImage;
+
+ // 4.5
+ PFNGLBINDTEXTUREUNITPROC bindTextureUnit;
+ PFNGLBLITNAMEDFRAMEBUFFERPROC blitNamedFramebuffer;
+ PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC checkNamedFramebufferStatus;
+ PFNGLCLEARNAMEDBUFFERDATAPROC clearNamedBufferData;
+ PFNGLCLEARNAMEDBUFFERSUBDATAPROC clearNamedBufferSubData;
+ PFNGLCLEARNAMEDFRAMEBUFFERFIPROC clearNamedFramebufferfi;
+ PFNGLCLEARNAMEDFRAMEBUFFERFVPROC clearNamedFramebufferfv;
+ PFNGLCLEARNAMEDFRAMEBUFFERIVPROC clearNamedFramebufferiv;
+ PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC clearNamedFramebufferuiv;
+ PFNGLCLIPCONTROLPROC clipControl;
+ PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC compressedTextureSubImage1D;
+ PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC compressedTextureSubImage2D;
+ PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC compressedTextureSubImage3D;
+ PFNGLCOPYNAMEDBUFFERSUBDATAPROC copyNamedBufferSubData;
+ PFNGLCOPYTEXTURESUBIMAGE1DPROC copyTextureSubImage1D;
+ PFNGLCOPYTEXTURESUBIMAGE2DPROC copyTextureSubImage2D;
+ PFNGLCOPYTEXTURESUBIMAGE3DPROC copyTextureSubImage3D;
+ PFNGLCREATEBUFFERSPROC createBuffers;
+ PFNGLCREATEFRAMEBUFFERSPROC createFramebuffers;
+ PFNGLCREATEPROGRAMPIPELINESPROC createProgramPipelines;
+ PFNGLCREATEQUERIESPROC createQueries;
+ PFNGLCREATERENDERBUFFERSPROC createRenderbuffers;
+ PFNGLCREATESAMPLERSPROC createSamplers;
+ PFNGLCREATETEXTURESPROC createTextures;
+ PFNGLCREATETRANSFORMFEEDBACKSPROC createTransformFeedbacks;
+ PFNGLCREATEVERTEXARRAYSPROC createVertexArrays;
+ PFNGLDISABLEVERTEXARRAYATTRIBPROC disableVertexArrayAttrib;
+ PFNGLENABLEVERTEXARRAYATTRIBPROC enableVertexArrayAttrib;
+ PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC flushMappedNamedBufferRange;
+ PFNGLGENERATETEXTUREMIPMAPPROC generateTextureMipmap;
+ PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC getCompressedTextureImage;
+ PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC getCompressedTextureSubImage;
+ PFNGLGETGRAPHICSRESETSTATUSPROC getGraphicsResetStatus;
+ PFNGLGETNAMEDBUFFERPARAMETERI64VPROC getNamedBufferParameteri64v;
+ PFNGLGETNAMEDBUFFERPARAMETERIVPROC getNamedBufferParameteriv;
+ PFNGLGETNAMEDBUFFERPOINTERVPROC getNamedBufferPointerv;
+ PFNGLGETNAMEDBUFFERSUBDATAPROC getNamedBufferSubData;
+ PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC getNamedFramebufferAttachmentParameteriv;
+ PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC getNamedFramebufferParameteriv;
+ PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC getNamedRenderbufferParameteriv;
+ PFNGLGETQUERYBUFFEROBJECTI64VPROC getQueryBufferObjecti64v;
+ PFNGLGETQUERYBUFFEROBJECTIVPROC getQueryBufferObjectiv;
+ PFNGLGETQUERYBUFFEROBJECTUI64VPROC getQueryBufferObjectui64v;
+ PFNGLGETQUERYBUFFEROBJECTUIVPROC getQueryBufferObjectuiv;
+ PFNGLGETTEXTUREIMAGEPROC getTextureImage;
+ PFNGLGETTEXTURELEVELPARAMETERFVPROC getTextureLevelParameterfv;
+ PFNGLGETTEXTURELEVELPARAMETERIVPROC getTextureLevelParameteriv;
+ PFNGLGETTEXTUREPARAMETERIIVPROC getTextureParameterIiv;
+ PFNGLGETTEXTUREPARAMETERIUIVPROC getTextureParameterIuiv;
+ PFNGLGETTEXTUREPARAMETERFVPROC getTextureParameterfv;
+ PFNGLGETTEXTUREPARAMETERIVPROC getTextureParameteriv;
+ PFNGLGETTEXTURESUBIMAGEPROC getTextureSubImage;
+ PFNGLGETTRANSFORMFEEDBACKI64_VPROC getTransformFeedbacki64_v;
+ PFNGLGETTRANSFORMFEEDBACKI_VPROC getTransformFeedbacki_v;
+ PFNGLGETTRANSFORMFEEDBACKIVPROC getTransformFeedbackiv;
+ PFNGLGETVERTEXARRAYINDEXED64IVPROC getVertexArrayIndexed64iv;
+ PFNGLGETVERTEXARRAYINDEXEDIVPROC getVertexArrayIndexediv;
+ PFNGLGETVERTEXARRAYIVPROC getVertexArrayiv;
+ PFNGLGETNCOMPRESSEDTEXIMAGEPROC getnCompressedTexImage;
+ PFNGLGETNTEXIMAGEPROC getnTexImage;
+ PFNGLGETNUNIFORMDVPROC getnUniformdv;
+ PFNGLGETNUNIFORMFVPROC getnUniformfv;
+ PFNGLGETNUNIFORMIVPROC getnUniformiv;
+ PFNGLGETNUNIFORMUIVPROC getnUniformuiv;
+ PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC invalidateNamedFramebufferData;
+ PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC invalidateNamedFramebufferSubData;
+ PFNGLMAPNAMEDBUFFERPROC mapNamedBuffer;
+ PFNGLMAPNAMEDBUFFERRANGEPROC mapNamedBufferRange;
+ PFNGLMEMORYBARRIERBYREGIONPROC memoryBarrierByRegion;
+ PFNGLNAMEDBUFFERDATAPROC namedBufferData;
+ PFNGLNAMEDBUFFERSTORAGEPROC namedBufferStorage;
+ PFNGLNAMEDBUFFERSUBDATAPROC namedBufferSubData;
+ PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC namedFramebufferDrawBuffer;
+ PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC namedFramebufferDrawBuffers;
+ PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC namedFramebufferParameteri;
+ PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC namedFramebufferReadBuffer;
+ PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC namedFramebufferRenderbuffer;
+ PFNGLNAMEDFRAMEBUFFERTEXTUREPROC namedFramebufferTexture;
+ PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC namedFramebufferTextureLayer;
+ PFNGLNAMEDRENDERBUFFERSTORAGEPROC namedRenderbufferStorage;
+ PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC namedRenderbufferStorageMultisample;
+ PFNGLREADNPIXELSPROC readnPixels;
+ PFNGLTEXTUREBARRIERPROC textureBarrier;
+ PFNGLTEXTUREBUFFERPROC textureBuffer;
+ PFNGLTEXTUREBUFFERRANGEPROC textureBufferRange;
+ PFNGLTEXTUREPARAMETERIIVPROC textureParameterIiv;
+ PFNGLTEXTUREPARAMETERIUIVPROC textureParameterIuiv;
+ PFNGLTEXTUREPARAMETERFPROC textureParameterf;
+ PFNGLTEXTUREPARAMETERFVPROC textureParameterfv;
+ PFNGLTEXTUREPARAMETERIPROC textureParameteri;
+ PFNGLTEXTUREPARAMETERIVPROC textureParameteriv;
+ PFNGLTEXTURESTORAGE1DPROC textureStorage1D;
+ PFNGLTEXTURESTORAGE2DPROC textureStorage2D;
+ PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC textureStorage2DMultisample;
+ PFNGLTEXTURESTORAGE3DPROC textureStorage3D;
+ PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC textureStorage3DMultisample;
+ PFNGLTEXTURESUBIMAGE1DPROC textureSubImage1D;
+ PFNGLTEXTURESUBIMAGE2DPROC textureSubImage2D;
+ PFNGLTEXTURESUBIMAGE3DPROC textureSubImage3D;
+ PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC transformFeedbackBufferBase;
+ PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC transformFeedbackBufferRange;
+ PFNGLUNMAPNAMEDBUFFERPROC unmapNamedBuffer;
+ PFNGLVERTEXARRAYATTRIBBINDINGPROC vertexArrayAttribBinding;
+ PFNGLVERTEXARRAYATTRIBFORMATPROC vertexArrayAttribFormat;
+ PFNGLVERTEXARRAYATTRIBIFORMATPROC vertexArrayAttribIFormat;
+ PFNGLVERTEXARRAYATTRIBLFORMATPROC vertexArrayAttribLFormat;
+ PFNGLVERTEXARRAYBINDINGDIVISORPROC vertexArrayBindingDivisor;
+ PFNGLVERTEXARRAYELEMENTBUFFERPROC vertexArrayElementBuffer;
+ PFNGLVERTEXARRAYVERTEXBUFFERPROC vertexArrayVertexBuffer;
+ PFNGLVERTEXARRAYVERTEXBUFFERSPROC vertexArrayVertexBuffers;
+
+ // ES 3.2
+ PFNGLBLENDBARRIERPROC blendBarrier;
+ PFNGLPRIMITIVEBOUNDINGBOXPROC primitiveBoundingBox;
+
+ // ES extensions
+ PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC eglImageTargetRenderbufferStorageOES;
+ PFNGLEGLIMAGETARGETTEXTURE2DOESPROC eglImageTargetTexture2DOES;
+
+ private:
+ void initializeProcsDesktopGL();
+ void initializeProcsGLES();
+
+ virtual void *loadProcAddress(const std::string &function) = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_FUNCTIONSGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/PathGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/PathGL.cpp
new file mode 100755
index 000000000..a859bd759
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/PathGL.cpp
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 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.
+//
+
+// PathGL.cpp: Implementation for PathGL class.
+
+#include "libANGLE/renderer/gl/PathGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
+namespace rx
+{
+
+PathGL::PathGL(const FunctionsGL *functions, GLuint path) : mFunctions(functions), mPathID(path)
+{
+}
+
+PathGL::~PathGL()
+{
+}
+
+gl::Error PathGL::setCommands(GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords)
+{
+ mFunctions->pathCommandsNV(mPathID, numCommands, commands, numCoords, coordType, coords);
+ return gl::Error(GL_NO_ERROR);
+}
+
+void PathGL::setPathParameter(GLenum pname, GLfloat value)
+{
+ mFunctions->setPathParameterfNV(mPathID, pname, value);
+}
+
+} // rx \ No newline at end of file
diff --git a/gfx/angle/src/libANGLE/renderer/gl/PathGL.h b/gfx/angle/src/libANGLE/renderer/gl/PathGL.h
new file mode 100755
index 000000000..461d39aec
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/PathGL.h
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 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.
+//
+
+// PathGL.h: Class definition for CHROMIUM_path_rendering path object for the
+// GL backend.
+
+#ifndef LIBANGLE_RENDERER_GL_PATHIMPL_H_
+#define LIBANGLE_RENDERER_GL_PATHIMPL_H_
+
+#include "libANGLE/renderer/PathImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+
+class PathGL : public PathImpl
+{
+ public:
+ PathGL(const FunctionsGL *functions, GLuint path);
+ ~PathGL();
+
+ gl::Error setCommands(GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords) override;
+
+ void setPathParameter(GLenum pname, GLfloat value) override;
+
+ GLuint getPathID() const { return mPathID; }
+
+ private:
+ const FunctionsGL *mFunctions;
+
+ GLuint mPathID;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_PATHIMPL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/ProgramGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/ProgramGL.cpp
new file mode 100755
index 000000000..88c7df720
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/ProgramGL.cpp
@@ -0,0 +1,588 @@
+//
+// 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.
+//
+
+// ProgramGL.cpp: Implements the class methods for ProgramGL.
+
+#include "libANGLE/renderer/gl/ProgramGL.h"
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "common/string_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/ShaderGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "libANGLE/Uniform.h"
+#include "platform/Platform.h"
+
+namespace rx
+{
+
+ProgramGL::ProgramGL(const gl::ProgramState &data,
+ const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ StateManagerGL *stateManager,
+ bool enablePathRendering)
+ : ProgramImpl(data),
+ mFunctions(functions),
+ mWorkarounds(workarounds),
+ mStateManager(stateManager),
+ mEnablePathRendering(enablePathRendering),
+ mProgramID(0)
+{
+ ASSERT(mFunctions);
+ ASSERT(mStateManager);
+
+ mProgramID = mFunctions->createProgram();
+}
+
+ProgramGL::~ProgramGL()
+{
+ mFunctions->deleteProgram(mProgramID);
+ mProgramID = 0;
+}
+
+LinkResult ProgramGL::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
+{
+ preLink();
+
+ // Read the binary format, size and blob
+ GLenum binaryFormat = stream->readInt<GLenum>();
+ GLint binaryLength = stream->readInt<GLint>();
+ const uint8_t *binary = stream->data() + stream->offset();
+ stream->skip(binaryLength);
+
+ // Load the binary
+ mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);
+
+ // Verify that the program linked
+ if (!checkLinkStatus(infoLog))
+ {
+ return false;
+ }
+
+ postLink();
+
+ return true;
+}
+
+gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
+{
+ GLint binaryLength = 0;
+ mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
+
+ std::vector<uint8_t> binary(binaryLength);
+ GLenum binaryFormat = GL_NONE;
+ mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
+ &binary[0]);
+
+ stream->writeInt(binaryFormat);
+ stream->writeInt(binaryLength);
+ stream->writeBytes(&binary[0], binaryLength);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void ProgramGL::setBinaryRetrievableHint(bool retrievable)
+{
+ // glProgramParameteri isn't always available on ES backends.
+ if (mFunctions->programParameteri)
+ {
+ mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
+ retrievable ? GL_TRUE : GL_FALSE);
+ }
+}
+
+LinkResult ProgramGL::link(const gl::ContextState &data, gl::InfoLog &infoLog)
+{
+ preLink();
+
+ if (mState.getAttachedComputeShader())
+ {
+ const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader());
+
+ mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
+
+ // Link and verify
+ mFunctions->linkProgram(mProgramID);
+
+ // Detach the shaders
+ mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
+ }
+ else
+ {
+ // Set the transform feedback state
+ std::vector<const GLchar *> transformFeedbackVaryings;
+ for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
+ {
+ transformFeedbackVaryings.push_back(tfVarying.c_str());
+ }
+
+ if (transformFeedbackVaryings.empty())
+ {
+ if (mFunctions->transformFeedbackVaryings)
+ {
+ mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
+ mState.getTransformFeedbackBufferMode());
+ }
+ }
+ else
+ {
+ ASSERT(mFunctions->transformFeedbackVaryings);
+ mFunctions->transformFeedbackVaryings(
+ mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
+ &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
+ }
+
+ const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
+ const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
+
+ // Attach the shaders
+ mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
+ mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
+
+ // Bind attribute locations to match the GL layer.
+ for (const sh::Attribute &attribute : mState.getAttributes())
+ {
+ if (!attribute.staticUse)
+ {
+ continue;
+ }
+
+ mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
+ }
+
+ // Link and verify
+ mFunctions->linkProgram(mProgramID);
+
+ // Detach the shaders
+ mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
+ mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
+ }
+
+ // Verify the link
+ if (!checkLinkStatus(infoLog))
+ {
+ return false;
+ }
+
+ if (mWorkarounds.alwaysCallUseProgramAfterLink)
+ {
+ mStateManager->forceUseProgram(mProgramID);
+ }
+
+ postLink();
+
+ return true;
+}
+
+GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
+{
+ // TODO(jmadill): implement validate
+ return true;
+}
+
+void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniform1fv(uniLoc(location), count, v);
+}
+
+void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniform2fv(uniLoc(location), count, v);
+}
+
+void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniform3fv(uniLoc(location), count, v);
+}
+
+void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniform4fv(uniLoc(location), count, v);
+}
+
+void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniform1iv(uniLoc(location), count, v);
+
+ const gl::VariableLocation &locationEntry = mState.getUniformLocations()[location];
+
+ size_t samplerIndex = mUniformIndexToSamplerIndex[locationEntry.index];
+ if (samplerIndex != GL_INVALID_INDEX)
+ {
+ std::vector<GLuint> &boundTextureUnits = mSamplerBindings[samplerIndex].boundTextureUnits;
+
+ size_t copyCount =
+ std::min<size_t>(count, boundTextureUnits.size() - locationEntry.element);
+ std::copy(v, v + copyCount, boundTextureUnits.begin() + locationEntry.element);
+ }
+}
+
+void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniform2iv(uniLoc(location), count, v);
+}
+
+void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniform3iv(uniLoc(location), count, v);
+}
+
+void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniform4iv(uniLoc(location), count, v);
+}
+
+void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniform1uiv(uniLoc(location), count, v);
+}
+
+void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniform2uiv(uniLoc(location), count, v);
+}
+
+void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniform3uiv(uniLoc(location), count, v);
+}
+
+void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniform4uiv(uniLoc(location), count, v);
+}
+
+void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
+}
+
+void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
+}
+
+void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
+}
+
+void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
+}
+
+void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
+}
+
+void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
+}
+
+void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
+}
+
+void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
+}
+
+void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ mStateManager->useProgram(mProgramID);
+ mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
+}
+
+void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+{
+ // Lazy init
+ if (mUniformBlockRealLocationMap.empty())
+ {
+ mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
+ for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
+ {
+ const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
+ GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
+ mUniformBlockRealLocationMap.push_back(blockIndex);
+ }
+ }
+
+ GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
+ if (realBlockIndex != GL_INVALID_INDEX)
+ {
+ mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
+ }
+}
+
+GLuint ProgramGL::getProgramID() const
+{
+ return mProgramID;
+}
+
+const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() const
+{
+ return mSamplerBindings;
+}
+
+bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
+{
+ ASSERT(mProgramID != 0u);
+
+ GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
+ if (blockIndex == GL_INVALID_INDEX)
+ {
+ *sizeOut = 0;
+ return false;
+ }
+
+ GLint dataSize = 0;
+ mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
+ &dataSize);
+ *sizeOut = static_cast<size_t>(dataSize);
+ return true;
+}
+
+bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const
+{
+ GLuint uniformIndex;
+ const GLchar *memberNameGLStr = memberUniformName.c_str();
+ mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
+
+ if (uniformIndex == GL_INVALID_INDEX)
+ {
+ *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
+ return false;
+ }
+
+ mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
+ &memberInfoOut->offset);
+ mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
+ &memberInfoOut->arrayStride);
+ mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
+ &memberInfoOut->matrixStride);
+
+ // TODO(jmadill): possibly determine this at the gl::Program level.
+ GLint isRowMajorMatrix = 0;
+ mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
+ &isRowMajorMatrix);
+ memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
+ return true;
+}
+
+void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ ASSERT(mEnablePathRendering);
+
+ for (const auto &input : mPathRenderingFragmentInputs)
+ {
+ if (input.name == inputName)
+ {
+ mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
+ components, coeffs);
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+ return;
+ }
+ }
+
+}
+
+void ProgramGL::preLink()
+{
+ // Reset the program state
+ mUniformRealLocationMap.clear();
+ mUniformBlockRealLocationMap.clear();
+ mSamplerBindings.clear();
+ mUniformIndexToSamplerIndex.clear();
+ mPathRenderingFragmentInputs.clear();
+}
+
+bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
+{
+ GLint linkStatus = GL_FALSE;
+ mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
+ if (linkStatus == GL_FALSE)
+ {
+ // Linking failed, put the error into the info log
+ GLint infoLogLength = 0;
+ mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+ std::string warning;
+
+ // Info log length includes the null terminator, so 1 means that the info log is an empty
+ // string.
+ if (infoLogLength > 1)
+ {
+ std::vector<char> buf(infoLogLength);
+ mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
+
+ mFunctions->deleteProgram(mProgramID);
+ mProgramID = 0;
+
+ infoLog << buf.data();
+
+ warning = FormatString("Program link failed unexpectedly: %s", buf.data());
+ }
+ else
+ {
+ warning = "Program link failed unexpectedly with no info log.";
+ }
+ ANGLEPlatformCurrent()->logWarning(warning.c_str());
+ TRACE("\n%s", warning.c_str());
+
+ // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
+ return false;
+ }
+
+ return true;
+}
+
+void ProgramGL::postLink()
+{
+ // Query the uniform information
+ ASSERT(mUniformRealLocationMap.empty());
+ const auto &uniformLocations = mState.getUniformLocations();
+ const auto &uniforms = mState.getUniforms();
+ mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
+ for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
+ {
+ const auto &entry = uniformLocations[uniformLocation];
+ if (!entry.used)
+ {
+ continue;
+ }
+
+ // From the spec:
+ // "Locations for sequential array indices are not required to be sequential."
+ const gl::LinkedUniform &uniform = uniforms[entry.index];
+ std::stringstream fullNameStr;
+ fullNameStr << uniform.name;
+ if (uniform.isArray())
+ {
+ fullNameStr << "[" << entry.element << "]";
+ }
+ const std::string &fullName = fullNameStr.str();
+
+ GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
+ mUniformRealLocationMap[uniformLocation] = realLocation;
+ }
+
+ mUniformIndexToSamplerIndex.resize(mState.getUniforms().size(), GL_INVALID_INDEX);
+
+ for (size_t uniformId = 0; uniformId < uniforms.size(); ++uniformId)
+ {
+ const gl::LinkedUniform &linkedUniform = uniforms[uniformId];
+
+ if (!linkedUniform.isSampler() || !linkedUniform.staticUse)
+ continue;
+
+ mUniformIndexToSamplerIndex[uniformId] = mSamplerBindings.size();
+
+ // If uniform is a sampler type, insert it into the mSamplerBindings array
+ SamplerBindingGL samplerBinding;
+ samplerBinding.textureType = gl::SamplerTypeToTextureType(linkedUniform.type);
+ samplerBinding.boundTextureUnits.resize(linkedUniform.elementCount(), 0);
+ mSamplerBindings.push_back(samplerBinding);
+ }
+
+ // Discover CHROMIUM_path_rendering fragment inputs if enabled.
+ if (!mEnablePathRendering)
+ return;
+
+ GLint numFragmentInputs = 0;
+ mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
+ &numFragmentInputs);
+ if (numFragmentInputs <= 0)
+ return;
+
+ GLint maxNameLength = 0;
+ mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
+ &maxNameLength);
+ ASSERT(maxNameLength);
+
+ for (GLint i = 0; i < numFragmentInputs; ++i)
+ {
+ std::string name;
+ name.resize(maxNameLength);
+
+ GLsizei nameLen = 0;
+ mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
+ &nameLen, &name[0]);
+ name.resize(nameLen);
+
+ // Ignore built-ins
+ if (angle::BeginsWith(name, "gl_"))
+ continue;
+
+ const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
+ GLint queryResults[ArraySize(kQueryProperties)];
+ GLsizei queryLength = 0;
+
+ mFunctions->getProgramResourceiv(
+ mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
+ kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
+ queryResults);
+
+ ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
+
+ PathRenderingFragmentInput baseElementInput;
+ baseElementInput.name = name;
+ baseElementInput.location = queryResults[0];
+ mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
+
+ // If the input is an array it's denoted by [0] suffix on the variable
+ // name. We'll then create an entry per each array index where index > 0
+ if (angle::EndsWith(name, "[0]"))
+ {
+ // drop the suffix
+ name.resize(name.size() - 3);
+
+ const auto arraySize = queryResults[1];
+ const auto baseLocation = queryResults[0];
+
+ for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
+ {
+ PathRenderingFragmentInput arrayElementInput;
+ arrayElementInput.name = name + "[" + ToString(arrayIndex) + "]";
+ arrayElementInput.location = baseLocation + arrayIndex;
+ mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
+ }
+ }
+ }
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/ProgramGL.h b/gfx/angle/src/libANGLE/renderer/gl/ProgramGL.h
new file mode 100755
index 000000000..88e2245fa
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/ProgramGL.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.
+//
+
+// ProgramGL.h: Defines the class interface for ProgramGL.
+
+#ifndef LIBANGLE_RENDERER_GL_PROGRAMGL_H_
+#define LIBANGLE_RENDERER_GL_PROGRAMGL_H_
+
+#include <string>
+#include <vector>
+
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "libANGLE/renderer/ProgramImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+
+struct SamplerBindingGL
+{
+ GLenum textureType;
+ std::vector<GLuint> boundTextureUnits;
+};
+
+class ProgramGL : public ProgramImpl
+{
+ public:
+ ProgramGL(const gl::ProgramState &data,
+ const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ StateManagerGL *stateManager,
+ bool enablePathRendering);
+ ~ProgramGL() override;
+
+ LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
+ gl::Error save(gl::BinaryOutputStream *stream) override;
+ void setBinaryRetrievableHint(bool retrievable) override;
+
+ LinkResult link(const gl::ContextState &data, gl::InfoLog &infoLog) override;
+ GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
+
+ 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 setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
+
+ bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
+ bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const override;
+
+ void setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs) override;
+
+ GLuint getProgramID() const;
+ const std::vector<SamplerBindingGL> &getAppliedSamplerUniforms() const;
+
+ private:
+ void preLink();
+ bool checkLinkStatus(gl::InfoLog &infoLog);
+ void postLink();
+
+ // Helper function, makes it simpler to type.
+ GLint uniLoc(GLint glLocation) const { return mUniformRealLocationMap[glLocation]; }
+
+ const FunctionsGL *mFunctions;
+ const WorkaroundsGL &mWorkarounds;
+ StateManagerGL *mStateManager;
+
+ std::vector<GLint> mUniformRealLocationMap;
+ std::vector<GLuint> mUniformBlockRealLocationMap;
+
+ // An array of the samplers that are used by the program
+ std::vector<SamplerBindingGL> mSamplerBindings;
+
+ // A map from a mData.getUniforms() index to a mSamplerBindings index.
+ std::vector<size_t> mUniformIndexToSamplerIndex;
+
+ struct PathRenderingFragmentInput
+ {
+ std::string name;
+ GLint location;
+ };
+ std::vector<PathRenderingFragmentInput> mPathRenderingFragmentInputs;
+
+ bool mEnablePathRendering;
+
+ GLuint mProgramID;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_PROGRAMGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/QueryGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/QueryGL.cpp
new file mode 100755
index 000000000..6d9df5d76
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/QueryGL.cpp
@@ -0,0 +1,222 @@
+//
+// 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.
+//
+
+// QueryGL.cpp: Implements the class methods for QueryGL.
+
+#include "libANGLE/renderer/gl/QueryGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+namespace
+{
+
+GLuint64 MergeQueryResults(GLenum type, GLuint64 currentResult, GLuint64 newResult)
+{
+ switch (type)
+ {
+ case GL_ANY_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;
+
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ return currentResult + newResult;
+
+ case GL_TIME_ELAPSED:
+ return currentResult + newResult;
+
+ case GL_TIMESTAMP:
+ return newResult;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+} // anonymous namespace
+
+namespace rx
+{
+
+QueryGL::QueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager)
+ : QueryImpl(type),
+ mType(type),
+ mFunctions(functions),
+ mStateManager(stateManager),
+ mActiveQuery(0),
+ mPendingQueries(),
+ mResultSum(0)
+{
+}
+
+QueryGL::~QueryGL()
+{
+ mStateManager->deleteQuery(mActiveQuery);
+ mStateManager->onDeleteQueryObject(this);
+ while (!mPendingQueries.empty())
+ {
+ mStateManager->deleteQuery(mPendingQueries.front());
+ mPendingQueries.pop_front();
+ }
+}
+
+gl::Error QueryGL::begin()
+{
+ mResultSum = 0;
+ mStateManager->onBeginQuery(this);
+ return resume();
+}
+
+gl::Error QueryGL::end()
+{
+ return pause();
+}
+
+gl::Error QueryGL::queryCounter()
+{
+ ASSERT(mType == GL_TIMESTAMP);
+
+ // Directly create a query for the timestamp and add it to the pending query queue, as timestamp
+ // queries do not have the traditional begin/end block and never need to be paused/resumed
+ GLuint query;
+ mFunctions->genQueries(1, &query);
+ mFunctions->queryCounter(query, GL_TIMESTAMP);
+ mPendingQueries.push_back(query);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+template <typename T>
+gl::Error QueryGL::getResultBase(T *params)
+{
+ ASSERT(mActiveQuery == 0);
+
+ gl::Error error = flush(true);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(mPendingQueries.empty());
+ *params = static_cast<T>(mResultSum);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error QueryGL::getResult(GLint *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error QueryGL::getResult(GLuint *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error QueryGL::getResult(GLint64 *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error QueryGL::getResult(GLuint64 *params)
+{
+ return getResultBase(params);
+}
+
+gl::Error QueryGL::isResultAvailable(bool *available)
+{
+ ASSERT(mActiveQuery == 0);
+
+ gl::Error error = flush(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *available = mPendingQueries.empty();
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error QueryGL::pause()
+{
+ if (mActiveQuery != 0)
+ {
+ mStateManager->endQuery(mType, mActiveQuery);
+
+ mPendingQueries.push_back(mActiveQuery);
+ mActiveQuery = 0;
+ }
+
+ // Flush to make sure the pending queries don't add up too much.
+ gl::Error error = flush(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error QueryGL::resume()
+{
+ if (mActiveQuery == 0)
+ {
+ // Flush to make sure the pending queries don't add up too much.
+ gl::Error error = flush(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mFunctions->genQueries(1, &mActiveQuery);
+ mStateManager->beginQuery(mType, mActiveQuery);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error QueryGL::flush(bool force)
+{
+ while (!mPendingQueries.empty())
+ {
+ GLuint id = mPendingQueries.front();
+ if (!force)
+ {
+ GLuint resultAvailable = 0;
+ mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &resultAvailable);
+ if (resultAvailable == GL_FALSE)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+ }
+
+ // Even though getQueryObjectui64v was introduced for timer queries, there is nothing in the
+ // standard that says that it doesn't work for any other queries. It also passes on all the
+ // trybots, so we use it if it is available
+ if (mFunctions->getQueryObjectui64v != nullptr)
+ {
+ GLuint64 result = 0;
+ mFunctions->getQueryObjectui64v(id, GL_QUERY_RESULT, &result);
+ mResultSum = MergeQueryResults(mType, mResultSum, result);
+ }
+ else
+ {
+ GLuint result = 0;
+ mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT, &result);
+ mResultSum = MergeQueryResults(mType, mResultSum, static_cast<GLuint64>(result));
+ }
+
+ mStateManager->deleteQuery(id);
+
+ mPendingQueries.pop_front();
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/QueryGL.h b/gfx/angle/src/libANGLE/renderer/gl/QueryGL.h
new file mode 100755
index 000000000..5e280b1f7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/QueryGL.h
@@ -0,0 +1,64 @@
+//
+// 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.
+//
+
+// QueryGL.h: Defines the class interface for QueryGL.
+
+#ifndef LIBANGLE_RENDERER_GL_QUERYGL_H_
+#define LIBANGLE_RENDERER_GL_QUERYGL_H_
+
+#include <deque>
+
+#include "libANGLE/renderer/QueryImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+
+class QueryGL : public QueryImpl
+{
+ public:
+ QueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager);
+ ~QueryGL() override;
+
+ gl::Error begin() override;
+ gl::Error end() override;
+ gl::Error queryCounter() override;
+ gl::Error getResult(GLint *params) override;
+ gl::Error getResult(GLuint *params) override;
+ gl::Error getResult(GLint64 *params) override;
+ gl::Error getResult(GLuint64 *params) override;
+ gl::Error isResultAvailable(bool *available) override;
+
+ // OpenGL is only allowed to have one query of each type active at any given time. Since ANGLE
+ // virtualizes contexts, queries need to be able to be paused and resumed.
+ // A query is "paused" by ending it and pushing the ID into a list of queries awaiting readback.
+ // When it is "resumed", a new query is generated and started.
+ // When a result is required, the queries are "flushed" by iterating over the list of pending
+ // queries and merging their results.
+ gl::Error pause();
+ gl::Error resume();
+
+ private:
+ gl::Error flush(bool force);
+
+ template <typename T>
+ gl::Error getResultBase(T *params);
+
+ GLenum mType;
+
+ const FunctionsGL *mFunctions;
+ StateManagerGL *mStateManager;
+
+ GLuint mActiveQuery;
+ std::deque<GLuint> mPendingQueries;
+ GLuint64 mResultSum;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_QUERYGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.cpp
new file mode 100755
index 000000000..bfc2bb254
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.cpp
@@ -0,0 +1,96 @@
+//
+// 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.
+//
+
+// RenderbufferGL.cpp: Implements the class methods for RenderbufferGL.
+
+#include "libANGLE/renderer/gl/RenderbufferGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/formatutilsgl.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+namespace rx
+{
+RenderbufferGL::RenderbufferGL(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ StateManagerGL *stateManager,
+ const gl::TextureCapsMap &textureCaps)
+ : RenderbufferImpl(),
+ mFunctions(functions),
+ mWorkarounds(workarounds),
+ mStateManager(stateManager),
+ mTextureCaps(textureCaps),
+ mRenderbufferID(0)
+{
+ mFunctions->genRenderbuffers(1, &mRenderbufferID);
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID);
+}
+
+RenderbufferGL::~RenderbufferGL()
+{
+ mStateManager->deleteRenderbuffer(mRenderbufferID);
+ mRenderbufferID = 0;
+}
+
+gl::Error RenderbufferGL::setStorage(GLenum internalformat, size_t width, size_t height)
+{
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID);
+
+ nativegl::RenderbufferFormat renderbufferFormat =
+ nativegl::GetRenderbufferFormat(mFunctions, mWorkarounds, internalformat);
+ mFunctions->renderbufferStorage(GL_RENDERBUFFER, renderbufferFormat.internalFormat,
+ static_cast<GLsizei>(width), static_cast<GLsizei>(height));
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RenderbufferGL::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
+{
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID);
+
+ nativegl::RenderbufferFormat renderbufferFormat =
+ nativegl::GetRenderbufferFormat(mFunctions, mWorkarounds, internalformat);
+ mFunctions->renderbufferStorageMultisample(
+ GL_RENDERBUFFER, static_cast<GLsizei>(samples), renderbufferFormat.internalFormat,
+ static_cast<GLsizei>(width), static_cast<GLsizei>(height));
+
+ const gl::TextureCaps &formatCaps = mTextureCaps.get(internalformat);
+ if (samples > formatCaps.getMaxSamples())
+ {
+ // Before version 4.2, it is unknown if the specific internal format can support the requested number
+ // of samples. It is expected that GL_OUT_OF_MEMORY is returned if the renderbuffer cannot be created.
+ GLenum error = GL_NO_ERROR;
+ do
+ {
+ error = mFunctions->getError();
+ if (error == GL_OUT_OF_MEMORY)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY);
+ }
+
+ ASSERT(error == GL_NO_ERROR);
+ } while (error != GL_NO_ERROR);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RenderbufferGL::setStorageEGLImageTarget(egl::Image *image)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+GLuint RenderbufferGL::getRenderbufferID() const
+{
+ return mRenderbufferID;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.h b/gfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.h
new file mode 100755
index 000000000..0ff0faeae
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/RenderbufferGL.h
@@ -0,0 +1,52 @@
+//
+// 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.
+//
+
+// RenderbufferGL.h: Defines the class interface for RenderbufferGL.
+
+#ifndef LIBANGLE_RENDERER_GL_RENDERBUFFERGL_H_
+#define LIBANGLE_RENDERER_GL_RENDERBUFFERGL_H_
+
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace gl
+{
+class TextureCapsMap;
+}
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class RenderbufferGL : public RenderbufferImpl
+{
+ public:
+ RenderbufferGL(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ StateManagerGL *stateManager,
+ const gl::TextureCapsMap &textureCaps);
+ ~RenderbufferGL() override;
+
+ virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override;
+ virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) override;
+ virtual gl::Error setStorageEGLImageTarget(egl::Image *image) override;
+
+ GLuint getRenderbufferID() const;
+
+ private:
+ const FunctionsGL *mFunctions;
+ const WorkaroundsGL &mWorkarounds;
+ StateManagerGL *mStateManager;
+ const gl::TextureCapsMap &mTextureCaps;
+
+ GLuint mRenderbufferID;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_RENDERBUFFERGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/RendererGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/RendererGL.cpp
new file mode 100755
index 000000000..da1a65687
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/RendererGL.cpp
@@ -0,0 +1,561 @@
+//
+// 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.
+//
+
+// RendererGL.cpp: Implements the class methods for RendererGL.
+
+#include "libANGLE/renderer/gl/RendererGL.h"
+
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/Path.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/BlitGL.h"
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/CompilerGL.h"
+#include "libANGLE/renderer/gl/ContextGL.h"
+#include "libANGLE/renderer/gl/FenceNVGL.h"
+#include "libANGLE/renderer/gl/FenceSyncGL.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/PathGL.h"
+#include "libANGLE/renderer/gl/ProgramGL.h"
+#include "libANGLE/renderer/gl/QueryGL.h"
+#include "libANGLE/renderer/gl/RenderbufferGL.h"
+#include "libANGLE/renderer/gl/SamplerGL.h"
+#include "libANGLE/renderer/gl/ShaderGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
+#include "libANGLE/renderer/gl/VertexArrayGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+namespace
+{
+
+std::vector<GLuint> GatherPaths(const std::vector<gl::Path *> &paths)
+{
+ std::vector<GLuint> ret;
+ ret.reserve(paths.size());
+
+ for (const auto *p : paths)
+ {
+ const auto *pathObj = rx::GetImplAs<rx::PathGL>(p);
+ ret.push_back(pathObj->getPathID());
+ }
+ return ret;
+}
+
+} // namespace
+
+#ifndef NDEBUG
+static void INTERNAL_GL_APIENTRY LogGLDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
+ const GLchar *message, const void *userParam)
+{
+ std::string sourceText;
+ switch (source)
+ {
+ case GL_DEBUG_SOURCE_API: sourceText = "OpenGL"; break;
+ case GL_DEBUG_SOURCE_WINDOW_SYSTEM: sourceText = "Windows"; break;
+ case GL_DEBUG_SOURCE_SHADER_COMPILER: sourceText = "Shader Compiler"; break;
+ case GL_DEBUG_SOURCE_THIRD_PARTY: sourceText = "Third Party"; break;
+ case GL_DEBUG_SOURCE_APPLICATION: sourceText = "Application"; break;
+ case GL_DEBUG_SOURCE_OTHER: sourceText = "Other"; break;
+ default: sourceText = "UNKNOWN"; break;
+ }
+
+ std::string typeText;
+ switch (type)
+ {
+ case GL_DEBUG_TYPE_ERROR: typeText = "Error"; break;
+ case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: typeText = "Deprecated behavior"; break;
+ case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: typeText = "Undefined behavior"; break;
+ case GL_DEBUG_TYPE_PORTABILITY: typeText = "Portability"; break;
+ case GL_DEBUG_TYPE_PERFORMANCE: typeText = "Performance"; break;
+ case GL_DEBUG_TYPE_OTHER: typeText = "Other"; break;
+ case GL_DEBUG_TYPE_MARKER: typeText = "Marker"; break;
+ default: typeText = "UNKNOWN"; break;
+ }
+
+ std::string severityText;
+ switch (severity)
+ {
+ case GL_DEBUG_SEVERITY_HIGH: severityText = "High"; break;
+ case GL_DEBUG_SEVERITY_MEDIUM: severityText = "Medium"; break;
+ case GL_DEBUG_SEVERITY_LOW: severityText = "Low"; break;
+ case GL_DEBUG_SEVERITY_NOTIFICATION: severityText = "Notification"; break;
+ default: severityText = "UNKNOWN"; break;
+ }
+
+ ERR("\n\tSource: %s\n\tType: %s\n\tID: %d\n\tSeverity: %s\n\tMessage: %s", sourceText.c_str(), typeText.c_str(), id,
+ severityText.c_str(), message);
+}
+#endif
+
+namespace rx
+{
+
+RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &attribMap)
+ : mMaxSupportedESVersion(0, 0),
+ mFunctions(functions),
+ mStateManager(nullptr),
+ mBlitter(nullptr),
+ mHasDebugOutput(false),
+ mSkipDrawCalls(false),
+ mCapsInitialized(false)
+{
+ ASSERT(mFunctions);
+ mStateManager = new StateManagerGL(mFunctions, getNativeCaps());
+ nativegl_gl::GenerateWorkarounds(mFunctions, &mWorkarounds);
+ mBlitter = new BlitGL(functions, mWorkarounds, mStateManager);
+
+ mHasDebugOutput = mFunctions->isAtLeastGL(gl::Version(4, 3)) ||
+ mFunctions->hasGLExtension("GL_KHR_debug") ||
+ mFunctions->isAtLeastGLES(gl::Version(3, 2)) ||
+ mFunctions->hasGLESExtension("GL_KHR_debug");
+#ifndef NDEBUG
+ if (mHasDebugOutput)
+ {
+ mFunctions->enable(GL_DEBUG_OUTPUT);
+ mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr, GL_TRUE);
+ mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr, GL_TRUE);
+ mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0, nullptr, GL_FALSE);
+ mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr, GL_FALSE);
+ mFunctions->debugMessageCallback(&LogGLDebugMessage, nullptr);
+ }
+#endif
+
+ EGLint deviceType =
+ static_cast<EGLint>(attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_NONE));
+ if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
+ {
+ mSkipDrawCalls = true;
+ }
+
+ if (mWorkarounds.initializeCurrentVertexAttributes)
+ {
+ GLint maxVertexAttribs = 0;
+ mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
+
+ for (GLint i = 0; i < maxVertexAttribs; ++i)
+ {
+ mFunctions->vertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ }
+}
+
+RendererGL::~RendererGL()
+{
+ SafeDelete(mBlitter);
+ SafeDelete(mStateManager);
+}
+
+gl::Error RendererGL::flush()
+{
+ mFunctions->flush();
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RendererGL::finish()
+{
+#ifdef NDEBUG
+ if (mWorkarounds.finishDoesNotCauseQueriesToBeAvailable && mHasDebugOutput)
+ {
+ mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ }
+#endif
+
+ mFunctions->finish();
+
+#ifdef NDEBUG
+ if (mWorkarounds.finishDoesNotCauseQueriesToBeAvailable && mHasDebugOutput)
+ {
+ mFunctions->disable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ }
+#endif
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RendererGL::drawArrays(const gl::ContextState &data,
+ GLenum mode,
+ GLint first,
+ GLsizei count)
+{
+ ANGLE_TRY(mStateManager->setDrawArraysState(data, first, count, 0));
+
+ if (!mSkipDrawCalls)
+ {
+ mFunctions->drawArrays(mode, first, count);
+ }
+
+ return gl::NoError();
+}
+
+gl::Error RendererGL::drawArraysInstanced(const gl::ContextState &data,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ ANGLE_TRY(mStateManager->setDrawArraysState(data, first, count, instanceCount));
+
+ if (!mSkipDrawCalls)
+ {
+ mFunctions->drawArraysInstanced(mode, first, count, instanceCount);
+ }
+
+ return gl::NoError();
+}
+
+gl::Error RendererGL::drawElements(const gl::ContextState &data,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange)
+{
+ const GLvoid *drawIndexPtr = nullptr;
+ ANGLE_TRY(mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPtr));
+
+ if (!mSkipDrawCalls)
+ {
+ mFunctions->drawElements(mode, count, type, drawIndexPtr);
+ }
+
+ return gl::NoError();
+}
+
+gl::Error RendererGL::drawElementsInstanced(const gl::ContextState &data,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange)
+{
+ const GLvoid *drawIndexPointer = nullptr;
+ ANGLE_TRY(mStateManager->setDrawElementsState(data, count, type, indices, instances,
+ &drawIndexPointer));
+
+ if (!mSkipDrawCalls)
+ {
+ mFunctions->drawElementsInstanced(mode, count, type, drawIndexPointer, instances);
+ }
+
+ return gl::NoError();
+}
+
+gl::Error RendererGL::drawRangeElements(const gl::ContextState &data,
+ GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange)
+{
+ const GLvoid *drawIndexPointer = nullptr;
+ ANGLE_TRY(
+ mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPointer));
+
+ if (!mSkipDrawCalls)
+ {
+ mFunctions->drawRangeElements(mode, start, end, count, type, drawIndexPointer);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void RendererGL::stencilFillPath(const gl::ContextState &state,
+ const gl::Path *path,
+ GLenum fillMode,
+ GLuint mask)
+{
+ const auto *pathObj = GetImplAs<PathGL>(path);
+
+ mFunctions->stencilFillPathNV(pathObj->getPathID(), fillMode, mask);
+
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::stencilStrokePath(const gl::ContextState &state,
+ const gl::Path *path,
+ GLint reference,
+ GLuint mask)
+{
+ const auto *pathObj = GetImplAs<PathGL>(path);
+
+ mFunctions->stencilStrokePathNV(pathObj->getPathID(), reference, mask);
+
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::coverFillPath(const gl::ContextState &state,
+ const gl::Path *path,
+ GLenum coverMode)
+{
+
+ const auto *pathObj = GetImplAs<PathGL>(path);
+ mFunctions->coverFillPathNV(pathObj->getPathID(), coverMode);
+
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::coverStrokePath(const gl::ContextState &state,
+ const gl::Path *path,
+ GLenum coverMode)
+{
+ const auto *pathObj = GetImplAs<PathGL>(path);
+ mFunctions->coverStrokePathNV(pathObj->getPathID(), coverMode);
+
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::stencilThenCoverFillPath(const gl::ContextState &state,
+ const gl::Path *path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode)
+{
+
+ const auto *pathObj = GetImplAs<PathGL>(path);
+ mFunctions->stencilThenCoverFillPathNV(pathObj->getPathID(), fillMode, mask, coverMode);
+
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::stencilThenCoverStrokePath(const gl::ContextState &state,
+ const gl::Path *path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode)
+{
+
+ const auto *pathObj = GetImplAs<PathGL>(path);
+ mFunctions->stencilThenCoverStrokePathNV(pathObj->getPathID(), reference, mask, coverMode);
+
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::coverFillPathInstanced(const gl::ContextState &state,
+ const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjs = GatherPaths(paths);
+
+ mFunctions->coverFillPathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
+ &pathObjs[0], 0, coverMode, transformType,
+ transformValues);
+
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+void RendererGL::coverStrokePathInstanced(const gl::ContextState &state,
+ const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjs = GatherPaths(paths);
+
+ mFunctions->coverStrokePathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
+ &pathObjs[0], 0, coverMode, transformType,
+ transformValues);
+
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+void RendererGL::stencilFillPathInstanced(const gl::ContextState &state,
+ const std::vector<gl::Path *> &paths,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjs = GatherPaths(paths);
+
+ mFunctions->stencilFillPathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
+ &pathObjs[0], 0, fillMode, mask, transformType,
+ transformValues);
+
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+void RendererGL::stencilStrokePathInstanced(const gl::ContextState &state,
+ const std::vector<gl::Path *> &paths,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjs = GatherPaths(paths);
+
+ mFunctions->stencilStrokePathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
+ &pathObjs[0], 0, reference, mask, transformType,
+ transformValues);
+
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+void RendererGL::stencilThenCoverFillPathInstanced(const gl::ContextState &state,
+ const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjs = GatherPaths(paths);
+
+ mFunctions->stencilThenCoverFillPathInstancedNV(
+ static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, &pathObjs[0], 0, fillMode, mask,
+ coverMode, transformType, transformValues);
+
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+void RendererGL::stencilThenCoverStrokePathInstanced(const gl::ContextState &state,
+ const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjs = GatherPaths(paths);
+
+ mFunctions->stencilThenCoverStrokePathInstancedNV(
+ static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, &pathObjs[0], 0, reference, mask,
+ coverMode, transformType, transformValues);
+
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+}
+
+GLenum RendererGL::getResetStatus()
+{
+ return mFunctions->getGraphicsResetStatus();
+}
+
+ContextImpl *RendererGL::createContext(const gl::ContextState &state)
+{
+ return new ContextGL(state, this);
+}
+
+void RendererGL::insertEventMarker(GLsizei length, const char *marker)
+{
+ mFunctions->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0,
+ GL_DEBUG_SEVERITY_NOTIFICATION, length, marker);
+}
+
+void RendererGL::pushGroupMarker(GLsizei length, const char *marker)
+{
+ mFunctions->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, length, marker);
+}
+
+void RendererGL::popGroupMarker()
+{
+ mFunctions->popDebugGroup();
+}
+
+std::string RendererGL::getVendorString() const
+{
+ return std::string(reinterpret_cast<const char*>(mFunctions->getString(GL_VENDOR)));
+}
+
+std::string RendererGL::getRendererDescription() const
+{
+ std::string nativeVendorString(reinterpret_cast<const char*>(mFunctions->getString(GL_VENDOR)));
+ std::string nativeRendererString(reinterpret_cast<const char*>(mFunctions->getString(GL_RENDERER)));
+
+ std::ostringstream rendererString;
+ rendererString << nativeVendorString << " " << nativeRendererString << " OpenGL";
+ if (mFunctions->standard == STANDARD_GL_ES)
+ {
+ rendererString << " ES";
+ }
+ rendererString << " " << mFunctions->version.major << "." << mFunctions->version.minor;
+ if (mFunctions->standard == STANDARD_GL_DESKTOP)
+ {
+ // Some drivers (NVIDIA) use a profile mask of 0 when in compatibility profile.
+ if ((mFunctions->profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0 ||
+ (mFunctions->isAtLeastGL(gl::Version(3, 2)) && mFunctions->profile == 0))
+ {
+ rendererString << " compatibility";
+ }
+ else if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
+ {
+ rendererString << " core";
+ }
+ }
+
+ return rendererString.str();
+}
+
+const gl::Version &RendererGL::getMaxSupportedESVersion() const
+{
+ // Force generation of caps
+ getNativeCaps();
+
+ return mMaxSupportedESVersion;
+}
+
+void RendererGL::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations * /* outLimitations */) const
+{
+ nativegl_gl::GenerateCaps(mFunctions, outCaps, outTextureCaps, outExtensions, &mMaxSupportedESVersion);
+}
+
+GLint RendererGL::getGPUDisjoint()
+{
+ // TODO(ewell): On GLES backends we should find a way to reliably query disjoint events
+ return 0;
+}
+
+GLint64 RendererGL::getTimestamp()
+{
+ GLint64 result = 0;
+ mFunctions->getInteger64v(GL_TIMESTAMP, &result);
+ return result;
+}
+
+void RendererGL::ensureCapsInitialized() const
+{
+ if (!mCapsInitialized)
+ {
+ generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
+ mCapsInitialized = true;
+ }
+}
+
+const gl::Caps &RendererGL::getNativeCaps() const
+{
+ ensureCapsInitialized();
+ return mNativeCaps;
+}
+
+const gl::TextureCapsMap &RendererGL::getNativeTextureCaps() const
+{
+ ensureCapsInitialized();
+ return mNativeTextureCaps;
+}
+
+const gl::Extensions &RendererGL::getNativeExtensions() const
+{
+ ensureCapsInitialized();
+ return mNativeExtensions;
+}
+
+const gl::Limitations &RendererGL::getNativeLimitations() const
+{
+ ensureCapsInitialized();
+ return mNativeLimitations;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/RendererGL.h b/gfx/angle/src/libANGLE/renderer/gl/RendererGL.h
new file mode 100755
index 000000000..71f012055
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/RendererGL.h
@@ -0,0 +1,194 @@
+//
+// 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.
+//
+
+// RendererGL.h: Defines the class interface for RendererGL.
+
+#ifndef LIBANGLE_RENDERER_GL_RENDERERGL_H_
+#define LIBANGLE_RENDERER_GL_RENDERERGL_H_
+
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+
+namespace gl
+{
+class ContextState;
+struct IndexRange;
+class Path;
+}
+
+namespace egl
+{
+class AttributeMap;
+}
+
+namespace sh
+{
+struct BlockMemberInfo;
+}
+
+namespace rx
+{
+class BlitGL;
+class ContextImpl;
+class FunctionsGL;
+class StateManagerGL;
+
+class RendererGL : angle::NonCopyable
+{
+ public:
+ RendererGL(const FunctionsGL *functions, const egl::AttributeMap &attribMap);
+ ~RendererGL();
+
+ ContextImpl *createContext(const gl::ContextState &state);
+
+ gl::Error flush();
+ gl::Error finish();
+
+ gl::Error drawArrays(const gl::ContextState &data, GLenum mode, GLint first, GLsizei count);
+ gl::Error drawArraysInstanced(const gl::ContextState &data,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount);
+
+ gl::Error drawElements(const gl::ContextState &data,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange);
+ gl::Error drawElementsInstanced(const gl::ContextState &data,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange);
+ gl::Error drawRangeElements(const gl::ContextState &data,
+ GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange);
+
+ // CHROMIUM_path_rendering implementation
+ void stencilFillPath(const gl::ContextState &state,
+ const gl::Path *path,
+ GLenum fillMode,
+ GLuint mask);
+ void stencilStrokePath(const gl::ContextState &state,
+ const gl::Path *path,
+ GLint reference,
+ GLuint mask);
+ void coverFillPath(const gl::ContextState &state, const gl::Path *path, GLenum coverMode);
+ void coverStrokePath(const gl::ContextState &state, const gl::Path *path, GLenum coverMode);
+ void stencilThenCoverFillPath(const gl::ContextState &state,
+ const gl::Path *path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode);
+ void stencilThenCoverStrokePath(const gl::ContextState &state,
+ const gl::Path *path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode);
+ void coverFillPathInstanced(const gl::ContextState &state,
+ const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void coverStrokePathInstanced(const gl::ContextState &state,
+ const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void stencilFillPathInstanced(const gl::ContextState &state,
+ const std::vector<gl::Path *> &paths,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void stencilStrokePathInstanced(const gl::ContextState &state,
+ const std::vector<gl::Path *> &paths,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+
+ void stencilThenCoverFillPathInstanced(const gl::ContextState &state,
+ const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void stencilThenCoverStrokePathInstanced(const gl::ContextState &state,
+ const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+
+ GLenum getResetStatus();
+
+ // EXT_debug_marker
+ void insertEventMarker(GLsizei length, const char *marker);
+ void pushGroupMarker(GLsizei length, const char *marker);
+ void popGroupMarker();
+
+ std::string getVendorString() const;
+ std::string getRendererDescription() const;
+
+ GLint getGPUDisjoint();
+ GLint64 getTimestamp();
+
+ const gl::Version &getMaxSupportedESVersion() const;
+ const FunctionsGL *getFunctions() const { return mFunctions; }
+ StateManagerGL *getStateManager() const { return mStateManager; }
+ const WorkaroundsGL &getWorkarounds() const { return mWorkarounds; }
+ BlitGL *getBlitter() const { return mBlitter; }
+
+ const gl::Caps &getNativeCaps() const;
+ const gl::TextureCapsMap &getNativeTextureCaps() const;
+ const gl::Extensions &getNativeExtensions() const;
+ const gl::Limitations &getNativeLimitations() const;
+
+ private:
+ void ensureCapsInitialized() const;
+ void generateCaps(gl::Caps *outCaps,
+ gl::TextureCapsMap *outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations *outLimitations) const;
+
+ mutable gl::Version mMaxSupportedESVersion;
+
+ const FunctionsGL *mFunctions;
+ StateManagerGL *mStateManager;
+
+ BlitGL *mBlitter;
+
+ WorkaroundsGL mWorkarounds;
+
+ bool mHasDebugOutput;
+
+ // For performance debugging
+ bool mSkipDrawCalls;
+
+ mutable bool mCapsInitialized;
+ mutable gl::Caps mNativeCaps;
+ mutable gl::TextureCapsMap mNativeTextureCaps;
+ mutable gl::Extensions mNativeExtensions;
+ mutable gl::Limitations mNativeLimitations;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_RENDERERGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/SamplerGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/SamplerGL.cpp
new file mode 100755
index 000000000..2a6d81583
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/SamplerGL.cpp
@@ -0,0 +1,73 @@
+//
+// 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.
+//
+
+// SamplerGL.cpp: Defines the rx::SamplerGL class, an implementation of SamplerImpl.
+
+#include "libANGLE/renderer/gl/SamplerGL.h"
+
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+namespace
+{
+
+template <typename T>
+static inline void SyncSamplerStateMember(const rx::FunctionsGL *functions,
+ GLuint sampler,
+ const gl::SamplerState &newState,
+ gl::SamplerState &curState,
+ GLenum name,
+ T(gl::SamplerState::*samplerMember))
+{
+ if (curState.*samplerMember != newState.*samplerMember)
+ {
+ curState.*samplerMember = newState.*samplerMember;
+ functions->samplerParameterf(sampler, name, static_cast<GLfloat>(curState.*samplerMember));
+ }
+}
+}
+
+namespace rx
+{
+
+SamplerGL::SamplerGL(const FunctionsGL *functions, StateManagerGL *stateManager)
+ : SamplerImpl(),
+ mFunctions(functions),
+ mStateManager(stateManager),
+ mAppliedSamplerState(),
+ mSamplerID(0)
+{
+ mFunctions->genSamplers(1, &mSamplerID);
+}
+
+SamplerGL::~SamplerGL()
+{
+ mStateManager->deleteSampler(mSamplerID);
+ mSamplerID = 0;
+}
+
+void SamplerGL::syncState(const gl::SamplerState &samplerState) const
+{
+ // clang-format off
+ SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MIN_FILTER, &gl::SamplerState::minFilter);
+ SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAG_FILTER, &gl::SamplerState::magFilter);
+ SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_WRAP_S, &gl::SamplerState::wrapS);
+ SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_WRAP_T, &gl::SamplerState::wrapT);
+ SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_WRAP_R, &gl::SamplerState::wrapR);
+ SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAX_ANISOTROPY_EXT, &gl::SamplerState::maxAnisotropy);
+ SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MIN_LOD, &gl::SamplerState::minLod);
+ SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAX_LOD, &gl::SamplerState::maxLod);
+ SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode);
+ SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc);
+ SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_SRGB_DECODE_EXT, &gl::SamplerState::sRGBDecode);
+ // clang-format on
+}
+
+GLuint SamplerGL::getSamplerID() const
+{
+ return mSamplerID;
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/SamplerGL.h b/gfx/angle/src/libANGLE/renderer/gl/SamplerGL.h
new file mode 100755
index 000000000..c3fcfde80
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/SamplerGL.h
@@ -0,0 +1,40 @@
+//
+// 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.
+//
+
+// SamplerGL.h: Defines the rx::SamplerGL class, an implementation of SamplerImpl.
+
+#ifndef LIBANGLE_RENDERER_GL_SAMPLERGL_H_
+#define LIBANGLE_RENDERER_GL_SAMPLERGL_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/SamplerImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+
+class SamplerGL : public SamplerImpl
+{
+ public:
+ SamplerGL(const FunctionsGL *functions, StateManagerGL *stateManager);
+ ~SamplerGL() override;
+
+ void syncState(const gl::SamplerState &samplerState) const;
+
+ GLuint getSamplerID() const;
+
+ private:
+ const FunctionsGL *mFunctions;
+ StateManagerGL *mStateManager;
+
+ mutable gl::SamplerState mAppliedSamplerState;
+ GLuint mSamplerID;
+};
+}
+
+#endif // LIBANGLE_RENDERER_GL_SAMPLERGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/ShaderGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/ShaderGL.cpp
new file mode 100755
index 000000000..c9145b00a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/ShaderGL.cpp
@@ -0,0 +1,143 @@
+//
+// 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.
+//
+
+// ShaderGL.cpp: Implements the class methods for ShaderGL.
+
+#include "libANGLE/renderer/gl/ShaderGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+
+#include <iostream>
+
+namespace rx
+{
+
+ShaderGL::ShaderGL(const gl::ShaderState &data,
+ const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds)
+ : ShaderImpl(data), mFunctions(functions), mWorkarounds(workarounds), mShaderID(0)
+{
+ ASSERT(mFunctions);
+}
+
+ShaderGL::~ShaderGL()
+{
+ if (mShaderID != 0)
+ {
+ mFunctions->deleteShader(mShaderID);
+ mShaderID = 0;
+ }
+}
+
+ShCompileOptions ShaderGL::prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string * /*sourcePath*/)
+{
+ // Reset the previous state
+ if (mShaderID != 0)
+ {
+ mFunctions->deleteShader(mShaderID);
+ mShaderID = 0;
+ }
+
+ *sourceStream << mData.getSource();
+
+ ShCompileOptions options = SH_INIT_GL_POSITION;
+
+ if (mWorkarounds.doWhileGLSLCausesGPUHang)
+ {
+ options |= SH_REWRITE_DO_WHILE_LOOPS;
+ }
+
+ if (mWorkarounds.emulateAbsIntFunction)
+ {
+ options |= SH_EMULATE_ABS_INT_FUNCTION;
+ }
+
+ if (mWorkarounds.addAndTrueToLoopCondition)
+ {
+ options |= SH_ADD_AND_TRUE_TO_LOOP_CONDITION;
+ }
+
+ if (mWorkarounds.emulateIsnanFloat)
+ {
+ options |= SH_EMULATE_ISNAN_FLOAT_FUNCTION;
+ }
+
+ if (mWorkarounds.useUnusedBlocksWithStandardOrSharedLayout)
+ {
+ options |= SH_USE_UNUSED_STANDARD_SHARED_BLOCKS;
+ }
+
+ if (mWorkarounds.dontRemoveInvariantForFragmentInput)
+ {
+ options |= SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT;
+ }
+
+ if (mWorkarounds.removeInvariantAndCentroidForESSL3)
+ {
+ options |= SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3;
+ }
+
+ return options;
+}
+
+bool ShaderGL::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
+{
+ // Translate the ESSL into GLSL
+ const char *translatedSourceCString = mData.getTranslatedSource().c_str();
+
+ // Generate a shader object and set the source
+ mShaderID = mFunctions->createShader(mData.getShaderType());
+ mFunctions->shaderSource(mShaderID, 1, &translatedSourceCString, nullptr);
+ mFunctions->compileShader(mShaderID);
+
+ // Check for compile errors from the native driver
+ GLint compileStatus = GL_FALSE;
+ mFunctions->getShaderiv(mShaderID, GL_COMPILE_STATUS, &compileStatus);
+ if (compileStatus == GL_FALSE)
+ {
+ // Compilation failed, put the error into the info log
+ GLint infoLogLength = 0;
+ mFunctions->getShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+ // Info log length includes the null terminator, so 1 means that the info log is an empty
+ // string.
+ if (infoLogLength > 1)
+ {
+ std::vector<char> buf(infoLogLength);
+ mFunctions->getShaderInfoLog(mShaderID, infoLogLength, nullptr, &buf[0]);
+
+ mFunctions->deleteShader(mShaderID);
+ mShaderID = 0;
+
+ *infoLog = &buf[0];
+ TRACE("\n%s", infoLog->c_str());
+ }
+ else
+ {
+ TRACE("\nShader compilation failed with no info log.");
+ }
+ return false;
+ }
+
+ return true;
+}
+
+std::string ShaderGL::getDebugInfo() const
+{
+ return std::string();
+}
+
+GLuint ShaderGL::getShaderID() const
+{
+ return mShaderID;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/ShaderGL.h b/gfx/angle/src/libANGLE/renderer/gl/ShaderGL.h
new file mode 100755
index 000000000..0ecd89ce6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/ShaderGL.h
@@ -0,0 +1,44 @@
+//
+// 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.
+//
+
+// ShaderGL.h: Defines the class interface for ShaderGL.
+
+#ifndef LIBANGLE_RENDERER_GL_SHADERGL_H_
+#define LIBANGLE_RENDERER_GL_SHADERGL_H_
+
+#include "libANGLE/renderer/ShaderImpl.h"
+
+namespace rx
+{
+class FunctionsGL;
+struct WorkaroundsGL;
+
+class ShaderGL : public ShaderImpl
+{
+ public:
+ ShaderGL(const gl::ShaderState &data,
+ const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds);
+ ~ShaderGL() override;
+
+ // ShaderImpl implementation
+ ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string *sourcePath) override;
+ bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override;
+ std::string getDebugInfo() const override;
+
+ GLuint getShaderID() const;
+
+ private:
+ const FunctionsGL *mFunctions;
+ const WorkaroundsGL &mWorkarounds;
+
+ GLuint mShaderID;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_SHADERGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
new file mode 100755
index 000000000..3a227906f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -0,0 +1,1742 @@
+//
+// Copyright (c) 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.
+//
+
+// StateManagerGL.h: Defines a class for caching applied OpenGL state
+
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+#include <limits>
+#include <string.h>
+
+#include "common/BitSetIterator.h"
+#include "common/mathutil.h"
+#include "common/matrix_utils.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/ProgramGL.h"
+#include "libANGLE/renderer/gl/SamplerGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
+#include "libANGLE/renderer/gl/VertexArrayGL.h"
+#include "libANGLE/renderer/gl/QueryGL.h"
+
+namespace rx
+{
+
+static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
+ GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED,
+ GL_COMMANDS_COMPLETED_CHROMIUM};
+
+StateManagerGL::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0)
+{
+}
+
+StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &rendererCaps)
+ : mFunctions(functions),
+ mProgram(0),
+ mVAO(0),
+ mVertexAttribCurrentValues(rendererCaps.maxVertexAttributes),
+ mBuffers(),
+ mIndexedBuffers(),
+ mTextureUnitIndex(0),
+ mTextures(),
+ mSamplers(rendererCaps.maxCombinedTextureImageUnits, 0),
+ mTransformFeedback(0),
+ mQueries(),
+ mPrevDrawTransformFeedback(nullptr),
+ mCurrentQueries(),
+ mPrevDrawContext(0),
+ mUnpackAlignment(4),
+ mUnpackRowLength(0),
+ mUnpackSkipRows(0),
+ mUnpackSkipPixels(0),
+ mUnpackImageHeight(0),
+ mUnpackSkipImages(0),
+ mPackAlignment(4),
+ mPackRowLength(0),
+ mPackSkipRows(0),
+ mPackSkipPixels(0),
+ mFramebuffers(angle::FramebufferBindingSingletonMax, 0),
+ mRenderbuffer(0),
+ mScissorTestEnabled(false),
+ mScissor(0, 0, 0, 0),
+ mViewport(0, 0, 0, 0),
+ mNear(0.0f),
+ mFar(1.0f),
+ mBlendEnabled(false),
+ mBlendColor(0, 0, 0, 0),
+ mSourceBlendRGB(GL_ONE),
+ mDestBlendRGB(GL_ZERO),
+ mSourceBlendAlpha(GL_ONE),
+ mDestBlendAlpha(GL_ZERO),
+ mBlendEquationRGB(GL_FUNC_ADD),
+ mBlendEquationAlpha(GL_FUNC_ADD),
+ mColorMaskRed(true),
+ mColorMaskGreen(true),
+ mColorMaskBlue(true),
+ mColorMaskAlpha(true),
+ mSampleAlphaToCoverageEnabled(false),
+ mSampleCoverageEnabled(false),
+ mSampleCoverageValue(1.0f),
+ mSampleCoverageInvert(false),
+ mDepthTestEnabled(false),
+ mDepthFunc(GL_LESS),
+ mDepthMask(true),
+ mStencilTestEnabled(false),
+ mStencilFrontFunc(GL_ALWAYS),
+ mStencilFrontRef(0),
+ mStencilFrontValueMask(static_cast<GLuint>(-1)),
+ mStencilFrontStencilFailOp(GL_KEEP),
+ mStencilFrontStencilPassDepthFailOp(GL_KEEP),
+ mStencilFrontStencilPassDepthPassOp(GL_KEEP),
+ mStencilFrontWritemask(static_cast<GLuint>(-1)),
+ mStencilBackFunc(GL_ALWAYS),
+ mStencilBackRef(0),
+ mStencilBackValueMask(static_cast<GLuint>(-1)),
+ mStencilBackStencilFailOp(GL_KEEP),
+ mStencilBackStencilPassDepthFailOp(GL_KEEP),
+ mStencilBackStencilPassDepthPassOp(GL_KEEP),
+ mStencilBackWritemask(static_cast<GLuint>(-1)),
+ mCullFaceEnabled(false),
+ mCullFace(GL_BACK),
+ mFrontFace(GL_CCW),
+ mPolygonOffsetFillEnabled(false),
+ mPolygonOffsetFactor(0.0f),
+ mPolygonOffsetUnits(0.0f),
+ mRasterizerDiscardEnabled(false),
+ mLineWidth(1.0f),
+ mPrimitiveRestartEnabled(false),
+ mClearColor(0.0f, 0.0f, 0.0f, 0.0f),
+ mClearDepth(1.0f),
+ mClearStencil(0),
+ mFramebufferSRGBEnabled(false),
+ mDitherEnabled(true),
+ mTextureCubemapSeamlessEnabled(false),
+ mMultisamplingEnabled(true),
+ mSampleAlphaToOneEnabled(false),
+ mCoverageModulation(GL_NONE),
+ mPathStencilFunc(GL_ALWAYS),
+ mPathStencilRef(0),
+ mPathStencilMask(std::numeric_limits<GLuint>::max()),
+ mLocalDirtyBits()
+{
+ ASSERT(mFunctions);
+
+ mTextures[GL_TEXTURE_2D].resize(rendererCaps.maxCombinedTextureImageUnits);
+ mTextures[GL_TEXTURE_CUBE_MAP].resize(rendererCaps.maxCombinedTextureImageUnits);
+ mTextures[GL_TEXTURE_2D_ARRAY].resize(rendererCaps.maxCombinedTextureImageUnits);
+ mTextures[GL_TEXTURE_3D].resize(rendererCaps.maxCombinedTextureImageUnits);
+
+ mIndexedBuffers[GL_UNIFORM_BUFFER].resize(rendererCaps.maxCombinedUniformBlocks);
+
+ for (GLenum queryType : QueryTypes)
+ {
+ mQueries[queryType] = 0;
+ }
+
+ // Initialize point sprite state for desktop GL
+ if (mFunctions->standard == STANDARD_GL_DESKTOP)
+ {
+ mFunctions->enable(GL_PROGRAM_POINT_SIZE);
+
+ // GL_POINT_SPRITE was deprecated in the core profile. Point rasterization is always
+ // performed
+ // as though POINT_SPRITE were enabled.
+ if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) == 0)
+ {
+ mFunctions->enable(GL_POINT_SPRITE);
+ }
+ }
+
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
+}
+
+void StateManagerGL::deleteProgram(GLuint program)
+{
+ if (program != 0)
+ {
+ if (mProgram == program)
+ {
+ useProgram(0);
+ }
+
+ mFunctions->deleteProgram(program);
+ }
+}
+
+void StateManagerGL::deleteVertexArray(GLuint vao)
+{
+ if (vao != 0)
+ {
+ if (mVAO == vao)
+ {
+ bindVertexArray(0, 0);
+ }
+
+ mFunctions->deleteVertexArrays(1, &vao);
+ }
+}
+
+void StateManagerGL::deleteTexture(GLuint texture)
+{
+ if (texture != 0)
+ {
+ for (const auto &textureTypeIter : mTextures)
+ {
+ const std::vector<GLuint> &textureVector = textureTypeIter.second;
+ for (size_t textureUnitIndex = 0; textureUnitIndex < textureVector.size(); textureUnitIndex++)
+ {
+ if (textureVector[textureUnitIndex] == texture)
+ {
+ activeTexture(textureUnitIndex);
+ bindTexture(textureTypeIter.first, 0);
+ }
+ }
+ }
+
+ mFunctions->deleteTextures(1, &texture);
+ }
+}
+
+void StateManagerGL::deleteSampler(GLuint sampler)
+{
+ if (sampler != 0)
+ {
+ for (size_t unit = 0; unit < mSamplers.size(); unit++)
+ {
+ if (mSamplers[unit] == sampler)
+ {
+ bindSampler(unit, 0);
+ }
+ }
+
+ mFunctions->deleteSamplers(1, &sampler);
+ }
+}
+
+void StateManagerGL::deleteBuffer(GLuint buffer)
+{
+ if (buffer != 0)
+ {
+ for (const auto &bufferTypeIter : mBuffers)
+ {
+ if (bufferTypeIter.second == buffer)
+ {
+ bindBuffer(bufferTypeIter.first, 0);
+ }
+ }
+
+ for (const auto &bufferTypeIter : mIndexedBuffers)
+ {
+ for (size_t bindIndex = 0; bindIndex < bufferTypeIter.second.size(); bindIndex++)
+ {
+ if (bufferTypeIter.second[bindIndex].buffer == buffer)
+ {
+ bindBufferBase(bufferTypeIter.first, bindIndex, 0);
+ }
+ }
+ }
+
+ mFunctions->deleteBuffers(1, &buffer);
+ }
+}
+
+void StateManagerGL::deleteFramebuffer(GLuint fbo)
+{
+ if (fbo != 0)
+ {
+ for (size_t binding = 0; binding < mFramebuffers.size(); ++binding)
+ {
+ if (mFramebuffers[binding] == fbo)
+ {
+ GLenum enumValue = angle::FramebufferBindingToEnum(
+ static_cast<angle::FramebufferBinding>(binding));
+ bindFramebuffer(enumValue, 0);
+ }
+ mFunctions->deleteFramebuffers(1, &fbo);
+ }
+ }
+}
+
+void StateManagerGL::deleteRenderbuffer(GLuint rbo)
+{
+ if (rbo != 0)
+ {
+ if (mRenderbuffer == rbo)
+ {
+ bindRenderbuffer(GL_RENDERBUFFER, 0);
+ }
+
+ mFunctions->deleteRenderbuffers(1, &rbo);
+ }
+}
+
+void StateManagerGL::deleteTransformFeedback(GLuint transformFeedback)
+{
+ if (transformFeedback != 0)
+ {
+ if (mTransformFeedback == transformFeedback)
+ {
+ bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+ }
+
+ if (mPrevDrawTransformFeedback != nullptr &&
+ mPrevDrawTransformFeedback->getTransformFeedbackID() == transformFeedback)
+ {
+ mPrevDrawTransformFeedback = nullptr;
+ }
+
+ mFunctions->deleteTransformFeedbacks(1, &transformFeedback);
+ }
+}
+
+void StateManagerGL::deleteQuery(GLuint query)
+{
+ if (query != 0)
+ {
+ for (auto &activeQuery : mQueries)
+ {
+ GLuint activeQueryID = activeQuery.second;
+ if (activeQueryID == query)
+ {
+ GLenum type = activeQuery.first;
+ endQuery(type, query);
+ }
+ }
+ }
+}
+
+void StateManagerGL::useProgram(GLuint program)
+{
+ if (mProgram != program)
+ {
+ forceUseProgram(program);
+ }
+}
+
+void StateManagerGL::forceUseProgram(GLuint program)
+{
+ mProgram = program;
+ mFunctions->useProgram(mProgram);
+}
+
+void StateManagerGL::bindVertexArray(GLuint vao, GLuint elementArrayBuffer)
+{
+ if (mVAO != vao)
+ {
+ mVAO = vao;
+ mBuffers[GL_ELEMENT_ARRAY_BUFFER] = elementArrayBuffer;
+ mFunctions->bindVertexArray(vao);
+ }
+}
+
+void StateManagerGL::bindBuffer(GLenum type, GLuint buffer)
+{
+ if (mBuffers[type] != buffer)
+ {
+ mBuffers[type] = buffer;
+ mFunctions->bindBuffer(type, buffer);
+ }
+}
+
+void StateManagerGL::bindBufferBase(GLenum type, size_t index, GLuint buffer)
+{
+ auto &binding = mIndexedBuffers[type][index];
+ if (binding.buffer != buffer || binding.offset != static_cast<size_t>(-1) ||
+ binding.size != static_cast<size_t>(-1))
+ {
+ binding.buffer = buffer;
+ binding.offset = static_cast<size_t>(-1);
+ binding.size = static_cast<size_t>(-1);
+ mFunctions->bindBufferBase(type, static_cast<GLuint>(index), buffer);
+ }
+}
+
+void StateManagerGL::bindBufferRange(GLenum type,
+ size_t index,
+ GLuint buffer,
+ size_t offset,
+ size_t size)
+{
+ auto &binding = mIndexedBuffers[type][index];
+ if (binding.buffer != buffer || binding.offset != offset || binding.size != size)
+ {
+ binding.buffer = buffer;
+ binding.offset = offset;
+ binding.size = size;
+ mFunctions->bindBufferRange(type, static_cast<GLuint>(index), buffer, offset, size);
+ }
+}
+
+void StateManagerGL::activeTexture(size_t unit)
+{
+ if (mTextureUnitIndex != unit)
+ {
+ mTextureUnitIndex = unit;
+ mFunctions->activeTexture(GL_TEXTURE0 + static_cast<GLenum>(mTextureUnitIndex));
+ }
+}
+
+void StateManagerGL::bindTexture(GLenum type, GLuint texture)
+{
+ if (mTextures[type][mTextureUnitIndex] != texture)
+ {
+ mTextures[type][mTextureUnitIndex] = texture;
+ mFunctions->bindTexture(type, texture);
+ }
+}
+
+void StateManagerGL::bindSampler(size_t unit, GLuint sampler)
+{
+ if (mSamplers[unit] != sampler)
+ {
+ mSamplers[unit] = sampler;
+ mFunctions->bindSampler(static_cast<GLuint>(unit), sampler);
+ }
+}
+
+void StateManagerGL::setPixelUnpackState(const gl::PixelUnpackState &unpack)
+{
+ GLuint unpackBufferID = 0;
+ const gl::Buffer *unpackBuffer = unpack.pixelBuffer.get();
+ if (unpackBuffer != nullptr)
+ {
+ unpackBufferID = GetImplAs<BufferGL>(unpackBuffer)->getBufferID();
+ }
+ setPixelUnpackState(unpack.alignment, unpack.rowLength, unpack.skipRows, unpack.skipPixels,
+ unpack.imageHeight, unpack.skipImages, unpackBufferID);
+}
+
+void StateManagerGL::setPixelUnpackState(GLint alignment,
+ GLint rowLength,
+ GLint skipRows,
+ GLint skipPixels,
+ GLint imageHeight,
+ GLint skipImages,
+ GLuint unpackBuffer)
+{
+ if (mUnpackAlignment != alignment)
+ {
+ mUnpackAlignment = alignment;
+ mFunctions->pixelStorei(GL_UNPACK_ALIGNMENT, mUnpackAlignment);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_ALIGNMENT);
+ }
+
+ if (mUnpackRowLength != rowLength)
+ {
+ mUnpackRowLength = rowLength;
+ mFunctions->pixelStorei(GL_UNPACK_ROW_LENGTH, mUnpackRowLength);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH);
+ }
+
+ if (mUnpackSkipRows != skipRows)
+ {
+ mUnpackSkipRows = skipRows;
+ mFunctions->pixelStorei(GL_UNPACK_SKIP_ROWS, mUnpackSkipRows);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_SKIP_ROWS);
+ }
+
+ if (mUnpackSkipPixels != skipPixels)
+ {
+ mUnpackSkipPixels = skipPixels;
+ mFunctions->pixelStorei(GL_UNPACK_SKIP_PIXELS, mUnpackSkipPixels);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_SKIP_PIXELS);
+ }
+
+ if (mUnpackImageHeight != imageHeight)
+ {
+ mUnpackImageHeight = imageHeight;
+ mFunctions->pixelStorei(GL_UNPACK_IMAGE_HEIGHT, mUnpackImageHeight);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
+ }
+
+ if (mUnpackSkipImages != skipImages)
+ {
+ mUnpackSkipImages = skipImages;
+ mFunctions->pixelStorei(GL_UNPACK_SKIP_IMAGES, mUnpackSkipImages);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_SKIP_IMAGES);
+ }
+
+ bindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
+}
+
+void StateManagerGL::setPixelPackState(const gl::PixelPackState &pack)
+{
+ GLuint packBufferID = 0;
+ const gl::Buffer *packBuffer = pack.pixelBuffer.get();
+ if (packBuffer != nullptr)
+ {
+ packBufferID = GetImplAs<BufferGL>(packBuffer)->getBufferID();
+ }
+ setPixelPackState(pack.alignment, pack.rowLength, pack.skipRows, pack.skipPixels, packBufferID);
+}
+
+void StateManagerGL::setPixelPackState(GLint alignment,
+ GLint rowLength,
+ GLint skipRows,
+ GLint skipPixels,
+ GLuint packBuffer)
+{
+ if (mPackAlignment != alignment)
+ {
+ mPackAlignment = alignment;
+ mFunctions->pixelStorei(GL_PACK_ALIGNMENT, mPackAlignment);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_PACK_ALIGNMENT);
+ }
+
+ if (mPackRowLength != rowLength)
+ {
+ mPackRowLength = rowLength;
+ mFunctions->pixelStorei(GL_PACK_ROW_LENGTH, mPackRowLength);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH);
+ }
+
+ if (mPackSkipRows != skipRows)
+ {
+ mPackSkipRows = skipRows;
+ mFunctions->pixelStorei(GL_PACK_SKIP_ROWS, mPackSkipRows);
+
+ // TODO: set dirty bit once one exists
+ }
+
+ if (mPackSkipPixels != skipPixels)
+ {
+ mPackSkipPixels = skipPixels;
+ mFunctions->pixelStorei(GL_PACK_SKIP_PIXELS, mPackSkipPixels);
+
+ // TODO: set dirty bit once one exists
+ }
+
+ bindBuffer(GL_PIXEL_PACK_BUFFER, packBuffer);
+}
+
+void StateManagerGL::bindFramebuffer(GLenum type, GLuint framebuffer)
+{
+ if (type == GL_FRAMEBUFFER)
+ {
+ if (mFramebuffers[angle::FramebufferBindingRead] != framebuffer ||
+ mFramebuffers[angle::FramebufferBindingDraw] != framebuffer)
+ {
+ mFramebuffers[angle::FramebufferBindingRead] = framebuffer;
+ mFramebuffers[angle::FramebufferBindingDraw] = framebuffer;
+ mFunctions->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+ }
+ }
+ else
+ {
+ angle::FramebufferBinding binding = angle::EnumToFramebufferBinding(type);
+
+ if (mFramebuffers[binding] != framebuffer)
+ {
+ mFramebuffers[binding] = framebuffer;
+ mFunctions->bindFramebuffer(type, framebuffer);
+ }
+ }
+}
+
+void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer)
+{
+ ASSERT(type == GL_RENDERBUFFER);
+ if (mRenderbuffer != renderbuffer)
+ {
+ mRenderbuffer = renderbuffer;
+ mFunctions->bindRenderbuffer(type, mRenderbuffer);
+ }
+}
+
+void StateManagerGL::bindTransformFeedback(GLenum type, GLuint transformFeedback)
+{
+ ASSERT(type == GL_TRANSFORM_FEEDBACK);
+ if (mTransformFeedback != transformFeedback)
+ {
+ // Pause the current transform feedback if one is active.
+ // To handle virtualized contexts, StateManagerGL needs to be able to bind a new transform
+ // feedback at any time, even if there is one active.
+ if (mPrevDrawTransformFeedback != nullptr &&
+ mPrevDrawTransformFeedback->getTransformFeedbackID() != transformFeedback)
+ {
+ mPrevDrawTransformFeedback->syncPausedState(true);
+ mPrevDrawTransformFeedback = nullptr;
+ }
+
+ mTransformFeedback = transformFeedback;
+ mFunctions->bindTransformFeedback(type, mTransformFeedback);
+ }
+}
+
+void StateManagerGL::beginQuery(GLenum type, GLuint query)
+{
+ // Make sure this is a valid query type and there is no current active query of this type
+ ASSERT(mQueries.find(type) != mQueries.end());
+ ASSERT(mQueries[type] == 0);
+ ASSERT(query != 0);
+
+ mQueries[type] = query;
+ mFunctions->beginQuery(type, query);
+}
+
+void StateManagerGL::endQuery(GLenum type, GLuint query)
+{
+ ASSERT(mQueries[type] == query);
+ mQueries[type] = 0;
+ mFunctions->endQuery(type);
+}
+
+void StateManagerGL::onBeginQuery(QueryGL *query)
+{
+ mCurrentQueries.insert(query);
+}
+
+void StateManagerGL::onDeleteQueryObject(QueryGL *query)
+{
+ mCurrentQueries.erase(query);
+}
+
+gl::Error StateManagerGL::setDrawArraysState(const gl::ContextState &data,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ const gl::State &state = data.getState();
+
+ const gl::Program *program = state.getProgram();
+
+ const gl::VertexArray *vao = state.getVertexArray();
+ const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
+
+ gl::Error error = vaoGL->syncDrawArraysState(program->getActiveAttribLocationsMask(), first,
+ count, instanceCount);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
+
+ return setGenericDrawState(data);
+}
+
+gl::Error StateManagerGL::setDrawElementsState(const gl::ContextState &data,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instanceCount,
+ const GLvoid **outIndices)
+{
+ const gl::State &state = data.getState();
+
+ const gl::Program *program = state.getProgram();
+
+ const gl::VertexArray *vao = state.getVertexArray();
+ const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
+
+ gl::Error error =
+ vaoGL->syncDrawElementsState(program->getActiveAttribLocationsMask(), count, type, indices,
+ instanceCount, state.isPrimitiveRestartEnabled(), outIndices);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
+
+ return setGenericDrawState(data);
+}
+
+gl::Error StateManagerGL::pauseTransformFeedback(const gl::ContextState &data)
+{
+ // If the context is going to be changed, pause the previous context's transform feedback
+ if (data.getContext() != mPrevDrawContext)
+ {
+ if (mPrevDrawTransformFeedback != nullptr)
+ {
+ mPrevDrawTransformFeedback->syncPausedState(true);
+ }
+ }
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error StateManagerGL::onMakeCurrent(const gl::ContextState &data)
+{
+ const gl::State &state = data.getState();
+
+ // If the context has changed, pause the previous context's queries
+ if (data.getContext() != mPrevDrawContext)
+ {
+ for (QueryGL *prevQuery : mCurrentQueries)
+ {
+ prevQuery->pause();
+ }
+ }
+ mCurrentQueries.clear();
+ mPrevDrawTransformFeedback = nullptr;
+ mPrevDrawContext = data.getContext();
+
+ // Set the current query state
+ for (GLenum queryType : QueryTypes)
+ {
+ gl::Query *query = state.getActiveQuery(queryType);
+ if (query != nullptr)
+ {
+ QueryGL *queryGL = GetImplAs<QueryGL>(query);
+ queryGL->resume();
+
+ mCurrentQueries.insert(queryGL);
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error StateManagerGL::setGenericDrawState(const gl::ContextState &data)
+{
+ const gl::State &state = data.getState();
+
+ // Sync the current program state
+ const gl::Program *program = state.getProgram();
+ const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
+ useProgram(programGL->getProgramID());
+
+ for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
+ uniformBlockIndex++)
+ {
+ GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
+ const auto &uniformBuffer = state.getIndexedUniformBuffer(binding);
+
+ if (uniformBuffer.get() != nullptr)
+ {
+ BufferGL *bufferGL = GetImplAs<BufferGL>(uniformBuffer.get());
+
+ if (uniformBuffer.getSize() == 0)
+ {
+ bindBufferBase(GL_UNIFORM_BUFFER, binding, bufferGL->getBufferID());
+ }
+ else
+ {
+ bindBufferRange(GL_UNIFORM_BUFFER, binding, bufferGL->getBufferID(),
+ uniformBuffer.getOffset(), uniformBuffer.getSize());
+ }
+ }
+ }
+
+ const std::vector<SamplerBindingGL> &appliedSamplerUniforms = programGL->getAppliedSamplerUniforms();
+ for (const SamplerBindingGL &samplerUniform : appliedSamplerUniforms)
+ {
+ GLenum textureType = samplerUniform.textureType;
+ for (GLuint textureUnitIndex : samplerUniform.boundTextureUnits)
+ {
+ gl::Texture *texture = state.getSamplerTexture(textureUnitIndex, textureType);
+ if (texture != nullptr)
+ {
+ const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
+
+ if (mTextures[textureType][textureUnitIndex] != textureGL->getTextureID() ||
+ texture->hasAnyDirtyBit() || textureGL->hasAnyDirtyBit())
+ {
+ activeTexture(textureUnitIndex);
+ bindTexture(textureType, textureGL->getTextureID());
+
+ // TODO: Call this from the gl:: layer once other backends use dirty bits for
+ // texture state.
+ texture->syncImplState();
+ }
+ }
+ else
+ {
+ if (mTextures[textureType][textureUnitIndex] != 0)
+ {
+ activeTexture(textureUnitIndex);
+ bindTexture(textureType, 0);
+ }
+ }
+
+ const gl::Sampler *sampler = state.getSampler(textureUnitIndex);
+ if (sampler != nullptr)
+ {
+ const SamplerGL *samplerGL = GetImplAs<SamplerGL>(sampler);
+ samplerGL->syncState(sampler->getSamplerState());
+ bindSampler(textureUnitIndex, samplerGL->getSamplerID());
+ }
+ else
+ {
+ bindSampler(textureUnitIndex, 0);
+ }
+ }
+ }
+
+ const gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
+ const FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
+ bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferGL->getFramebufferID());
+
+ // Seamless cubemaps are required for ES3 and higher contexts.
+ setTextureCubemapSeamlessEnabled(data.getClientMajorVersion() >= 3);
+
+ // Set the current transform feedback state
+ gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
+ if (transformFeedback)
+ {
+ TransformFeedbackGL *transformFeedbackGL =
+ GetImplAs<TransformFeedbackGL>(transformFeedback);
+ bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID());
+ transformFeedbackGL->syncActiveState(transformFeedback->isActive(),
+ transformFeedback->getPrimitiveMode());
+ transformFeedbackGL->syncPausedState(transformFeedback->isPaused());
+ mPrevDrawTransformFeedback = transformFeedbackGL;
+ }
+ else
+ {
+ bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+ mPrevDrawTransformFeedback = nullptr;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void StateManagerGL::setAttributeCurrentData(size_t index,
+ const gl::VertexAttribCurrentValueData &data)
+{
+ if (mVertexAttribCurrentValues[index] != data)
+ {
+ mVertexAttribCurrentValues[index] = data;
+ switch (mVertexAttribCurrentValues[index].Type)
+ {
+ case GL_FLOAT:
+ mFunctions->vertexAttrib4fv(static_cast<GLuint>(index),
+ mVertexAttribCurrentValues[index].FloatValues);
+ break;
+ case GL_INT:
+ mFunctions->vertexAttribI4iv(static_cast<GLuint>(index),
+ mVertexAttribCurrentValues[index].IntValues);
+ break;
+ case GL_UNSIGNED_INT:
+ mFunctions->vertexAttribI4uiv(static_cast<GLuint>(index),
+ mVertexAttribCurrentValues[index].UnsignedIntValues);
+ break;
+ default: UNREACHABLE();
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_CURRENT_VALUE_0 + index);
+ }
+}
+
+void StateManagerGL::setScissorTestEnabled(bool enabled)
+{
+ if (mScissorTestEnabled != enabled)
+ {
+ mScissorTestEnabled = enabled;
+ if (mScissorTestEnabled)
+ {
+ mFunctions->enable(GL_SCISSOR_TEST);
+ }
+ else
+ {
+ mFunctions->disable(GL_SCISSOR_TEST);
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
+ }
+}
+
+void StateManagerGL::setScissor(const gl::Rectangle &scissor)
+{
+ if (scissor != mScissor)
+ {
+ mScissor = scissor;
+ mFunctions->scissor(mScissor.x, mScissor.y, mScissor.width, mScissor.height);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR);
+ }
+}
+
+void StateManagerGL::setViewport(const gl::Rectangle &viewport)
+{
+ if (viewport != mViewport)
+ {
+ mViewport = viewport;
+ mFunctions->viewport(mViewport.x, mViewport.y, mViewport.width, mViewport.height);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_VIEWPORT);
+ }
+}
+
+void StateManagerGL::setDepthRange(float near, float far)
+{
+ if (mNear != near || mFar != far)
+ {
+ mNear = near;
+ mFar = far;
+
+ // The glDepthRangef function isn't available until OpenGL 4.1. Prefer it when it is
+ // available because OpenGL ES only works in floats.
+ if (mFunctions->depthRangef)
+ {
+ mFunctions->depthRangef(mNear, mFar);
+ }
+ else
+ {
+ ASSERT(mFunctions->depthRange);
+ mFunctions->depthRange(mNear, mFar);
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_RANGE);
+ }
+}
+
+void StateManagerGL::setBlendEnabled(bool enabled)
+{
+ if (mBlendEnabled != enabled)
+ {
+ mBlendEnabled = enabled;
+ if (mBlendEnabled)
+ {
+ mFunctions->enable(GL_BLEND);
+ }
+ else
+ {
+ mFunctions->disable(GL_BLEND);
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
+ }
+}
+
+void StateManagerGL::setBlendColor(const gl::ColorF &blendColor)
+{
+ if (mBlendColor != blendColor)
+ {
+ mBlendColor = blendColor;
+ mFunctions->blendColor(mBlendColor.red, mBlendColor.green, mBlendColor.blue, mBlendColor.alpha);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_COLOR);
+ }
+}
+
+void StateManagerGL::setBlendFuncs(GLenum sourceBlendRGB,
+ GLenum destBlendRGB,
+ GLenum sourceBlendAlpha,
+ GLenum destBlendAlpha)
+{
+ if (mSourceBlendRGB != sourceBlendRGB || mDestBlendRGB != destBlendRGB ||
+ mSourceBlendAlpha != sourceBlendAlpha || mDestBlendAlpha != destBlendAlpha)
+ {
+ mSourceBlendRGB = sourceBlendRGB;
+ mDestBlendRGB = destBlendRGB;
+ mSourceBlendAlpha = sourceBlendAlpha;
+ mDestBlendAlpha = destBlendAlpha;
+
+ mFunctions->blendFuncSeparate(mSourceBlendRGB, mDestBlendRGB, mSourceBlendAlpha, mDestBlendAlpha);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);
+ }
+}
+
+void StateManagerGL::setBlendEquations(GLenum blendEquationRGB, GLenum blendEquationAlpha)
+{
+ if (mBlendEquationRGB != blendEquationRGB || mBlendEquationAlpha != blendEquationAlpha)
+ {
+ mBlendEquationRGB = blendEquationRGB;
+ mBlendEquationAlpha = blendEquationAlpha;
+
+ mFunctions->blendEquationSeparate(mBlendEquationRGB, mBlendEquationAlpha);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_EQUATIONS);
+ }
+}
+
+void StateManagerGL::setColorMask(bool red, bool green, bool blue, bool alpha)
+{
+ if (mColorMaskRed != red || mColorMaskGreen != green || mColorMaskBlue != blue || mColorMaskAlpha != alpha)
+ {
+ mColorMaskRed = red;
+ mColorMaskGreen = green;
+ mColorMaskBlue = blue;
+ mColorMaskAlpha = alpha;
+ mFunctions->colorMask(mColorMaskRed, mColorMaskGreen, mColorMaskBlue, mColorMaskAlpha);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
+ }
+}
+
+void StateManagerGL::setSampleAlphaToCoverageEnabled(bool enabled)
+{
+ if (mSampleAlphaToCoverageEnabled != enabled)
+ {
+ mSampleAlphaToCoverageEnabled = enabled;
+ if (mSampleAlphaToCoverageEnabled)
+ {
+ mFunctions->enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+ }
+ else
+ {
+ mFunctions->disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
+ }
+}
+
+void StateManagerGL::setSampleCoverageEnabled(bool enabled)
+{
+ if (mSampleCoverageEnabled != enabled)
+ {
+ mSampleCoverageEnabled = enabled;
+ if (mSampleCoverageEnabled)
+ {
+ mFunctions->enable(GL_SAMPLE_COVERAGE);
+ }
+ else
+ {
+ mFunctions->disable(GL_SAMPLE_COVERAGE);
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
+ }
+}
+
+void StateManagerGL::setSampleCoverage(float value, bool invert)
+{
+ if (mSampleCoverageValue != value || mSampleCoverageInvert != invert)
+ {
+ mSampleCoverageValue = value;
+ mSampleCoverageInvert = invert;
+ mFunctions->sampleCoverage(mSampleCoverageValue, mSampleCoverageInvert);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_COVERAGE);
+ }
+}
+
+void StateManagerGL::setDepthTestEnabled(bool enabled)
+{
+ if (mDepthTestEnabled != enabled)
+ {
+ mDepthTestEnabled = enabled;
+ if (mDepthTestEnabled)
+ {
+ mFunctions->enable(GL_DEPTH_TEST);
+ }
+ else
+ {
+ mFunctions->disable(GL_DEPTH_TEST);
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED);
+ }
+}
+
+void StateManagerGL::setDepthFunc(GLenum depthFunc)
+{
+ if (mDepthFunc != depthFunc)
+ {
+ mDepthFunc = depthFunc;
+ mFunctions->depthFunc(mDepthFunc);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_FUNC);
+ }
+}
+
+void StateManagerGL::setDepthMask(bool mask)
+{
+ if (mDepthMask != mask)
+ {
+ mDepthMask = mask;
+ mFunctions->depthMask(mDepthMask);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_DEPTH_MASK);
+ }
+}
+
+void StateManagerGL::setStencilTestEnabled(bool enabled)
+{
+ if (mStencilTestEnabled != enabled)
+ {
+ mStencilTestEnabled = enabled;
+ if (mStencilTestEnabled)
+ {
+ mFunctions->enable(GL_STENCIL_TEST);
+ }
+ else
+ {
+ mFunctions->disable(GL_STENCIL_TEST);
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED);
+ }
+}
+
+void StateManagerGL::setStencilFrontWritemask(GLuint mask)
+{
+ if (mStencilFrontWritemask != mask)
+ {
+ mStencilFrontWritemask = mask;
+ mFunctions->stencilMaskSeparate(GL_FRONT, mStencilFrontWritemask);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+ }
+}
+
+void StateManagerGL::setStencilBackWritemask(GLuint mask)
+{
+ if (mStencilBackWritemask != mask)
+ {
+ mStencilBackWritemask = mask;
+ mFunctions->stencilMaskSeparate(GL_BACK, mStencilBackWritemask);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+ }
+}
+
+void StateManagerGL::setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask)
+{
+ if (mStencilFrontFunc != func || mStencilFrontRef != ref || mStencilFrontValueMask != mask)
+ {
+ mStencilFrontFunc = func;
+ mStencilFrontRef = ref;
+ mStencilFrontValueMask = mask;
+ mFunctions->stencilFuncSeparate(GL_FRONT, mStencilFrontFunc, mStencilFrontRef, mStencilFrontValueMask);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT);
+ }
+}
+
+void StateManagerGL::setStencilBackFuncs(GLenum func, GLint ref, GLuint mask)
+{
+ if (mStencilBackFunc != func || mStencilBackRef != ref || mStencilBackValueMask != mask)
+ {
+ mStencilBackFunc = func;
+ mStencilBackRef = ref;
+ mStencilBackValueMask = mask;
+ mFunctions->stencilFuncSeparate(GL_BACK, mStencilBackFunc, mStencilBackRef, mStencilBackValueMask);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK);
+ }
+}
+
+void StateManagerGL::setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass)
+{
+ if (mStencilFrontStencilFailOp != sfail || mStencilFrontStencilPassDepthFailOp != dpfail || mStencilFrontStencilPassDepthPassOp != dppass)
+ {
+ mStencilFrontStencilFailOp = sfail;
+ mStencilFrontStencilPassDepthFailOp = dpfail;
+ mStencilFrontStencilPassDepthPassOp = dppass;
+ mFunctions->stencilOpSeparate(GL_FRONT, mStencilFrontStencilFailOp, mStencilFrontStencilPassDepthFailOp, mStencilFrontStencilPassDepthPassOp);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_FRONT);
+ }
+}
+
+void StateManagerGL::setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass)
+{
+ if (mStencilBackStencilFailOp != sfail || mStencilBackStencilPassDepthFailOp != dpfail || mStencilBackStencilPassDepthPassOp != dppass)
+ {
+ mStencilBackStencilFailOp = sfail;
+ mStencilBackStencilPassDepthFailOp = dpfail;
+ mStencilBackStencilPassDepthPassOp = dppass;
+ mFunctions->stencilOpSeparate(GL_BACK, mStencilBackStencilFailOp, mStencilBackStencilPassDepthFailOp, mStencilBackStencilPassDepthPassOp);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_STENCIL_OPS_BACK);
+ }
+}
+
+void StateManagerGL::setCullFaceEnabled(bool enabled)
+{
+ if (mCullFaceEnabled != enabled)
+ {
+ mCullFaceEnabled = enabled;
+ if (mCullFaceEnabled)
+ {
+ mFunctions->enable(GL_CULL_FACE);
+ }
+ else
+ {
+ mFunctions->disable(GL_CULL_FACE);
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE_ENABLED);
+ }
+}
+
+void StateManagerGL::setCullFace(GLenum cullFace)
+{
+ if (mCullFace != cullFace)
+ {
+ mCullFace = cullFace;
+ mFunctions->cullFace(mCullFace);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_CULL_FACE);
+ }
+}
+
+void StateManagerGL::setFrontFace(GLenum frontFace)
+{
+ if (mFrontFace != frontFace)
+ {
+ mFrontFace = frontFace;
+ mFunctions->frontFace(mFrontFace);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRONT_FACE);
+ }
+}
+
+void StateManagerGL::setPolygonOffsetFillEnabled(bool enabled)
+{
+ if (mPolygonOffsetFillEnabled != enabled)
+ {
+ mPolygonOffsetFillEnabled = enabled;
+ if (mPolygonOffsetFillEnabled)
+ {
+ mFunctions->enable(GL_POLYGON_OFFSET_FILL);
+ }
+ else
+ {
+ mFunctions->disable(GL_POLYGON_OFFSET_FILL);
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
+ }
+}
+
+void StateManagerGL::setPolygonOffset(float factor, float units)
+{
+ if (mPolygonOffsetFactor != factor || mPolygonOffsetUnits != units)
+ {
+ mPolygonOffsetFactor = factor;
+ mPolygonOffsetUnits = units;
+ mFunctions->polygonOffset(mPolygonOffsetFactor, mPolygonOffsetUnits);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_POLYGON_OFFSET);
+ }
+}
+
+void StateManagerGL::setRasterizerDiscardEnabled(bool enabled)
+{
+ if (mRasterizerDiscardEnabled != enabled)
+ {
+ mRasterizerDiscardEnabled = enabled;
+ if (mRasterizerDiscardEnabled)
+ {
+ mFunctions->enable(GL_RASTERIZER_DISCARD);
+ }
+ else
+ {
+ mFunctions->disable(GL_RASTERIZER_DISCARD);
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
+ }
+}
+
+void StateManagerGL::setLineWidth(float width)
+{
+ if (mLineWidth != width)
+ {
+ mLineWidth = width;
+ mFunctions->lineWidth(mLineWidth);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_LINE_WIDTH);
+ }
+}
+
+void StateManagerGL::setPrimitiveRestartEnabled(bool enabled)
+{
+ if (mPrimitiveRestartEnabled != enabled)
+ {
+ mPrimitiveRestartEnabled = enabled;
+
+ if (mPrimitiveRestartEnabled)
+ {
+ mFunctions->enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
+ }
+ else
+ {
+ mFunctions->disable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
+ }
+}
+
+void StateManagerGL::setClearDepth(float clearDepth)
+{
+ if (mClearDepth != clearDepth)
+ {
+ mClearDepth = clearDepth;
+
+ // The glClearDepthf function isn't available until OpenGL 4.1. Prefer it when it is
+ // available because OpenGL ES only works in floats.
+ if (mFunctions->clearDepthf)
+ {
+ mFunctions->clearDepthf(mClearDepth);
+ }
+ else
+ {
+ ASSERT(mFunctions->clearDepth);
+ mFunctions->clearDepth(mClearDepth);
+ }
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_DEPTH);
+ }
+}
+
+void StateManagerGL::setClearColor(const gl::ColorF &clearColor)
+{
+ if (mClearColor != clearColor)
+ {
+ mClearColor = clearColor;
+ mFunctions->clearColor(mClearColor.red, mClearColor.green, mClearColor.blue, mClearColor.alpha);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_COLOR);
+ }
+}
+
+void StateManagerGL::setClearStencil(GLint clearStencil)
+{
+ if (mClearStencil != clearStencil)
+ {
+ mClearStencil = clearStencil;
+ mFunctions->clearStencil(mClearStencil);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_CLEAR_STENCIL);
+ }
+}
+
+void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBits &glDirtyBits)
+{
+ // The the current framebuffer binding sometimes requires resetting the srgb blending
+ if (glDirtyBits[gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING] &&
+ mFunctions->standard == STANDARD_GL_DESKTOP)
+ {
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
+ }
+
+ const auto &glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits);
+
+ if (!glAndLocalDirtyBits.any())
+ {
+ return;
+ }
+
+ // TODO(jmadill): Investigate only syncing vertex state for active attributes
+ for (auto dirtyBit : angle::IterateBitSet(glAndLocalDirtyBits))
+ {
+ switch (dirtyBit)
+ {
+ case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
+ setScissorTestEnabled(state.isScissorTestEnabled());
+ break;
+ case gl::State::DIRTY_BIT_SCISSOR:
+ setScissor(state.getScissor());
+ break;
+ case gl::State::DIRTY_BIT_VIEWPORT:
+ setViewport(state.getViewport());
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_RANGE:
+ setDepthRange(state.getNearPlane(), state.getFarPlane());
+ break;
+ case gl::State::DIRTY_BIT_BLEND_ENABLED:
+ setBlendEnabled(state.isBlendEnabled());
+ break;
+ case gl::State::DIRTY_BIT_BLEND_COLOR:
+ setBlendColor(state.getBlendColor());
+ break;
+ case gl::State::DIRTY_BIT_BLEND_FUNCS:
+ {
+ const auto &blendState = state.getBlendState();
+ setBlendFuncs(blendState.sourceBlendRGB, blendState.destBlendRGB,
+ blendState.sourceBlendAlpha, blendState.destBlendAlpha);
+ break;
+ }
+ case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
+ {
+ const auto &blendState = state.getBlendState();
+ setBlendEquations(blendState.blendEquationRGB, blendState.blendEquationAlpha);
+ break;
+ }
+ case gl::State::DIRTY_BIT_COLOR_MASK:
+ {
+ const auto &blendState = state.getBlendState();
+ setColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
+ blendState.colorMaskBlue, blendState.colorMaskAlpha);
+ break;
+ }
+ case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
+ setSampleAlphaToCoverageEnabled(state.isSampleAlphaToCoverageEnabled());
+ break;
+ case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
+ setSampleCoverageEnabled(state.isSampleCoverageEnabled());
+ break;
+ case gl::State::DIRTY_BIT_SAMPLE_COVERAGE:
+ setSampleCoverage(state.getSampleCoverageValue(), state.getSampleCoverageInvert());
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
+ setDepthTestEnabled(state.isDepthTestEnabled());
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_FUNC:
+ setDepthFunc(state.getDepthStencilState().depthFunc);
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_MASK:
+ setDepthMask(state.getDepthStencilState().depthMask);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
+ setStencilTestEnabled(state.isStencilTestEnabled());
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
+ {
+ const auto &depthStencilState = state.getDepthStencilState();
+ setStencilFrontFuncs(depthStencilState.stencilFunc, state.getStencilRef(),
+ depthStencilState.stencilMask);
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
+ {
+ const auto &depthStencilState = state.getDepthStencilState();
+ setStencilBackFuncs(depthStencilState.stencilBackFunc, state.getStencilBackRef(),
+ depthStencilState.stencilBackMask);
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
+ {
+ const auto &depthStencilState = state.getDepthStencilState();
+ setStencilFrontOps(depthStencilState.stencilFail,
+ depthStencilState.stencilPassDepthFail,
+ depthStencilState.stencilPassDepthPass);
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
+ {
+ const auto &depthStencilState = state.getDepthStencilState();
+ setStencilBackOps(depthStencilState.stencilBackFail,
+ depthStencilState.stencilBackPassDepthFail,
+ depthStencilState.stencilBackPassDepthPass);
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+ setStencilFrontWritemask(state.getDepthStencilState().stencilWritemask);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+ setStencilBackWritemask(state.getDepthStencilState().stencilBackWritemask);
+ break;
+ case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
+ setCullFaceEnabled(state.isCullFaceEnabled());
+ break;
+ case gl::State::DIRTY_BIT_CULL_FACE:
+ setCullFace(state.getRasterizerState().cullMode);
+ break;
+ case gl::State::DIRTY_BIT_FRONT_FACE:
+ setFrontFace(state.getRasterizerState().frontFace);
+ break;
+ case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
+ setPolygonOffsetFillEnabled(state.isPolygonOffsetFillEnabled());
+ break;
+ case gl::State::DIRTY_BIT_POLYGON_OFFSET:
+ {
+ const auto &rasterizerState = state.getRasterizerState();
+ setPolygonOffset(rasterizerState.polygonOffsetFactor,
+ rasterizerState.polygonOffsetUnits);
+ break;
+ }
+ case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
+ setRasterizerDiscardEnabled(state.isRasterizerDiscardEnabled());
+ break;
+ case gl::State::DIRTY_BIT_LINE_WIDTH:
+ setLineWidth(state.getLineWidth());
+ break;
+ case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
+ setPrimitiveRestartEnabled(state.isPrimitiveRestartEnabled());
+ break;
+ case gl::State::DIRTY_BIT_CLEAR_COLOR:
+ setClearColor(state.getColorClearValue());
+ break;
+ case gl::State::DIRTY_BIT_CLEAR_DEPTH:
+ setClearDepth(state.getDepthClearValue());
+ break;
+ case gl::State::DIRTY_BIT_CLEAR_STENCIL:
+ setClearStencil(state.getStencilClearValue());
+ break;
+ case gl::State::DIRTY_BIT_UNPACK_ALIGNMENT:
+ // TODO(jmadill): split this
+ setPixelUnpackState(state.getUnpackState());
+ break;
+ case gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH:
+ // TODO(jmadill): split this
+ setPixelUnpackState(state.getUnpackState());
+ break;
+ case gl::State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT:
+ // TODO(jmadill): split this
+ setPixelUnpackState(state.getUnpackState());
+ break;
+ case gl::State::DIRTY_BIT_UNPACK_SKIP_IMAGES:
+ // TODO(jmadill): split this
+ setPixelUnpackState(state.getUnpackState());
+ break;
+ case gl::State::DIRTY_BIT_UNPACK_SKIP_ROWS:
+ // TODO(jmadill): split this
+ setPixelUnpackState(state.getUnpackState());
+ break;
+ case gl::State::DIRTY_BIT_UNPACK_SKIP_PIXELS:
+ // TODO(jmadill): split this
+ setPixelUnpackState(state.getUnpackState());
+ break;
+ case gl::State::DIRTY_BIT_UNPACK_BUFFER_BINDING:
+ // TODO(jmadill): split this
+ setPixelUnpackState(state.getUnpackState());
+ break;
+ case gl::State::DIRTY_BIT_PACK_ALIGNMENT:
+ // TODO(jmadill): split this
+ setPixelPackState(state.getPackState());
+ break;
+ case gl::State::DIRTY_BIT_PACK_REVERSE_ROW_ORDER:
+ // TODO(jmadill): split this
+ setPixelPackState(state.getPackState());
+ break;
+ case gl::State::DIRTY_BIT_PACK_ROW_LENGTH:
+ // TODO(jmadill): split this
+ setPixelPackState(state.getPackState());
+ break;
+ case gl::State::DIRTY_BIT_PACK_SKIP_ROWS:
+ // TODO(jmadill): split this
+ setPixelPackState(state.getPackState());
+ break;
+ case gl::State::DIRTY_BIT_PACK_SKIP_PIXELS:
+ // TODO(jmadill): split this
+ setPixelPackState(state.getPackState());
+ break;
+ case gl::State::DIRTY_BIT_PACK_BUFFER_BINDING:
+ // TODO(jmadill): split this
+ setPixelPackState(state.getPackState());
+ break;
+ case gl::State::DIRTY_BIT_DITHER_ENABLED:
+ setDitherEnabled(state.isDitherEnabled());
+ break;
+ case gl::State::DIRTY_BIT_GENERATE_MIPMAP_HINT:
+ // TODO(jmadill): implement this
+ break;
+ case gl::State::DIRTY_BIT_SHADER_DERIVATIVE_HINT:
+ // TODO(jmadill): implement this
+ break;
+ case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
+ // TODO(jmadill): implement this
+ break;
+ case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
+ // TODO(jmadill): implement this
+ break;
+ case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
+ // TODO(jmadill): implement this
+ break;
+ case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
+ // TODO(jmadill): implement this
+ break;
+ case gl::State::DIRTY_BIT_PROGRAM_BINDING:
+ // TODO(jmadill): implement this
+ break;
+ case gl::State::DIRTY_BIT_MULTISAMPLING:
+ setMultisamplingStateEnabled(state.isMultisamplingEnabled());
+ break;
+ case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
+ setSampleAlphaToOneStateEnabled(state.isSampleAlphaToOneEnabled());
+ case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
+ setCoverageModulation(state.getCoverageModulation());
+ break;
+ case gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_MV:
+ setPathRenderingModelViewMatrix(
+ state.getPathRenderingMatrix(GL_PATH_MODELVIEW_MATRIX_CHROMIUM));
+ break;
+ case gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ:
+ setPathRenderingProjectionMatrix(
+ state.getPathRenderingMatrix(GL_PATH_PROJECTION_MATRIX_CHROMIUM));
+ break;
+ case gl::State::DIRTY_BIT_PATH_RENDERING_STENCIL_STATE:
+ setPathRenderingStencilState(state.getPathStencilFunc(), state.getPathStencilRef(),
+ state.getPathStencilMask());
+ break;
+ case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB:
+ setFramebufferSRGBEnabledForFramebuffer(
+ state.getFramebufferSRGB(),
+ GetImplAs<FramebufferGL>(state.getDrawFramebuffer()));
+ break;
+ default:
+ {
+ ASSERT(dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 &&
+ dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX);
+ size_t attribIndex =
+ static_cast<size_t>(dirtyBit) - gl::State::DIRTY_BIT_CURRENT_VALUE_0;
+ setAttributeCurrentData(attribIndex, state.getVertexAttribCurrentValue(
+ static_cast<unsigned int>(attribIndex)));
+ break;
+ }
+ }
+
+ mLocalDirtyBits.reset();
+ }
+}
+
+void StateManagerGL::setFramebufferSRGBEnabled(bool enabled)
+{
+ if (mFramebufferSRGBEnabled != enabled)
+ {
+ mFramebufferSRGBEnabled = enabled;
+ if (mFramebufferSRGBEnabled)
+ {
+ mFunctions->enable(GL_FRAMEBUFFER_SRGB);
+ }
+ else
+ {
+ mFunctions->disable(GL_FRAMEBUFFER_SRGB);
+ }
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
+ }
+}
+
+void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(bool enabled,
+ const FramebufferGL *framebuffer)
+{
+ if (mFunctions->standard == STANDARD_GL_DESKTOP && framebuffer->isDefault())
+ {
+ // Obey the framebuffer sRGB state for blending on all framebuffers except the default
+ // framebuffer on Desktop OpenGL.
+ // When SRGB blending is enabled, only SRGB capable formats will use it but the default
+ // framebuffer will always use it if it is enabled.
+ // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
+ setFramebufferSRGBEnabled(false);
+ }
+ else
+ {
+ setFramebufferSRGBEnabled(enabled);
+ }
+}
+
+void StateManagerGL::setDitherEnabled(bool enabled)
+{
+ if (mDitherEnabled != enabled)
+ {
+ mDitherEnabled = enabled;
+ if (mDitherEnabled)
+ {
+ mFunctions->enable(GL_DITHER);
+ }
+ else
+ {
+ mFunctions->disable(GL_DITHER);
+ }
+ }
+}
+
+void StateManagerGL::setMultisamplingStateEnabled(bool enabled)
+{
+ if (mMultisamplingEnabled != enabled)
+ {
+ mMultisamplingEnabled = enabled;
+ if (mMultisamplingEnabled)
+ {
+ mFunctions->enable(GL_MULTISAMPLE_EXT);
+ }
+ else
+ {
+ mFunctions->disable(GL_MULTISAMPLE_EXT);
+ }
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_MULTISAMPLING);
+ }
+}
+
+void StateManagerGL::setSampleAlphaToOneStateEnabled(bool enabled)
+{
+ if (mSampleAlphaToOneEnabled != enabled)
+ {
+ mSampleAlphaToOneEnabled = enabled;
+ if (mSampleAlphaToOneEnabled)
+ {
+ mFunctions->enable(GL_SAMPLE_ALPHA_TO_ONE);
+ }
+ else
+ {
+ mFunctions->disable(GL_SAMPLE_ALPHA_TO_ONE);
+ }
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
+ }
+}
+
+void StateManagerGL::setCoverageModulation(GLenum components)
+{
+ if (mCoverageModulation != components)
+ {
+ mCoverageModulation = components;
+ mFunctions->coverageModulationNV(components);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_COVERAGE_MODULATION);
+ }
+}
+
+void StateManagerGL::setPathRenderingModelViewMatrix(const GLfloat *m)
+{
+ if (memcmp(mPathMatrixMV, m, sizeof(mPathMatrixMV)) != 0)
+ {
+ memcpy(mPathMatrixMV, m, sizeof(mPathMatrixMV));
+ mFunctions->matrixLoadEXT(GL_PATH_MODELVIEW_CHROMIUM, m);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_MV);
+ }
+}
+
+void StateManagerGL::setPathRenderingProjectionMatrix(const GLfloat *m)
+{
+ if (memcmp(mPathMatrixProj, m, sizeof(mPathMatrixProj)) != 0)
+ {
+ memcpy(mPathMatrixProj, m, sizeof(mPathMatrixProj));
+ mFunctions->matrixLoadEXT(GL_PATH_PROJECTION_CHROMIUM, m);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ);
+ }
+}
+
+void StateManagerGL::setPathRenderingStencilState(GLenum func, GLint ref, GLuint mask)
+{
+ if (func != mPathStencilFunc || ref != mPathStencilRef || mask != mPathStencilMask)
+ {
+ mPathStencilFunc = func;
+ mPathStencilRef = ref;
+ mPathStencilMask = mask;
+ mFunctions->pathStencilFuncNV(func, ref, mask);
+
+ mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING_STENCIL_STATE);
+ }
+}
+
+void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
+{
+ if (mTextureCubemapSeamlessEnabled != enabled)
+ {
+ mTextureCubemapSeamlessEnabled = enabled;
+ if (mTextureCubemapSeamlessEnabled)
+ {
+ mFunctions->enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+ }
+ else
+ {
+ mFunctions->disable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+ }
+ }
+}
+
+GLuint StateManagerGL::getBoundBuffer(GLenum type)
+{
+ ASSERT(mBuffers.find(type) != mBuffers.end());
+ return mBuffers[type];
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.h b/gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.h
new file mode 100755
index 000000000..3c8c5389f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.h
@@ -0,0 +1,290 @@
+//
+// Copyright (c) 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.
+//
+
+// StateManagerGL.h: Defines a class for caching applied OpenGL state
+
+#ifndef LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_
+#define LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_
+
+#include "common/debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/State.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/gl/functionsgl_typedefs.h"
+
+#include <map>
+
+namespace gl
+{
+struct Caps;
+class ContextState;
+class State;
+}
+
+namespace rx
+{
+
+class FramebufferGL;
+class FunctionsGL;
+class TransformFeedbackGL;
+class QueryGL;
+
+class StateManagerGL final : angle::NonCopyable
+{
+ public:
+ StateManagerGL(const FunctionsGL *functions, const gl::Caps &rendererCaps);
+
+ void deleteProgram(GLuint program);
+ void deleteVertexArray(GLuint vao);
+ void deleteTexture(GLuint texture);
+ void deleteSampler(GLuint sampler);
+ void deleteBuffer(GLuint buffer);
+ void deleteFramebuffer(GLuint fbo);
+ void deleteRenderbuffer(GLuint rbo);
+ void deleteTransformFeedback(GLuint transformFeedback);
+ void deleteQuery(GLuint query);
+
+ void useProgram(GLuint program);
+ void forceUseProgram(GLuint program);
+ void bindVertexArray(GLuint vao, GLuint elementArrayBuffer);
+ void bindBuffer(GLenum type, GLuint buffer);
+ void bindBufferBase(GLenum type, size_t index, GLuint buffer);
+ void bindBufferRange(GLenum type, size_t index, GLuint buffer, size_t offset, size_t size);
+ void activeTexture(size_t unit);
+ void bindTexture(GLenum type, GLuint texture);
+ void bindSampler(size_t unit, GLuint sampler);
+ void bindFramebuffer(GLenum type, GLuint framebuffer);
+ void bindRenderbuffer(GLenum type, GLuint renderbuffer);
+ void bindTransformFeedback(GLenum type, GLuint transformFeedback);
+ void beginQuery(GLenum type, GLuint query);
+ void endQuery(GLenum type, GLuint query);
+ void onBeginQuery(QueryGL *query);
+
+ void setAttributeCurrentData(size_t index, const gl::VertexAttribCurrentValueData &data);
+
+ void setScissorTestEnabled(bool enabled);
+ void setScissor(const gl::Rectangle &scissor);
+
+ void setViewport(const gl::Rectangle &viewport);
+ void setDepthRange(float near, float far);
+
+ void setBlendEnabled(bool enabled);
+ void setBlendColor(const gl::ColorF &blendColor);
+ void setBlendFuncs(GLenum sourceBlendRGB,
+ GLenum destBlendRGB,
+ GLenum sourceBlendAlpha,
+ GLenum destBlendAlpha);
+ void setBlendEquations(GLenum blendEquationRGB, GLenum blendEquationAlpha);
+ void setColorMask(bool red, bool green, bool blue, bool alpha);
+ void setSampleAlphaToCoverageEnabled(bool enabled);
+ void setSampleCoverageEnabled(bool enabled);
+ void setSampleCoverage(float value, bool invert);
+
+ void setDepthTestEnabled(bool enabled);
+ void setDepthFunc(GLenum depthFunc);
+ void setDepthMask(bool mask);
+ void setStencilTestEnabled(bool enabled);
+ void setStencilFrontWritemask(GLuint mask);
+ void setStencilBackWritemask(GLuint mask);
+ void setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask);
+ void setStencilBackFuncs(GLenum func, GLint ref, GLuint mask);
+ void setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass);
+ void setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass);
+
+ void setCullFaceEnabled(bool enabled);
+ void setCullFace(GLenum cullFace);
+ void setFrontFace(GLenum frontFace);
+ void setPolygonOffsetFillEnabled(bool enabled);
+ void setPolygonOffset(float factor, float units);
+ void setRasterizerDiscardEnabled(bool enabled);
+ void setLineWidth(float width);
+
+ void setPrimitiveRestartEnabled(bool enabled);
+
+ void setClearColor(const gl::ColorF &clearColor);
+ void setClearDepth(float clearDepth);
+ void setClearStencil(GLint clearStencil);
+
+ void setPixelUnpackState(const gl::PixelUnpackState &unpack);
+ void setPixelUnpackState(GLint alignment,
+ GLint rowLength,
+ GLint skipRows,
+ GLint skipPixels,
+ GLint imageHeight,
+ GLint skipImages,
+ GLuint unpackBuffer);
+ void setPixelPackState(const gl::PixelPackState &pack);
+ void setPixelPackState(GLint alignment,
+ GLint rowLength,
+ GLint skipRows,
+ GLint skipPixels,
+ GLuint packBuffer);
+
+ void setFramebufferSRGBEnabled(bool enabled);
+ void setFramebufferSRGBEnabledForFramebuffer(bool enabled, const FramebufferGL *framebuffer);
+
+ void setDitherEnabled(bool enabled);
+
+ void setMultisamplingStateEnabled(bool enabled);
+ void setSampleAlphaToOneStateEnabled(bool enabled);
+
+ void setCoverageModulation(GLenum components);
+
+ void setPathRenderingModelViewMatrix(const GLfloat *m);
+ void setPathRenderingProjectionMatrix(const GLfloat *m);
+ void setPathRenderingStencilState(GLenum func, GLint ref, GLuint mask);
+
+ void onDeleteQueryObject(QueryGL *query);
+
+ gl::Error setDrawArraysState(const gl::ContextState &data,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount);
+ gl::Error setDrawElementsState(const gl::ContextState &data,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instanceCount,
+ const GLvoid **outIndices);
+
+ gl::Error pauseTransformFeedback(const gl::ContextState &data);
+ gl::Error onMakeCurrent(const gl::ContextState &data);
+
+ void syncState(const gl::State &state, const gl::State::DirtyBits &glDirtyBits);
+
+ GLuint getBoundBuffer(GLenum type);
+
+ private:
+ gl::Error setGenericDrawState(const gl::ContextState &data);
+
+ void setTextureCubemapSeamlessEnabled(bool enabled);
+
+ const FunctionsGL *mFunctions;
+
+ GLuint mProgram;
+
+ GLuint mVAO;
+ std::vector<gl::VertexAttribCurrentValueData> mVertexAttribCurrentValues;
+
+ std::map<GLenum, GLuint> mBuffers;
+
+ struct IndexedBufferBinding
+ {
+ IndexedBufferBinding();
+
+ size_t offset;
+ size_t size;
+ GLuint buffer;
+ };
+ std::map<GLenum, std::vector<IndexedBufferBinding>> mIndexedBuffers;
+
+ size_t mTextureUnitIndex;
+ std::map<GLenum, std::vector<GLuint>> mTextures;
+ std::vector<GLuint> mSamplers;
+
+ GLuint mTransformFeedback;
+
+ std::map<GLenum, GLuint> mQueries;
+
+ TransformFeedbackGL *mPrevDrawTransformFeedback;
+ std::set<QueryGL *> mCurrentQueries;
+ uintptr_t mPrevDrawContext;
+
+ GLint mUnpackAlignment;
+ GLint mUnpackRowLength;
+ GLint mUnpackSkipRows;
+ GLint mUnpackSkipPixels;
+ GLint mUnpackImageHeight;
+ GLint mUnpackSkipImages;
+
+ GLint mPackAlignment;
+ GLint mPackRowLength;
+ GLint mPackSkipRows;
+ GLint mPackSkipPixels;
+
+ // TODO(jmadill): Convert to std::array when available
+ std::vector<GLenum> mFramebuffers;
+ GLuint mRenderbuffer;
+
+ bool mScissorTestEnabled;
+ gl::Rectangle mScissor;
+
+ gl::Rectangle mViewport;
+ float mNear;
+ float mFar;
+
+ bool mBlendEnabled;
+ gl::ColorF mBlendColor;
+ GLenum mSourceBlendRGB;
+ GLenum mDestBlendRGB;
+ GLenum mSourceBlendAlpha;
+ GLenum mDestBlendAlpha;
+ GLenum mBlendEquationRGB;
+ GLenum mBlendEquationAlpha;
+ bool mColorMaskRed;
+ bool mColorMaskGreen;
+ bool mColorMaskBlue;
+ bool mColorMaskAlpha;
+ bool mSampleAlphaToCoverageEnabled;
+ bool mSampleCoverageEnabled;
+ float mSampleCoverageValue;
+ bool mSampleCoverageInvert;
+
+ bool mDepthTestEnabled;
+ GLenum mDepthFunc;
+ bool mDepthMask;
+ bool mStencilTestEnabled;
+ GLenum mStencilFrontFunc;
+ GLint mStencilFrontRef;
+ GLuint mStencilFrontValueMask;
+ GLenum mStencilFrontStencilFailOp;
+ GLenum mStencilFrontStencilPassDepthFailOp;
+ GLenum mStencilFrontStencilPassDepthPassOp;
+ GLuint mStencilFrontWritemask;
+ GLenum mStencilBackFunc;
+ GLint mStencilBackRef;
+ GLuint mStencilBackValueMask;
+ GLenum mStencilBackStencilFailOp;
+ GLenum mStencilBackStencilPassDepthFailOp;
+ GLenum mStencilBackStencilPassDepthPassOp;
+ GLuint mStencilBackWritemask;
+
+ bool mCullFaceEnabled;
+ GLenum mCullFace;
+ GLenum mFrontFace;
+ bool mPolygonOffsetFillEnabled;
+ GLfloat mPolygonOffsetFactor;
+ GLfloat mPolygonOffsetUnits;
+ bool mRasterizerDiscardEnabled;
+ float mLineWidth;
+
+ bool mPrimitiveRestartEnabled;
+
+ gl::ColorF mClearColor;
+ float mClearDepth;
+ GLint mClearStencil;
+
+ bool mFramebufferSRGBEnabled;
+ bool mDitherEnabled;
+ bool mTextureCubemapSeamlessEnabled;
+
+ bool mMultisamplingEnabled;
+ bool mSampleAlphaToOneEnabled;
+
+ GLenum mCoverageModulation;
+
+ GLfloat mPathMatrixMV[16];
+ GLfloat mPathMatrixProj[16];
+ GLenum mPathStencilFunc;
+ GLint mPathStencilRef;
+ GLuint mPathStencilMask;
+
+ gl::State::DirtyBits mLocalDirtyBits;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.cpp
new file mode 100755
index 000000000..a1f0abba7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.cpp
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 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.
+//
+
+// SurfaceGL.cpp: OpenGL implementation of egl::Surface
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+
+namespace rx
+{
+
+SurfaceGL::SurfaceGL(const egl::SurfaceState &state, RendererGL *renderer)
+ : SurfaceImpl(state), mRenderer(renderer)
+{
+}
+
+SurfaceGL::~SurfaceGL()
+{
+}
+
+FramebufferImpl *SurfaceGL::createDefaultFramebuffer(const gl::FramebufferState &data)
+{
+ return new FramebufferGL(data, mRenderer->getFunctions(), mRenderer->getStateManager(),
+ mRenderer->getWorkarounds(), mRenderer->getBlitter(), true);
+}
+
+egl::Error SurfaceGL::unMakeCurrent()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.h b/gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.h
new file mode 100755
index 000000000..681c365d2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/SurfaceGL.h
@@ -0,0 +1,36 @@
+//
+// 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.
+//
+
+// SurfaceGL.h: Defines the class interface for SurfaceGL.
+
+#ifndef LIBANGLE_RENDERER_GL_SURFACEGL_H_
+#define LIBANGLE_RENDERER_GL_SURFACEGL_H_
+
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+namespace rx
+{
+
+class RendererGL;
+
+class SurfaceGL : public SurfaceImpl
+{
+ public:
+ SurfaceGL(const egl::SurfaceState &state, RendererGL *renderer);
+ ~SurfaceGL() override;
+
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
+
+ virtual egl::Error makeCurrent() = 0;
+ virtual egl::Error unMakeCurrent();
+
+ private:
+ RendererGL *mRenderer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_SURFACEGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/TextureGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/TextureGL.cpp
new file mode 100755
index 000000000..589580505
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/TextureGL.cpp
@@ -0,0 +1,1039 @@
+//
+// 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.
+//
+
+// TextureGL.cpp: Implements the class methods for TextureGL.
+
+#include "libANGLE/renderer/gl/TextureGL.h"
+
+#include "common/BitSetIterator.h"
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/State.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/gl/BlitGL.h"
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "libANGLE/renderer/gl/formatutilsgl.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+using angle::CheckedNumeric;
+
+namespace rx
+{
+
+namespace
+{
+
+bool UseTexImage2D(GLenum textureType)
+{
+ return textureType == GL_TEXTURE_2D || textureType == GL_TEXTURE_CUBE_MAP;
+}
+
+bool UseTexImage3D(GLenum textureType)
+{
+ return textureType == GL_TEXTURE_2D_ARRAY || textureType == GL_TEXTURE_3D;
+}
+
+bool CompatibleTextureTarget(GLenum textureType, GLenum textureTarget)
+{
+ if (textureType != GL_TEXTURE_CUBE_MAP)
+ {
+ return textureType == textureTarget;
+ }
+ else
+ {
+ return gl::IsCubeMapTextureTarget(textureTarget);
+ }
+}
+
+bool IsLUMAFormat(GLenum format)
+{
+ return format == GL_LUMINANCE || format == GL_ALPHA || format == GL_LUMINANCE_ALPHA;
+}
+
+LUMAWorkaroundGL GetLUMAWorkaroundInfo(const gl::InternalFormat &originalFormatInfo,
+ GLenum destinationFormat)
+{
+ if (IsLUMAFormat(originalFormatInfo.format))
+ {
+ const gl::InternalFormat &destinationFormatInfo =
+ gl::GetInternalFormatInfo(destinationFormat);
+ return LUMAWorkaroundGL(!IsLUMAFormat(destinationFormatInfo.format),
+ destinationFormatInfo.format);
+ }
+ else
+ {
+ return LUMAWorkaroundGL(false, GL_NONE);
+ }
+}
+
+bool IsDepthStencilFormat(GLenum format)
+{
+ return format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL;
+}
+
+bool GetDepthStencilWorkaround(const gl::InternalFormat &originalFormatInfo)
+{
+ return IsDepthStencilFormat(originalFormatInfo.format);
+}
+
+LevelInfoGL GetLevelInfo(GLenum originalFormat, GLenum destinationFormat)
+{
+ const gl::InternalFormat &originalFormatInfo = gl::GetInternalFormatInfo(originalFormat);
+ return LevelInfoGL(originalFormat, GetDepthStencilWorkaround(originalFormatInfo),
+ GetLUMAWorkaroundInfo(originalFormatInfo, destinationFormat));
+}
+
+gl::Texture::DirtyBits GetLevelWorkaroundDirtyBits()
+{
+ gl::Texture::DirtyBits bits;
+ bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_RED);
+ bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_GREEN);
+ bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE);
+ bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA);
+ return bits;
+}
+
+} // anonymous namespace
+
+LUMAWorkaroundGL::LUMAWorkaroundGL() : LUMAWorkaroundGL(false, GL_NONE)
+{
+}
+
+LUMAWorkaroundGL::LUMAWorkaroundGL(bool enabled_, GLenum workaroundFormat_)
+ : enabled(enabled_), workaroundFormat(workaroundFormat_)
+{
+}
+
+LevelInfoGL::LevelInfoGL() : LevelInfoGL(GL_NONE, false, LUMAWorkaroundGL())
+{
+}
+
+LevelInfoGL::LevelInfoGL(GLenum sourceFormat_,
+ bool depthStencilWorkaround_,
+ const LUMAWorkaroundGL &lumaWorkaround_)
+ : sourceFormat(sourceFormat_),
+ depthStencilWorkaround(depthStencilWorkaround_),
+ lumaWorkaround(lumaWorkaround_)
+{
+}
+
+TextureGL::TextureGL(const gl::TextureState &state,
+ const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ StateManagerGL *stateManager,
+ BlitGL *blitter)
+ : TextureImpl(state),
+ mFunctions(functions),
+ mWorkarounds(workarounds),
+ mStateManager(stateManager),
+ mBlitter(blitter),
+ mLevelInfo(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1),
+ mAppliedTextureState(state.mTarget),
+ mTextureID(0)
+{
+ ASSERT(mFunctions);
+ ASSERT(mStateManager);
+ ASSERT(mBlitter);
+
+ mFunctions->genTextures(1, &mTextureID);
+ mStateManager->bindTexture(mState.mTarget, mTextureID);
+}
+
+TextureGL::~TextureGL()
+{
+ mStateManager->deleteTexture(mTextureID);
+ mTextureID = 0;
+}
+
+gl::Error TextureGL::setImage(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ if (mWorkarounds.unpackOverlappingRowsSeparatelyUnpackBuffer && unpack.pixelBuffer.get() &&
+ unpack.rowLength != 0 && unpack.rowLength < size.width)
+ {
+ // The rows overlap in unpack memory. Upload the texture row by row to work around
+ // driver bug.
+ reserveTexImageToBeFilled(target, level, internalFormat, size, format, type);
+
+ if (size.width == 0 || size.height == 0 || size.depth == 0)
+ {
+ return gl::NoError();
+ }
+
+ gl::Box area(0, 0, 0, size.width, size.height, size.depth);
+ return setSubImageRowByRowWorkaround(target, level, area, format, type, unpack, pixels);
+ }
+
+ if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion)
+ {
+ bool apply;
+ ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, unpack, format, type,
+ UseTexImage3D(mState.mTarget), pixels),
+ apply);
+
+ // The driver will think the pixel buffer doesn't have enough data, work around this bug
+ // by uploading the last row (and last level if 3D) separately.
+ if (apply)
+ {
+ reserveTexImageToBeFilled(target, level, internalFormat, size, format, type);
+
+ if (size.width == 0 || size.height == 0 || size.depth == 0)
+ {
+ return gl::NoError();
+ }
+
+ gl::Box area(0, 0, 0, size.width, size.height, size.depth);
+ return setSubImagePaddingWorkaround(target, level, area, format, type, unpack, pixels);
+ }
+ }
+
+ setImageHelper(target, level, internalFormat, size, format, type, pixels);
+
+ return gl::NoError();
+}
+
+void TextureGL::setImageHelper(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const uint8_t *pixels)
+{
+ ASSERT(CompatibleTextureTarget(mState.mTarget, target));
+
+ nativegl::TexImageFormat texImageFormat =
+ nativegl::GetTexImageFormat(mFunctions, mWorkarounds, internalFormat, format, type);
+
+ mStateManager->bindTexture(mState.mTarget, mTextureID);
+
+ if (UseTexImage2D(mState.mTarget))
+ {
+ ASSERT(size.depth == 1);
+ mFunctions->texImage2D(target, static_cast<GLint>(level), texImageFormat.internalFormat,
+ size.width, size.height, 0, texImageFormat.format,
+ texImageFormat.type, pixels);
+ }
+ else if (UseTexImage3D(mState.mTarget))
+ {
+ mFunctions->texImage3D(target, static_cast<GLint>(level), texImageFormat.internalFormat,
+ size.width, size.height, size.depth, 0, texImageFormat.format,
+ texImageFormat.type, pixels);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ setLevelInfo(level, 1, GetLevelInfo(internalFormat, texImageFormat.internalFormat));
+}
+
+void TextureGL::reserveTexImageToBeFilled(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type)
+{
+ GLuint unpackBuffer = mStateManager->getBoundBuffer(GL_PIXEL_UNPACK_BUFFER);
+ mStateManager->bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ gl::PixelUnpackState unpack;
+ setImageHelper(target, level, internalFormat, size, format, type, nullptr);
+ mStateManager->bindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
+}
+
+gl::Error TextureGL::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
+{
+ ASSERT(CompatibleTextureTarget(mState.mTarget, target));
+
+ nativegl::TexSubImageFormat texSubImageFormat =
+ nativegl::GetTexSubImageFormat(mFunctions, mWorkarounds, format, type);
+
+ ASSERT(mLevelInfo[level].lumaWorkaround.enabled ==
+ GetLevelInfo(format, texSubImageFormat.format).lumaWorkaround.enabled);
+
+ mStateManager->bindTexture(mState.mTarget, mTextureID);
+ if (mWorkarounds.unpackOverlappingRowsSeparatelyUnpackBuffer && unpack.pixelBuffer.get() &&
+ unpack.rowLength != 0 && unpack.rowLength < area.width)
+ {
+ return setSubImageRowByRowWorkaround(target, level, area, format, type, unpack, pixels);
+ }
+
+ if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion)
+ {
+ gl::Extents size(area.width, area.height, area.depth);
+
+ bool apply;
+ ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, unpack, format, type,
+ UseTexImage3D(mState.mTarget), pixels),
+ apply);
+
+ // The driver will think the pixel buffer doesn't have enough data, work around this bug
+ // by uploading the last row (and last level if 3D) separately.
+ if (apply)
+ {
+ return setSubImagePaddingWorkaround(target, level, area, format, type, unpack, pixels);
+ }
+ }
+
+ if (UseTexImage2D(mState.mTarget))
+ {
+ ASSERT(area.z == 0 && area.depth == 1);
+ mFunctions->texSubImage2D(target, static_cast<GLint>(level), area.x, area.y, area.width,
+ area.height, texSubImageFormat.format, texSubImageFormat.type,
+ pixels);
+ }
+ else
+ {
+ ASSERT(UseTexImage3D(mState.mTarget));
+ mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, area.y, area.z,
+ area.width, area.height, area.depth, texSubImageFormat.format,
+ texSubImageFormat.type, pixels);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureGL::setSubImageRowByRowWorkaround(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ gl::PixelUnpackState directUnpack;
+ directUnpack.pixelBuffer = unpack.pixelBuffer;
+ directUnpack.alignment = 1;
+ mStateManager->setPixelUnpackState(directUnpack);
+ directUnpack.pixelBuffer.set(nullptr);
+
+ const gl::InternalFormat &glFormat =
+ gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
+ GLuint rowBytes = 0;
+ ANGLE_TRY_RESULT(glFormat.computeRowPitch(area.width, unpack.alignment, unpack.rowLength),
+ rowBytes);
+ GLuint imageBytes = 0;
+ ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(area.height, unpack.imageHeight, rowBytes),
+ imageBytes);
+ bool useTexImage3D = UseTexImage3D(mState.mTarget);
+ GLuint skipBytes = 0;
+ ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D),
+ skipBytes);
+
+ const uint8_t *pixelsWithSkip = pixels + skipBytes;
+ if (useTexImage3D)
+ {
+ for (GLint image = 0; image < area.depth; ++image)
+ {
+ GLint imageByteOffset = image * imageBytes;
+ for (GLint row = 0; row < area.height; ++row)
+ {
+ GLint byteOffset = imageByteOffset + row * rowBytes;
+ const GLubyte *rowPixels = pixelsWithSkip + byteOffset;
+ mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, row + area.y,
+ image + area.z, area.width, 1, 1, format, type,
+ rowPixels);
+ }
+ }
+ }
+ else
+ {
+ ASSERT(UseTexImage2D(mState.mTarget));
+ for (GLint row = 0; row < area.height; ++row)
+ {
+ GLint byteOffset = row * rowBytes;
+ const GLubyte *rowPixels = pixelsWithSkip + byteOffset;
+ mFunctions->texSubImage2D(target, static_cast<GLint>(level), area.x, row + area.y,
+ area.width, 1, format, type, rowPixels);
+ }
+ }
+ return gl::NoError();
+}
+
+gl::Error TextureGL::setSubImagePaddingWorkaround(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ const gl::InternalFormat &glFormat =
+ gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
+ GLuint rowBytes = 0;
+ ANGLE_TRY_RESULT(glFormat.computeRowPitch(area.width, unpack.alignment, unpack.rowLength),
+ rowBytes);
+ GLuint imageBytes = 0;
+ ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(area.height, unpack.imageHeight, rowBytes),
+ imageBytes);
+ bool useTexImage3D = UseTexImage3D(mState.mTarget);
+ GLuint skipBytes = 0;
+ ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D),
+ skipBytes);
+
+ gl::PixelUnpackState directUnpack;
+ directUnpack.pixelBuffer = unpack.pixelBuffer;
+ directUnpack.alignment = 1;
+
+ if (useTexImage3D)
+ {
+ // Upload all but the last slice
+ if (area.depth > 1)
+ {
+ mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, area.y, area.z,
+ area.width, area.height, area.depth - 1, format, type,
+ pixels);
+ }
+
+ // Upload the last slice but its last row
+ if (area.height > 1)
+ {
+ // Do not include skipBytes in the last image pixel start offset as it will be done by
+ // the driver
+ GLint lastImageOffset = (area.depth - 1) * imageBytes;
+ const GLubyte *lastImagePixels = pixels + lastImageOffset;
+ mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x, area.y,
+ area.z + area.depth - 1, area.width, area.height - 1, 1,
+ format, type, lastImagePixels);
+ }
+
+ // Upload the last row of the last slice "manually"
+ mStateManager->setPixelUnpackState(directUnpack);
+
+ GLint lastRowOffset =
+ skipBytes + (area.depth - 1) * imageBytes + (area.height - 1) * rowBytes;
+ const GLubyte *lastRowPixels = pixels + lastRowOffset;
+ mFunctions->texSubImage3D(target, static_cast<GLint>(level), area.x,
+ area.y + area.height - 1, area.z + area.depth - 1, area.width, 1,
+ 1, format, type, lastRowPixels);
+ }
+ else
+ {
+ ASSERT(UseTexImage2D(mState.mTarget));
+
+ // Upload all but the last row
+ if (area.height > 1)
+ {
+ mFunctions->texSubImage2D(target, static_cast<GLint>(level), area.x, area.y, area.width,
+ area.height - 1, format, type, pixels);
+ }
+
+ // Upload the last row "manually"
+ mStateManager->setPixelUnpackState(directUnpack);
+
+ GLint lastRowOffset = skipBytes + (area.height - 1) * rowBytes;
+ const GLubyte *lastRowPixels = pixels + lastRowOffset;
+ mFunctions->texSubImage2D(target, static_cast<GLint>(level), area.x,
+ area.y + area.height - 1, area.width, 1, format, type,
+ lastRowPixels);
+ }
+
+ directUnpack.pixelBuffer.set(nullptr);
+
+ return gl::NoError();
+}
+
+gl::Error TextureGL::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
+{
+ ASSERT(CompatibleTextureTarget(mState.mTarget, target));
+
+ nativegl::CompressedTexImageFormat compressedTexImageFormat =
+ nativegl::GetCompressedTexImageFormat(mFunctions, mWorkarounds, internalFormat);
+
+ mStateManager->bindTexture(mState.mTarget, mTextureID);
+ if (UseTexImage2D(mState.mTarget))
+ {
+ ASSERT(size.depth == 1);
+ mFunctions->compressedTexImage2D(target, static_cast<GLint>(level),
+ compressedTexImageFormat.internalFormat, size.width,
+ size.height, 0, static_cast<GLsizei>(imageSize), pixels);
+ }
+ else if (UseTexImage3D(mState.mTarget))
+ {
+ mFunctions->compressedTexImage3D(
+ target, static_cast<GLint>(level), compressedTexImageFormat.internalFormat, size.width,
+ size.height, size.depth, 0, static_cast<GLsizei>(imageSize), pixels);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ setLevelInfo(level, 1, GetLevelInfo(internalFormat, compressedTexImageFormat.internalFormat));
+ ASSERT(!mLevelInfo[level].lumaWorkaround.enabled);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureGL::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
+{
+ ASSERT(CompatibleTextureTarget(mState.mTarget, target));
+
+ nativegl::CompressedTexSubImageFormat compressedTexSubImageFormat =
+ nativegl::GetCompressedSubTexImageFormat(mFunctions, mWorkarounds, format);
+
+ mStateManager->bindTexture(mState.mTarget, mTextureID);
+ if (UseTexImage2D(mState.mTarget))
+ {
+ ASSERT(area.z == 0 && area.depth == 1);
+ mFunctions->compressedTexSubImage2D(
+ target, static_cast<GLint>(level), area.x, area.y, area.width, area.height,
+ compressedTexSubImageFormat.format, static_cast<GLsizei>(imageSize), pixels);
+ }
+ else if (UseTexImage3D(mState.mTarget))
+ {
+ mFunctions->compressedTexSubImage3D(target, static_cast<GLint>(level), area.x, area.y,
+ area.z, area.width, area.height, area.depth,
+ compressedTexSubImageFormat.format,
+ static_cast<GLsizei>(imageSize), pixels);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ ASSERT(!mLevelInfo[level].lumaWorkaround.enabled &&
+ !GetLevelInfo(format, compressedTexSubImageFormat.format).lumaWorkaround.enabled);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureGL::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source)
+{
+ nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat(
+ mFunctions, mWorkarounds, internalFormat, source->getImplementationColorReadType());
+
+ LevelInfoGL levelInfo = GetLevelInfo(internalFormat, copyTexImageFormat.internalFormat);
+ if (levelInfo.lumaWorkaround.enabled)
+ {
+ gl::Error error = mBlitter->copyImageToLUMAWorkaroundTexture(
+ mTextureID, mState.mTarget, target, levelInfo.sourceFormat, level, sourceArea,
+ copyTexImageFormat.internalFormat, source);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ else
+ {
+ const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
+
+ mStateManager->bindTexture(mState.mTarget, mTextureID);
+ mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER,
+ sourceFramebufferGL->getFramebufferID());
+
+ if (UseTexImage2D(mState.mTarget))
+ {
+ mFunctions->copyTexImage2D(target, static_cast<GLint>(level),
+ copyTexImageFormat.internalFormat, sourceArea.x,
+ sourceArea.y, sourceArea.width, sourceArea.height, 0);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+
+ setLevelInfo(level, 1, levelInfo);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureGL::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
+
+ mStateManager->bindTexture(mState.mTarget, mTextureID);
+ mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
+
+ const LevelInfoGL &levelInfo = mLevelInfo[level];
+ if (levelInfo.lumaWorkaround.enabled)
+ {
+ gl::Error error = mBlitter->copySubImageToLUMAWorkaroundTexture(
+ mTextureID, mState.mTarget, target, levelInfo.sourceFormat, level, destOffset,
+ sourceArea, source);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ else
+ {
+ if (UseTexImage2D(mState.mTarget))
+ {
+ ASSERT(destOffset.z == 0);
+ mFunctions->copyTexSubImage2D(target, static_cast<GLint>(level), destOffset.x,
+ destOffset.y, sourceArea.x, sourceArea.y,
+ sourceArea.width, sourceArea.height);
+ }
+ else if (UseTexImage3D(mState.mTarget))
+ {
+ mFunctions->copyTexSubImage3D(target, static_cast<GLint>(level), destOffset.x,
+ destOffset.y, destOffset.z, sourceArea.x, sourceArea.y,
+ sourceArea.width, sourceArea.height);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
+{
+ // TODO: emulate texture storage with TexImage calls if on GL version <4.2 or the
+ // ARB_texture_storage extension is not available.
+
+ nativegl::TexStorageFormat texStorageFormat =
+ nativegl::GetTexStorageFormat(mFunctions, mWorkarounds, internalFormat);
+
+ mStateManager->bindTexture(mState.mTarget, mTextureID);
+ if (UseTexImage2D(mState.mTarget))
+ {
+ ASSERT(size.depth == 1);
+ if (mFunctions->texStorage2D)
+ {
+ mFunctions->texStorage2D(target, static_cast<GLsizei>(levels),
+ texStorageFormat.internalFormat, size.width, size.height);
+ }
+ else
+ {
+ // Make sure no pixel unpack buffer is bound
+ mStateManager->bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
+
+ // Internal format must be sized
+ ASSERT(internalFormatInfo.pixelBytes != 0);
+
+ for (size_t level = 0; level < levels; level++)
+ {
+ gl::Extents levelSize(std::max(size.width >> level, 1),
+ std::max(size.height >> level, 1),
+ 1);
+
+ if (mState.mTarget == GL_TEXTURE_2D)
+ {
+ if (internalFormatInfo.compressed)
+ {
+ GLuint dataSize = 0;
+ ANGLE_TRY_RESULT(internalFormatInfo.computeCompressedImageSize(levelSize),
+ dataSize);
+ mFunctions->compressedTexImage2D(target, static_cast<GLint>(level),
+ texStorageFormat.internalFormat,
+ levelSize.width, levelSize.height, 0,
+ static_cast<GLsizei>(dataSize), nullptr);
+ }
+ else
+ {
+ mFunctions->texImage2D(target, static_cast<GLint>(level),
+ texStorageFormat.internalFormat, levelSize.width,
+ levelSize.height, 0, internalFormatInfo.format,
+ internalFormatInfo.type, nullptr);
+ }
+ }
+ else if (mState.mTarget == GL_TEXTURE_CUBE_MAP)
+ {
+ for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget; face++)
+ {
+ if (internalFormatInfo.compressed)
+ {
+ GLuint dataSize = 0;
+ ANGLE_TRY_RESULT(internalFormatInfo.computeCompressedImageSize(
+ levelSize),
+ dataSize);
+ mFunctions->compressedTexImage2D(
+ face, static_cast<GLint>(level), texStorageFormat.internalFormat,
+ levelSize.width, levelSize.height, 0,
+ static_cast<GLsizei>(dataSize), nullptr);
+ }
+ else
+ {
+ mFunctions->texImage2D(face, static_cast<GLint>(level),
+ texStorageFormat.internalFormat, levelSize.width,
+ levelSize.height, 0, internalFormatInfo.format,
+ internalFormatInfo.type, nullptr);
+ }
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+ }
+ }
+ else if (UseTexImage3D(mState.mTarget))
+ {
+ if (mFunctions->texStorage3D)
+ {
+ mFunctions->texStorage3D(target, static_cast<GLsizei>(levels),
+ texStorageFormat.internalFormat, size.width, size.height,
+ size.depth);
+ }
+ else
+ {
+ // Make sure no pixel unpack buffer is bound
+ mStateManager->bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
+
+ // Internal format must be sized
+ ASSERT(internalFormatInfo.pixelBytes != 0);
+
+ for (GLsizei i = 0; i < static_cast<GLsizei>(levels); i++)
+ {
+ gl::Extents levelSize(
+ std::max(size.width >> i, 1), std::max(size.height >> i, 1),
+ mState.mTarget == GL_TEXTURE_3D ? std::max(size.depth >> i, 1) : size.depth);
+
+ if (internalFormatInfo.compressed)
+ {
+ GLuint dataSize = 0;
+ ANGLE_TRY_RESULT(
+ internalFormatInfo.computeCompressedImageSize(levelSize),
+ dataSize);
+ mFunctions->compressedTexImage3D(target, i, texStorageFormat.internalFormat,
+ levelSize.width, levelSize.height,
+ levelSize.depth, 0,
+ static_cast<GLsizei>(dataSize), nullptr);
+ }
+ else
+ {
+ mFunctions->texImage3D(target, i, texStorageFormat.internalFormat,
+ levelSize.width, levelSize.height, levelSize.depth, 0,
+ internalFormatInfo.format, internalFormatInfo.type,
+ nullptr);
+ }
+ }
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ setLevelInfo(0, levels, GetLevelInfo(internalFormat, texStorageFormat.internalFormat));
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureGL::setImageExternal(GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureGL::generateMipmap()
+{
+ mStateManager->bindTexture(mState.mTarget, mTextureID);
+ mFunctions->generateMipmap(mState.mTarget);
+
+ const GLuint effectiveBaseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+
+ ASSERT(maxLevel < mLevelInfo.size());
+
+ setLevelInfo(effectiveBaseLevel, maxLevel - effectiveBaseLevel, mLevelInfo[effectiveBaseLevel]);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void TextureGL::bindTexImage(egl::Surface *surface)
+{
+ ASSERT(mState.mTarget == GL_TEXTURE_2D);
+
+ // Make sure this texture is bound
+ mStateManager->bindTexture(mState.mTarget, mTextureID);
+
+ setLevelInfo(0, 1, LevelInfoGL());
+}
+
+void TextureGL::releaseTexImage()
+{
+ // Not all Surface implementations reset the size of mip 0 when releasing, do it manually
+ ASSERT(mState.mTarget == GL_TEXTURE_2D);
+
+ mStateManager->bindTexture(mState.mTarget, mTextureID);
+ if (UseTexImage2D(mState.mTarget))
+ {
+ mFunctions->texImage2D(mState.mTarget, 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ nullptr);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+}
+
+gl::Error TextureGL::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+void TextureGL::syncState(const gl::Texture::DirtyBits &dirtyBits)
+{
+ if (dirtyBits.none() && mLocalDirtyBits.none())
+ {
+ return;
+ }
+
+ mStateManager->bindTexture(mState.mTarget, mTextureID);
+
+ if (dirtyBits[gl::Texture::DIRTY_BIT_BASE_LEVEL] || dirtyBits[gl::Texture::DIRTY_BIT_MAX_LEVEL])
+ {
+ // Don't know if the previous base level was using any workarounds, always re-sync the
+ // workaround dirty bits
+ mLocalDirtyBits |= GetLevelWorkaroundDirtyBits();
+ }
+
+ for (auto dirtyBit : angle::IterateBitSet(dirtyBits | mLocalDirtyBits))
+ {
+ switch (dirtyBit)
+ {
+ case gl::Texture::DIRTY_BIT_MIN_FILTER:
+ mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_MIN_FILTER,
+ mState.getSamplerState().minFilter);
+ break;
+ case gl::Texture::DIRTY_BIT_MAG_FILTER:
+ mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_MAG_FILTER,
+ mState.getSamplerState().magFilter);
+ break;
+ case gl::Texture::DIRTY_BIT_WRAP_S:
+ mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_WRAP_S,
+ mState.getSamplerState().wrapS);
+ break;
+ case gl::Texture::DIRTY_BIT_WRAP_T:
+ mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_WRAP_T,
+ mState.getSamplerState().wrapT);
+ break;
+ case gl::Texture::DIRTY_BIT_WRAP_R:
+ mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_WRAP_R,
+ mState.getSamplerState().wrapR);
+ break;
+ case gl::Texture::DIRTY_BIT_MAX_ANISOTROPY:
+ mFunctions->texParameterf(mState.mTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT,
+ mState.getSamplerState().maxAnisotropy);
+ break;
+ case gl::Texture::DIRTY_BIT_MIN_LOD:
+ mFunctions->texParameterf(mState.mTarget, GL_TEXTURE_MIN_LOD,
+ mState.getSamplerState().minLod);
+ break;
+ case gl::Texture::DIRTY_BIT_MAX_LOD:
+ mFunctions->texParameterf(mState.mTarget, GL_TEXTURE_MAX_LOD,
+ mState.getSamplerState().maxLod);
+ break;
+ case gl::Texture::DIRTY_BIT_COMPARE_MODE:
+ mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_COMPARE_MODE,
+ mState.getSamplerState().compareMode);
+ break;
+ case gl::Texture::DIRTY_BIT_COMPARE_FUNC:
+ mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_COMPARE_FUNC,
+ mState.getSamplerState().compareFunc);
+ break;
+ case gl::Texture::DIRTY_BIT_SRGB_DECODE:
+ mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_SRGB_DECODE_EXT,
+ mState.getSamplerState().sRGBDecode);
+ break;
+
+ // Texture state
+ case gl::Texture::DIRTY_BIT_SWIZZLE_RED:
+ syncTextureStateSwizzle(mFunctions, GL_TEXTURE_SWIZZLE_R,
+ mState.getSwizzleState().swizzleRed);
+ break;
+ case gl::Texture::DIRTY_BIT_SWIZZLE_GREEN:
+ syncTextureStateSwizzle(mFunctions, GL_TEXTURE_SWIZZLE_G,
+ mState.getSwizzleState().swizzleGreen);
+ break;
+ case gl::Texture::DIRTY_BIT_SWIZZLE_BLUE:
+ syncTextureStateSwizzle(mFunctions, GL_TEXTURE_SWIZZLE_B,
+ mState.getSwizzleState().swizzleBlue);
+ break;
+ case gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA:
+ syncTextureStateSwizzle(mFunctions, GL_TEXTURE_SWIZZLE_A,
+ mState.getSwizzleState().swizzleAlpha);
+ break;
+ case gl::Texture::DIRTY_BIT_BASE_LEVEL:
+ mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_BASE_LEVEL,
+ mState.getEffectiveBaseLevel());
+ break;
+ case gl::Texture::DIRTY_BIT_MAX_LEVEL:
+ mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_MAX_LEVEL,
+ mState.getEffectiveMaxLevel());
+ break;
+ case gl::Texture::DIRTY_BIT_USAGE:
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ mLocalDirtyBits.reset();
+}
+
+bool TextureGL::hasAnyDirtyBit() const
+{
+ return mLocalDirtyBits.any();
+}
+
+void TextureGL::syncTextureStateSwizzle(const FunctionsGL *functions, GLenum name, GLenum value)
+{
+ const LevelInfoGL &levelInfo = mLevelInfo[mState.getEffectiveBaseLevel()];
+ GLenum resultSwizzle = value;
+ if (levelInfo.lumaWorkaround.enabled || levelInfo.depthStencilWorkaround)
+ {
+ if (levelInfo.lumaWorkaround.enabled)
+ {
+ switch (value)
+ {
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ if (levelInfo.sourceFormat == GL_LUMINANCE ||
+ levelInfo.sourceFormat == GL_LUMINANCE_ALPHA)
+ {
+ // Texture is backed by a RED or RG texture, point all color channels at the red
+ // channel.
+ ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED ||
+ levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
+ resultSwizzle = GL_RED;
+ }
+ else if (levelInfo.sourceFormat == GL_ALPHA)
+ {
+ // Color channels are not supposed to exist, make them always sample 0.
+ resultSwizzle = GL_ZERO;
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ break;
+
+ case GL_ALPHA:
+ if (levelInfo.sourceFormat == GL_LUMINANCE)
+ {
+ // Alpha channel is not supposed to exist, make it always sample 1.
+ resultSwizzle = GL_ONE;
+ }
+ else if (levelInfo.sourceFormat == GL_ALPHA)
+ {
+ // Texture is backed by a RED texture, point the alpha channel at the red
+ // channel.
+ ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED);
+ resultSwizzle = GL_RED;
+ }
+ else if (levelInfo.sourceFormat == GL_LUMINANCE_ALPHA)
+ {
+ // Texture is backed by an RG texture, point the alpha channel at the green
+ // channel.
+ ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
+ resultSwizzle = GL_GREEN;
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ break;
+
+ case GL_ZERO:
+ case GL_ONE:
+ // Don't modify the swizzle state when requesting ZERO or ONE.
+ resultSwizzle = value;
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ else if (levelInfo.depthStencilWorkaround)
+ {
+ switch (value)
+ {
+ case GL_RED:
+ // Don't modify the swizzle state when requesting the red channel.
+ resultSwizzle = value;
+ break;
+
+ case GL_GREEN:
+ case GL_BLUE:
+ // Depth textures should sample 0 from the green and blue channels.
+ resultSwizzle = GL_ZERO;
+ break;
+
+ case GL_ALPHA:
+ // Depth textures should sample 1 from the alpha channel.
+ resultSwizzle = GL_ONE;
+ break;
+
+ case GL_ZERO:
+ case GL_ONE:
+ // Don't modify the swizzle state when requesting ZERO or ONE.
+ resultSwizzle = value;
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ }
+
+ functions->texParameteri(mState.mTarget, name, resultSwizzle);
+}
+
+void TextureGL::setLevelInfo(size_t level, size_t levelCount, const LevelInfoGL &levelInfo)
+{
+ ASSERT(levelCount > 0 && level + levelCount < mLevelInfo.size());
+
+ GLuint baseLevel = mState.getEffectiveBaseLevel();
+ bool needsResync = level <= baseLevel && level + levelCount >= baseLevel &&
+ (levelInfo.depthStencilWorkaround || levelInfo.lumaWorkaround.enabled);
+ if (needsResync)
+ {
+ mLocalDirtyBits |= GetLevelWorkaroundDirtyBits();
+ }
+
+ for (size_t i = level; i < level + levelCount; i++)
+ {
+ mLevelInfo[i] = levelInfo;
+ }
+}
+
+GLuint TextureGL::getTextureID() const
+{
+ return mTextureID;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/TextureGL.h b/gfx/angle/src/libANGLE/renderer/gl/TextureGL.h
new file mode 100755
index 000000000..068284c5b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/TextureGL.h
@@ -0,0 +1,145 @@
+//
+// 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.
+//
+
+// TextureGL.h: Defines the class interface for TextureGL.
+
+#ifndef LIBANGLE_RENDERER_GL_TEXTUREGL_H_
+#define LIBANGLE_RENDERER_GL_TEXTUREGL_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/Texture.h"
+
+namespace rx
+{
+
+class BlitGL;
+class FunctionsGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+struct LUMAWorkaroundGL
+{
+ bool enabled;
+ GLenum workaroundFormat;
+
+ LUMAWorkaroundGL();
+ LUMAWorkaroundGL(bool enabled, GLenum workaroundFormat);
+};
+
+// Structure containing information about format and workarounds for each mip level of the
+// TextureGL.
+struct LevelInfoGL
+{
+ // Format of the data used in this mip level.
+ GLenum sourceFormat;
+
+ // If this mip level requires sampler-state re-writing so that only a red channel is exposed.
+ bool depthStencilWorkaround;
+
+ // Information about luminance alpha texture workarounds in the core profile.
+ LUMAWorkaroundGL lumaWorkaround;
+
+ LevelInfoGL();
+ LevelInfoGL(GLenum sourceFormat,
+ bool depthStencilWorkaround,
+ const LUMAWorkaroundGL &lumaWorkaround);
+};
+
+class TextureGL : public TextureImpl
+{
+ public:
+ TextureGL(const gl::TextureState &state,
+ const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ StateManagerGL *stateManager,
+ BlitGL *blitter);
+ ~TextureGL() override;
+
+ gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
+
+ gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
+
+ gl::Error setImageExternal(GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+
+ gl::Error generateMipmap() override;
+
+ void bindTexImage(egl::Surface *surface) override;
+ void releaseTexImage() override;
+
+ gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+ GLuint getTextureID() const;
+
+ void setBaseLevel(GLuint) override {}
+
+ void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+ bool hasAnyDirtyBit() const;
+
+ private:
+ void setImageHelper(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const uint8_t *pixels);
+ void reserveTexImageToBeFilled(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type);
+ gl::Error setSubImageRowByRowWorkaround(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels);
+
+ gl::Error setSubImagePaddingWorkaround(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels);
+
+ void syncTextureStateSwizzle(const FunctionsGL *functions, GLenum name, GLenum value);
+
+ void setLevelInfo(size_t level, size_t levelCount, const LevelInfoGL &levelInfo);
+
+ const FunctionsGL *mFunctions;
+ const WorkaroundsGL &mWorkarounds;
+ StateManagerGL *mStateManager;
+ BlitGL *mBlitter;
+
+ std::vector<LevelInfoGL> mLevelInfo;
+ gl::Texture::DirtyBits mLocalDirtyBits;
+
+ mutable gl::TextureState mAppliedTextureState;
+ GLuint mTextureID;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_TEXTUREGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
new file mode 100755
index 000000000..ae75a0f47
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
@@ -0,0 +1,131 @@
+//
+// 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.
+//
+
+// TransformFeedbackGL.cpp: Implements the class methods for TransformFeedbackGL.
+
+#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+namespace rx
+{
+
+TransformFeedbackGL::TransformFeedbackGL(const gl::TransformFeedbackState &state,
+ const FunctionsGL *functions,
+ StateManagerGL *stateManager)
+ : TransformFeedbackImpl(state),
+ mFunctions(functions),
+ mStateManager(stateManager),
+ mTransformFeedbackID(0),
+ mIsActive(false),
+ mIsPaused(false)
+{
+ mFunctions->genTransformFeedbacks(1, &mTransformFeedbackID);
+}
+
+TransformFeedbackGL::~TransformFeedbackGL()
+{
+ mStateManager->deleteTransformFeedback(mTransformFeedbackID);
+ mTransformFeedbackID = 0;
+}
+
+void TransformFeedbackGL::begin(GLenum primitiveMode)
+{
+ // Do not begin directly, StateManagerGL will handle beginning and resuming transform feedback.
+}
+
+void TransformFeedbackGL::end()
+{
+ syncActiveState(false, GL_NONE);
+}
+
+void TransformFeedbackGL::pause()
+{
+ syncPausedState(true);
+}
+
+void TransformFeedbackGL::resume()
+{
+ // Do not resume directly, StateManagerGL will handle beginning and resuming transform feedback.
+}
+
+void TransformFeedbackGL::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
+{
+}
+
+void TransformFeedbackGL::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding)
+{
+ // Directly bind buffer (not through the StateManager methods) because the buffer bindings are
+ // tracked per transform feedback object
+ mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
+ if (binding.get() != nullptr)
+ {
+ const BufferGL *bufferGL = GetImplAs<BufferGL>(binding.get());
+ if (binding.getSize() != 0)
+ {
+ mFunctions->bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index),
+ bufferGL->getBufferID(), binding.getOffset(),
+ binding.getSize());
+ }
+ else
+ {
+ mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index),
+ bufferGL->getBufferID());
+ }
+ }
+ else
+ {
+ mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), 0);
+ }
+}
+
+GLuint TransformFeedbackGL::getTransformFeedbackID() const
+{
+ return mTransformFeedbackID;
+}
+
+void TransformFeedbackGL::syncActiveState(bool active, GLenum primitiveMode) const
+{
+ if (mIsActive != active)
+ {
+ mIsActive = active;
+ mIsPaused = false;
+
+ mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
+ if (mIsActive)
+ {
+ mFunctions->beginTransformFeedback(primitiveMode);
+ }
+ else
+ {
+ mFunctions->endTransformFeedback();
+ }
+ }
+}
+
+void TransformFeedbackGL::syncPausedState(bool paused) const
+{
+ if (mIsActive && mIsPaused != paused)
+ {
+ mIsPaused = paused;
+
+ mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
+ if (mIsPaused)
+ {
+ mFunctions->pauseTransformFeedback();
+ }
+ else
+ {
+ mFunctions->resumeTransformFeedback();
+ }
+ }
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h b/gfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h
new file mode 100755
index 000000000..f84edc0b7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h
@@ -0,0 +1,53 @@
+//
+// 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.
+//
+
+// TransformFeedbackGL.h: Defines the class interface for TransformFeedbackGL.
+
+#ifndef LIBANGLE_RENDERER_GL_TRANSFORMFEEDBACKGL_H_
+#define LIBANGLE_RENDERER_GL_TRANSFORMFEEDBACKGL_H_
+
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+
+class TransformFeedbackGL : public TransformFeedbackImpl
+{
+ public:
+ TransformFeedbackGL(const gl::TransformFeedbackState &state,
+ const FunctionsGL *functions,
+ StateManagerGL *stateManager);
+ ~TransformFeedbackGL() override;
+
+ void begin(GLenum primitiveMode) override;
+ void end() override;
+ void pause() override;
+ void resume() override;
+
+ void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
+ void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+
+ GLuint getTransformFeedbackID() const;
+
+ void syncActiveState(bool active, GLenum primitiveMode) const;
+ void syncPausedState(bool paused) const;
+
+ private:
+ const FunctionsGL *mFunctions;
+ StateManagerGL *mStateManager;
+
+ GLuint mTransformFeedbackID;
+
+ mutable bool mIsActive;
+ mutable bool mIsPaused;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_TRANSFORMFEEDBACKGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp
new file mode 100755
index 000000000..1e7fa030f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp
@@ -0,0 +1,499 @@
+//
+// 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.
+//
+
+// VertexArrayGL.cpp: Implements the class methods for VertexArrayGL.
+
+#include "libANGLE/renderer/gl/VertexArrayGL.h"
+
+#include "common/BitSetIterator.h"
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+using namespace gl;
+
+namespace rx
+{
+namespace
+{
+bool AttributeNeedsStreaming(const VertexAttribute &attribute)
+{
+ return (attribute.enabled && attribute.buffer.get() == nullptr);
+}
+
+} // anonymous namespace
+
+VertexArrayGL::VertexArrayGL(const VertexArrayState &state,
+ const FunctionsGL *functions,
+ StateManagerGL *stateManager)
+ : VertexArrayImpl(state),
+ mFunctions(functions),
+ mStateManager(stateManager),
+ mVertexArrayID(0),
+ mAppliedElementArrayBuffer(),
+ mStreamingElementArrayBufferSize(0),
+ mStreamingElementArrayBuffer(0),
+ mStreamingArrayBufferSize(0),
+ mStreamingArrayBuffer(0)
+{
+ ASSERT(mFunctions);
+ ASSERT(mStateManager);
+ mFunctions->genVertexArrays(1, &mVertexArrayID);
+
+ // Set the cached vertex attribute array size
+ GLint maxVertexAttribs = 0;
+ mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
+ mAppliedAttributes.resize(maxVertexAttribs);
+}
+
+VertexArrayGL::~VertexArrayGL()
+{
+ mStateManager->deleteVertexArray(mVertexArrayID);
+ mVertexArrayID = 0;
+
+ mStateManager->deleteBuffer(mStreamingElementArrayBuffer);
+ mStreamingElementArrayBufferSize = 0;
+ mStreamingElementArrayBuffer = 0;
+
+ mStateManager->deleteBuffer(mStreamingArrayBuffer);
+ mStreamingArrayBufferSize = 0;
+ mStreamingArrayBuffer = 0;
+
+ mAppliedElementArrayBuffer.set(nullptr);
+ for (size_t idx = 0; idx < mAppliedAttributes.size(); idx++)
+ {
+ mAppliedAttributes[idx].buffer.set(nullptr);
+ }
+}
+
+gl::Error VertexArrayGL::syncDrawArraysState(const gl::AttributesMask &activeAttributesMask,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) const
+{
+ return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, instanceCount, false,
+ nullptr);
+}
+
+gl::Error VertexArrayGL::syncDrawElementsState(const gl::AttributesMask &activeAttributesMask,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instanceCount,
+ bool primitiveRestartEnabled,
+ const GLvoid **outIndices) const
+{
+ return syncDrawState(activeAttributesMask, 0, count, type, indices, instanceCount,
+ primitiveRestartEnabled, outIndices);
+}
+
+gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask,
+ GLint first,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instanceCount,
+ bool primitiveRestartEnabled,
+ const GLvoid **outIndices) const
+{
+ mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
+
+ // Check if any attributes need to be streamed, determines if the index range needs to be computed
+ bool attributesNeedStreaming = mAttributesNeedStreaming.any();
+
+ // Determine if an index buffer needs to be streamed and the range of vertices that need to be copied
+ IndexRange indexRange;
+ if (type != GL_NONE)
+ {
+ Error error = syncIndexData(count, type, indices, primitiveRestartEnabled,
+ attributesNeedStreaming, &indexRange, outIndices);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ else
+ {
+ // Not an indexed call, set the range to [first, first + count - 1]
+ indexRange.start = first;
+ indexRange.end = first + count - 1;
+ }
+
+ if (attributesNeedStreaming)
+ {
+ Error error = streamAttributes(activeAttributesMask, instanceCount, indexRange);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return Error(GL_NO_ERROR);
+}
+
+Error VertexArrayGL::syncIndexData(GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ bool primitiveRestartEnabled,
+ bool attributesNeedStreaming,
+ IndexRange *outIndexRange,
+ const GLvoid **outIndices) const
+{
+ ASSERT(outIndices);
+
+ gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get();
+
+ // Need to check the range of indices if attributes need to be streamed
+ if (elementArrayBuffer != nullptr)
+ {
+ if (elementArrayBuffer != mAppliedElementArrayBuffer.get())
+ {
+ const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
+ mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID());
+ mAppliedElementArrayBuffer.set(elementArrayBuffer);
+ }
+
+ // Only compute the index range if the attributes also need to be streamed
+ if (attributesNeedStreaming)
+ {
+ ptrdiff_t elementArrayBufferOffset = reinterpret_cast<ptrdiff_t>(indices);
+ Error error = mData.getElementArrayBuffer()->getIndexRange(
+ type, elementArrayBufferOffset, count, primitiveRestartEnabled, outIndexRange);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ // Indices serves as an offset into the index buffer in this case, use the same value for the draw call
+ *outIndices = indices;
+ }
+ else
+ {
+ // Need to stream the index buffer
+ // TODO: if GLES, nothing needs to be streamed
+
+ // Only compute the index range if the attributes also need to be streamed
+ if (attributesNeedStreaming)
+ {
+ *outIndexRange = ComputeIndexRange(type, indices, count, primitiveRestartEnabled);
+ }
+
+ // Allocate the streaming element array buffer
+ if (mStreamingElementArrayBuffer == 0)
+ {
+ mFunctions->genBuffers(1, &mStreamingElementArrayBuffer);
+ mStreamingElementArrayBufferSize = 0;
+ }
+
+ mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mStreamingElementArrayBuffer);
+ mAppliedElementArrayBuffer.set(nullptr);
+
+ // Make sure the element array buffer is large enough
+ const Type &indexTypeInfo = GetTypeInfo(type);
+ size_t requiredStreamingBufferSize = indexTypeInfo.bytes * count;
+ if (requiredStreamingBufferSize > mStreamingElementArrayBufferSize)
+ {
+ // Copy the indices in while resizing the buffer
+ mFunctions->bufferData(GL_ELEMENT_ARRAY_BUFFER, requiredStreamingBufferSize, indices, GL_DYNAMIC_DRAW);
+ mStreamingElementArrayBufferSize = requiredStreamingBufferSize;
+ }
+ else
+ {
+ // Put the indices at the beginning of the buffer
+ mFunctions->bufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, requiredStreamingBufferSize, indices);
+ }
+
+ // Set the index offset for the draw call to zero since the supplied index pointer is to client data
+ *outIndices = nullptr;
+ }
+
+ return Error(GL_NO_ERROR);
+}
+
+void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
+ GLsizei instanceCount,
+ const gl::IndexRange &indexRange,
+ size_t *outStreamingDataSize,
+ size_t *outMaxAttributeDataSize) const
+{
+ *outStreamingDataSize = 0;
+ *outMaxAttributeDataSize = 0;
+
+ ASSERT(mAttributesNeedStreaming.any());
+
+ const auto &attribs = mData.getVertexAttributes();
+ for (auto idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
+ {
+ const auto &attrib = attribs[idx];
+ ASSERT(AttributeNeedsStreaming(attrib));
+
+ // If streaming is going to be required, compute the size of the required buffer
+ // and how much slack space at the beginning of the buffer will be required by determining
+ // the attribute with the largest data size.
+ size_t typeSize = ComputeVertexAttributeTypeSize(attrib);
+ *outStreamingDataSize += typeSize * ComputeVertexAttributeElementCount(
+ attrib, indexRange.vertexCount(), instanceCount);
+ *outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
+ }
+}
+
+gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttributesMask,
+ GLsizei instanceCount,
+ const gl::IndexRange &indexRange) const
+{
+ // Sync the vertex attribute state and track what data needs to be streamed
+ size_t streamingDataSize = 0;
+ size_t maxAttributeDataSize = 0;
+
+ computeStreamingAttributeSizes(activeAttributesMask, instanceCount, indexRange,
+ &streamingDataSize, &maxAttributeDataSize);
+
+ if (streamingDataSize == 0)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ if (mStreamingArrayBuffer == 0)
+ {
+ mFunctions->genBuffers(1, &mStreamingArrayBuffer);
+ mStreamingArrayBufferSize = 0;
+ }
+
+ // If first is greater than zero, a slack space needs to be left at the beginning of the buffer so that
+ // the same 'first' argument can be passed into the draw call.
+ const size_t bufferEmptySpace = maxAttributeDataSize * indexRange.start;
+ const size_t requiredBufferSize = streamingDataSize + bufferEmptySpace;
+
+ mStateManager->bindBuffer(GL_ARRAY_BUFFER, mStreamingArrayBuffer);
+ if (requiredBufferSize > mStreamingArrayBufferSize)
+ {
+ mFunctions->bufferData(GL_ARRAY_BUFFER, requiredBufferSize, nullptr, GL_DYNAMIC_DRAW);
+ mStreamingArrayBufferSize = requiredBufferSize;
+ }
+
+ // Unmapping a buffer can return GL_FALSE to indicate that the system has corrupted the data
+ // somehow (such as by a screen change), retry writing the data a few times and return OUT_OF_MEMORY
+ // if that fails.
+ GLboolean unmapResult = GL_FALSE;
+ size_t unmapRetryAttempts = 5;
+ while (unmapResult != GL_TRUE && --unmapRetryAttempts > 0)
+ {
+ uint8_t *bufferPointer = MapBufferRangeWithFallback(mFunctions, GL_ARRAY_BUFFER, 0,
+ requiredBufferSize, GL_MAP_WRITE_BIT);
+ size_t curBufferOffset = bufferEmptySpace;
+
+ const auto &attribs = mData.getVertexAttributes();
+ for (auto idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
+ {
+ const auto &attrib = attribs[idx];
+ ASSERT(AttributeNeedsStreaming(attrib));
+
+ const size_t streamedVertexCount =
+ ComputeVertexAttributeElementCount(attrib, indexRange.vertexCount(), instanceCount);
+
+ const size_t sourceStride = ComputeVertexAttributeStride(attrib);
+ const size_t destStride = ComputeVertexAttributeTypeSize(attrib);
+
+ const uint8_t *inputPointer = reinterpret_cast<const uint8_t *>(attrib.pointer);
+
+ // Pack the data when copying it, user could have supplied a very large stride that
+ // would cause the buffer to be much larger than needed.
+ if (destStride == sourceStride)
+ {
+ // Can copy in one go, the data is packed
+ memcpy(bufferPointer + curBufferOffset,
+ inputPointer + (sourceStride * indexRange.start),
+ destStride * streamedVertexCount);
+ }
+ else
+ {
+ // Copy each vertex individually
+ for (size_t vertexIdx = 0; vertexIdx < streamedVertexCount; vertexIdx++)
+ {
+ uint8_t *out = bufferPointer + curBufferOffset + (destStride * vertexIdx);
+ const uint8_t *in =
+ inputPointer + sourceStride * (vertexIdx + indexRange.start);
+ memcpy(out, in, destStride);
+ }
+ }
+
+ // Compute where the 0-index vertex would be.
+ const size_t vertexStartOffset = curBufferOffset - (indexRange.start * destStride);
+
+ if (attrib.pureInteger)
+ {
+ ASSERT(!attrib.normalized);
+ mFunctions->vertexAttribIPointer(
+ static_cast<GLuint>(idx), attrib.size, attrib.type,
+ static_cast<GLsizei>(destStride),
+ reinterpret_cast<const GLvoid *>(vertexStartOffset));
+ }
+ else
+ {
+ mFunctions->vertexAttribPointer(
+ static_cast<GLuint>(idx), attrib.size, attrib.type, attrib.normalized,
+ static_cast<GLsizei>(destStride),
+ reinterpret_cast<const GLvoid *>(vertexStartOffset));
+ }
+
+ curBufferOffset += destStride * streamedVertexCount;
+
+ // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
+ // need to be streamed later, there is no chance that the caching will skip it.
+ mAppliedAttributes[idx].size = static_cast<GLuint>(-1);
+ }
+
+ unmapResult = mFunctions->unmapBuffer(GL_ARRAY_BUFFER);
+ }
+
+ if (unmapResult != GL_TRUE)
+ {
+ return Error(GL_OUT_OF_MEMORY, "Failed to unmap the client data streaming buffer.");
+ }
+
+ return Error(GL_NO_ERROR);
+}
+
+GLuint VertexArrayGL::getVertexArrayID() const
+{
+ return mVertexArrayID;
+}
+
+GLuint VertexArrayGL::getAppliedElementArrayBufferID() const
+{
+ if (mAppliedElementArrayBuffer.get() == nullptr)
+ {
+ return mStreamingElementArrayBuffer;
+ }
+
+ return GetImplAs<BufferGL>(mAppliedElementArrayBuffer.get())->getBufferID();
+}
+
+void VertexArrayGL::updateNeedsStreaming(size_t attribIndex)
+{
+ const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
+ mAttributesNeedStreaming.set(attribIndex, AttributeNeedsStreaming(attrib));
+}
+
+void VertexArrayGL::updateAttribEnabled(size_t attribIndex)
+{
+ const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
+ if (mAppliedAttributes[attribIndex].enabled == attrib.enabled)
+ {
+ return;
+ }
+
+ updateNeedsStreaming(attribIndex);
+
+ mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
+ if (attrib.enabled)
+ {
+ mFunctions->enableVertexAttribArray(static_cast<GLuint>(attribIndex));
+ }
+ else
+ {
+ mFunctions->disableVertexAttribArray(static_cast<GLuint>(attribIndex));
+ }
+ mAppliedAttributes[attribIndex].enabled = attrib.enabled;
+}
+
+void VertexArrayGL::updateAttribPointer(size_t attribIndex)
+{
+ const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
+ if (mAppliedAttributes[attribIndex] == attrib)
+ {
+ return;
+ }
+
+ updateNeedsStreaming(attribIndex);
+
+ // If we need to stream, defer the attribPointer to the draw call.
+ if (mAttributesNeedStreaming[attribIndex])
+ {
+ return;
+ }
+
+ mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
+ const Buffer *arrayBuffer = attrib.buffer.get();
+ if (arrayBuffer != nullptr)
+ {
+ const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer);
+ mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID());
+ }
+ else
+ {
+ mStateManager->bindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ mAppliedAttributes[attribIndex].buffer = attrib.buffer;
+
+ if (attrib.pureInteger)
+ {
+ mFunctions->vertexAttribIPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
+ attrib.stride, attrib.pointer);
+ }
+ else
+ {
+ mFunctions->vertexAttribPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
+ attrib.normalized, attrib.stride, attrib.pointer);
+ }
+ mAppliedAttributes[attribIndex].size = attrib.size;
+ mAppliedAttributes[attribIndex].type = attrib.type;
+ mAppliedAttributes[attribIndex].normalized = attrib.normalized;
+ mAppliedAttributes[attribIndex].pureInteger = attrib.pureInteger;
+ mAppliedAttributes[attribIndex].stride = attrib.stride;
+ mAppliedAttributes[attribIndex].pointer = attrib.pointer;
+}
+
+void VertexArrayGL::syncState(const VertexArray::DirtyBits &dirtyBits)
+{
+ for (unsigned long dirtyBit : angle::IterateBitSet(dirtyBits))
+ {
+ if (dirtyBit == VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
+ {
+ // TODO(jmadill): Element array buffer bindings
+ }
+ else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED &&
+ dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED)
+ {
+ size_t attribIndex =
+ static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED;
+ updateAttribEnabled(attribIndex);
+ }
+ else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_POINTER &&
+ dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER)
+ {
+ size_t attribIndex =
+ static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_POINTER;
+ updateAttribPointer(attribIndex);
+ }
+ else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR &&
+ dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_DIVISOR)
+ {
+ size_t attribIndex =
+ static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR;
+ const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
+
+ if (mAppliedAttributes[attribIndex].divisor != attrib.divisor)
+ {
+ mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
+ mFunctions->vertexAttribDivisor(static_cast<GLuint>(attribIndex), attrib.divisor);
+ mAppliedAttributes[attribIndex].divisor = attrib.divisor;
+ }
+ }
+ else
+ UNREACHABLE();
+ }
+}
+
+} // rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.h b/gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.h
new file mode 100755
index 000000000..261b63d91
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.h
@@ -0,0 +1,100 @@
+//
+// 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.
+//
+
+// VertexArrayGL.h: Defines the class interface for VertexArrayGL.
+
+#ifndef LIBANGLE_RENDERER_GL_VERTEXARRAYGL_H_
+#define LIBANGLE_RENDERER_GL_VERTEXARRAYGL_H_
+
+#include "libANGLE/renderer/VertexArrayImpl.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+
+class VertexArrayGL : public VertexArrayImpl
+{
+ public:
+ VertexArrayGL(const gl::VertexArrayState &data,
+ const FunctionsGL *functions,
+ StateManagerGL *stateManager);
+ ~VertexArrayGL() override;
+
+ gl::Error syncDrawArraysState(const gl::AttributesMask &activeAttributesMask,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) const;
+ gl::Error syncDrawElementsState(const gl::AttributesMask &activeAttributesMask,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instanceCount,
+ bool primitiveRestartEnabled,
+ const GLvoid **outIndices) const;
+
+ GLuint getVertexArrayID() const;
+ GLuint getAppliedElementArrayBufferID() const;
+
+ void syncState(const gl::VertexArray::DirtyBits &dirtyBits) override;
+
+ private:
+ gl::Error syncDrawState(const gl::AttributesMask &activeAttributesMask,
+ GLint first,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instanceCount,
+ bool primitiveRestartEnabled,
+ const GLvoid **outIndices) const;
+
+ // Apply index data, only sets outIndexRange if attributesNeedStreaming is true
+ gl::Error syncIndexData(GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ bool primitiveRestartEnabled,
+ bool attributesNeedStreaming,
+ gl::IndexRange *outIndexRange,
+ const GLvoid **outIndices) const;
+
+ // Returns the amount of space needed to stream all attributes that need streaming
+ // and the data size of the largest attribute
+ void computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
+ GLsizei instanceCount,
+ const gl::IndexRange &indexRange,
+ size_t *outStreamingDataSize,
+ size_t *outMaxAttributeDataSize) const;
+
+ // Stream attributes that have client data
+ gl::Error streamAttributes(const gl::AttributesMask &activeAttributesMask,
+ GLsizei instanceCount,
+ const gl::IndexRange &indexRange) const;
+
+ void updateNeedsStreaming(size_t attribIndex);
+ void updateAttribEnabled(size_t attribIndex);
+ void updateAttribPointer(size_t attribIndex);
+
+ const FunctionsGL *mFunctions;
+ StateManagerGL *mStateManager;
+
+ GLuint mVertexArrayID;
+
+ mutable BindingPointer<gl::Buffer> mAppliedElementArrayBuffer;
+ mutable std::vector<gl::VertexAttribute> mAppliedAttributes;
+
+ mutable size_t mStreamingElementArrayBufferSize;
+ mutable GLuint mStreamingElementArrayBuffer;
+
+ mutable size_t mStreamingArrayBufferSize;
+ mutable GLuint mStreamingArrayBuffer;
+
+ gl::AttributesMask mAttributesNeedStreaming;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_VERTEXARRAYGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h b/gfx/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h
new file mode 100755
index 000000000..105f94089
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h
@@ -0,0 +1,126 @@
+//
+// Copyright (c) 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.
+//
+
+// WorkaroundsGL.h: Workarounds for GL driver bugs and other issues.
+
+#ifndef LIBANGLE_RENDERER_GL_WORKAROUNDSGL_H_
+#define LIBANGLE_RENDERER_GL_WORKAROUNDSGL_H_
+
+namespace rx
+{
+
+struct WorkaroundsGL
+{
+ WorkaroundsGL()
+ : avoid1BitAlphaTextureFormats(false),
+ rgba4IsNotSupportedForColorRendering(false),
+ doesSRGBClearsOnLinearFramebufferAttachments(false),
+ doWhileGLSLCausesGPUHang(false),
+ finishDoesNotCauseQueriesToBeAvailable(false),
+ alwaysCallUseProgramAfterLink(false),
+ unpackOverlappingRowsSeparatelyUnpackBuffer(false),
+ emulateAbsIntFunction(false),
+ addAndTrueToLoopCondition(false),
+ emulateIsnanFloat(false),
+ useUnusedBlocksWithStandardOrSharedLayout(false),
+ dontRemoveInvariantForFragmentInput(false),
+ removeInvariantAndCentroidForESSL3(false)
+ {
+ }
+
+ // When writing a float to a normalized integer framebuffer, desktop OpenGL is allowed to write
+ // one of the two closest normalized integer representations (although round to nearest is
+ // preferred) (see section 2.3.5.2 of the GL 4.5 core specification). OpenGL ES requires that
+ // round-to-nearest is used (see "Conversion from Floating-Point to Framebuffer Fixed-Point" in
+ // section 2.1.2 of the OpenGL ES 2.0.25 spec). This issue only shows up on Intel and AMD
+ // drivers on framebuffer formats that have 1-bit alpha, work around this by using higher
+ // precision formats instead.
+ bool avoid1BitAlphaTextureFormats;
+
+ // On some older Intel drivers, GL_RGBA4 is not color renderable, glCheckFramebufferStatus
+ // returns GL_FRAMEBUFFER_UNSUPPORTED. Work around this by using a known color-renderable
+ // format.
+ bool rgba4IsNotSupportedForColorRendering;
+
+ // When clearing a framebuffer on Intel or AMD drivers, when GL_FRAMEBUFFER_SRGB is enabled, the
+ // driver clears to the linearized clear color despite the framebuffer not supporting SRGB
+ // blending. It only seems to do this when the framebuffer has only linear attachments, mixed
+ // attachments appear to get the correct clear color.
+ bool doesSRGBClearsOnLinearFramebufferAttachments;
+
+ // On Mac some GLSL constructs involving do-while loops cause GPU hangs, such as the following:
+ // int i = 1;
+ // do {
+ // i --;
+ // continue;
+ // } while (i > 0)
+ // Work around this by rewriting the do-while to use another GLSL construct (block + while)
+ bool doWhileGLSLCausesGPUHang;
+
+ // Calling glFinish doesn't cause all queries to report that the result is available on some
+ // (NVIDIA) drivers. It was found that enabling GL_DEBUG_OUTPUT_SYNCHRONOUS before the finish
+ // causes it to fully finish.
+ bool finishDoesNotCauseQueriesToBeAvailable;
+
+ // Always call useProgram after a successful link to avoid a driver bug.
+ // This workaround is meant to reproduce the use_current_program_after_successful_link
+ // workaround in Chromium (http://crbug.com/110263). It has been shown that this workaround is
+ // not necessary for MacOSX 10.9 and higher (http://crrev.com/39eb535b).
+ bool alwaysCallUseProgramAfterLink;
+
+ // In the case of unpacking from a pixel unpack buffer, unpack overlapping rows row by row.
+ bool unpackOverlappingRowsSeparatelyUnpackBuffer;
+ // In the case of packing to a pixel pack buffer, pack overlapping rows row by row.
+ bool packOverlappingRowsSeparatelyPackBuffer;
+
+ // During initialization, assign the current vertex attributes to the spec-mandated defaults.
+ bool initializeCurrentVertexAttributes;
+
+ // abs(i) where i is an integer returns unexpected result on Intel Mac.
+ // Emulate abs(i) with i * sign(i).
+ bool emulateAbsIntFunction;
+
+ // On Intel Mac, calculation of loop conditions in for and while loop has bug.
+ // Add "&& true" to the end of the condition expression to work around the bug.
+ bool addAndTrueToLoopCondition;
+
+ // When uploading textures from an unpack buffer, some drivers count an extra row padding when
+ // checking if the pixel unpack buffer is big enough. Tracking bug: http://anglebug.com/1512
+ // For example considering the pixel buffer below where in memory, each row data (D) of the
+ // texture is followed by some unused data (the dots):
+ // +-------+--+
+ // |DDDDDDD|..|
+ // |DDDDDDD|..|
+ // |DDDDDDD|..|
+ // |DDDDDDD|..|
+ // +-------A--B
+ // The last pixel read will be A, but the driver will think it is B, causing it to generate an
+ // error when the pixel buffer is just big enough.
+ bool unpackLastRowSeparatelyForPaddingInclusion;
+
+ // Equivalent workaround when uploading data from a pixel pack buffer.
+ bool packLastRowSeparatelyForPaddingInclusion;
+
+ // On some Intel drivers, using isnan() on highp float will get wrong answer. To work around
+ // this bug, we use an expression to emulate function isnan().
+ // Tracking bug: http://crbug.com/650547
+ bool emulateIsnanFloat;
+
+ // On Mac with OpenGL version 4.1, unused std140 or shared uniform blocks will be
+ // treated as inactive which is not consistent with WebGL2.0 spec. Reference all members in a
+ // unused std140 or shared uniform block at the beginning of main to work around it.
+ bool useUnusedBlocksWithStandardOrSharedLayout;
+
+ // This flag will keep invariant declaration for input in fragment shader for GLSL >=4.20
+ // on AMD.
+ bool dontRemoveInvariantForFragmentInput;
+
+ // This flag is used to fix spec difference between GLSL 4.1 or lower and ESSL3.
+ bool removeInvariantAndCentroidForESSL3;
+};
+}
+
+#endif // LIBANGLE_RENDERER_GL_WORKAROUNDSGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.h b/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.h
new file mode 100755
index 000000000..cc1b17bb7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.h
@@ -0,0 +1,77 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayCGL.h: CGL implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_CGL_DISPLAYCGL_H_
+#define LIBANGLE_RENDERER_GL_CGL_DISPLAYCGL_H_
+
+#include "libANGLE/renderer/gl/DisplayGL.h"
+
+struct _CGLContextObject;
+typedef _CGLContextObject *CGLContextObj;
+
+namespace rx
+{
+
+class DisplayCGL : public DisplayGL
+{
+ public:
+ DisplayCGL();
+ ~DisplayCGL() override;
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() override;
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+ egl::Error getDevice(DeviceImpl **device) override;
+
+ std::string getVendorString() const override;
+
+ egl::Error waitClient() const override;
+ egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const override;
+
+ egl::Error getDriverVersion(std::string *version) const override;
+
+ private:
+ const FunctionsGL *getFunctionsGL() const override;
+
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+ void generateCaps(egl::Caps *outCaps) const override;
+
+ egl::Display *mEGLDisplay;
+ FunctionsGL *mFunctions;
+ CGLContextObj mContext;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_CGL_DISPLAYCGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm b/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm
new file mode 100755
index 000000000..f87134c82
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm
@@ -0,0 +1,275 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayCGL.mm: CGL implementation of egl::Display
+
+#include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
+
+#import <Cocoa/Cocoa.h>
+#include <dlfcn.h>
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h"
+#include "libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h"
+
+namespace
+{
+
+const char *kDefaultOpenGLDylibName =
+ "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib";
+const char *kFallbackOpenGLDylibName = "GL";
+
+}
+
+namespace rx
+{
+
+class FunctionsGLCGL : public FunctionsGL
+{
+ public:
+ FunctionsGLCGL(void *dylibHandle) : mDylibHandle(dylibHandle) {}
+
+ ~FunctionsGLCGL() override { dlclose(mDylibHandle); }
+
+ private:
+ void *loadProcAddress(const std::string &function) override
+ {
+ return dlsym(mDylibHandle, function.c_str());
+ }
+
+ void *mDylibHandle;
+};
+
+DisplayCGL::DisplayCGL() : DisplayGL(), mEGLDisplay(nullptr), mFunctions(nullptr), mContext(nullptr)
+{
+}
+
+DisplayCGL::~DisplayCGL()
+{
+}
+
+egl::Error DisplayCGL::initialize(egl::Display *display)
+{
+ mEGLDisplay = display;
+
+ CGLPixelFormatObj pixelFormat;
+ {
+ // TODO(cwallez) investigate which pixel format we want
+ CGLPixelFormatAttribute attribs[] = {
+ kCGLPFAOpenGLProfile, static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_3_2_Core),
+ static_cast<CGLPixelFormatAttribute>(0)};
+ GLint nVirtualScreens = 0;
+ CGLChoosePixelFormat(attribs, &pixelFormat, &nVirtualScreens);
+
+ if (pixelFormat == nullptr)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create the context's pixel format.");
+ }
+ }
+
+ CGLCreateContext(pixelFormat, nullptr, &mContext);
+ if (mContext == nullptr)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create the CGL context.");
+ }
+ CGLSetCurrentContext(mContext);
+
+ // There is no equivalent getProcAddress in CGL so we open the dylib directly
+ void *handle = dlopen(kDefaultOpenGLDylibName, RTLD_NOW);
+ if (!handle)
+ {
+ handle = dlopen(kFallbackOpenGLDylibName, RTLD_NOW);
+ }
+ if (!handle)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not open the OpenGL Framework.");
+ }
+
+ mFunctions = new FunctionsGLCGL(handle);
+ mFunctions->initialize();
+
+ return DisplayGL::initialize(display);
+}
+
+void DisplayCGL::terminate()
+{
+ DisplayGL::terminate();
+
+ if (mContext != nullptr)
+ {
+ CGLSetCurrentContext(nullptr);
+ CGLReleaseContext(mContext);
+ mContext = nullptr;
+ }
+
+ SafeDelete(mFunctions);
+}
+
+SurfaceImpl *DisplayCGL::createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ return new WindowSurfaceCGL(state, this->getRenderer(), window, mFunctions, mContext);
+}
+
+SurfaceImpl *DisplayCGL::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs)
+{
+ EGLint width = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0));
+ EGLint height = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0));
+ return new PbufferSurfaceCGL(state, this->getRenderer(), width, height, mFunctions);
+}
+
+SurfaceImpl *DisplayCGL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+SurfaceImpl *DisplayCGL::createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+egl::Error DisplayCGL::getDevice(DeviceImpl **device)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+egl::ConfigSet DisplayCGL::generateConfigs()
+{
+ // TODO(cwallez): generate more config permutations
+ egl::ConfigSet configs;
+
+ const gl::Version &maxVersion = getMaxSupportedESVersion();
+ ASSERT(maxVersion >= gl::Version(2, 0));
+ bool supportsES3 = maxVersion >= gl::Version(3, 0);
+
+ egl::Config config;
+
+ // Native stuff
+ config.nativeVisualID = 0;
+ config.nativeVisualType = 0;
+ config.nativeRenderable = EGL_TRUE;
+
+ // Buffer sizes
+ config.redSize = 8;
+ config.greenSize = 8;
+ config.blueSize = 8;
+ config.alphaSize = 8;
+ config.depthSize = 24;
+ config.stencilSize = 8;
+
+ config.colorBufferType = EGL_RGB_BUFFER;
+ config.luminanceSize = 0;
+ config.alphaMaskSize = 0;
+
+ config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize;
+
+ config.transparentType = EGL_NONE;
+
+ // Pbuffer
+ config.maxPBufferWidth = 4096;
+ config.maxPBufferHeight = 4096;
+ config.maxPBufferPixels = 4096 * 4096;
+
+ // Caveat
+ config.configCaveat = EGL_NONE;
+
+ // Misc
+ config.sampleBuffers = 0;
+ config.samples = 0;
+ config.level = 0;
+ config.bindToTextureRGB = EGL_FALSE;
+ config.bindToTextureRGBA = EGL_FALSE;
+
+ config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
+
+ config.minSwapInterval = 1;
+ config.maxSwapInterval = 1;
+
+ config.renderTargetFormat = GL_RGBA8;
+ config.depthStencilFormat = GL_DEPTH24_STENCIL8;
+
+ config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+ config.renderableType = config.conformant;
+
+ config.matchNativePixmap = EGL_NONE;
+
+ configs.add(config);
+ return configs;
+}
+
+bool DisplayCGL::testDeviceLost()
+{
+ // TODO(cwallez) investigate implementing this
+ return false;
+}
+
+egl::Error DisplayCGL::restoreLostDevice()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+bool DisplayCGL::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ // TODO(cwallez) investigate implementing this
+ return true;
+}
+
+std::string DisplayCGL::getVendorString() const
+{
+ // TODO(cwallez) find a useful vendor string
+ return "";
+}
+
+const FunctionsGL *DisplayCGL::getFunctionsGL() const
+{
+ return mFunctions;
+}
+
+void DisplayCGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+}
+
+void DisplayCGL::generateCaps(egl::Caps *outCaps) const
+{
+ outCaps->textureNPOT = true;
+}
+
+egl::Error DisplayCGL::waitClient() const
+{
+ // TODO(cwallez) UNIMPLEMENTED()
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayCGL::waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const
+{
+ // TODO(cwallez) UNIMPLEMENTED()
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayCGL::getDriverVersion(std::string *version) const
+{
+ *version = "";
+ return egl::Error(EGL_SUCCESS);
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h b/gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h
new file mode 100755
index 000000000..7cbb74da4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h
@@ -0,0 +1,65 @@
+//
+// Copyright (c) 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.
+//
+
+// PBufferSurfaceCGL.h: an implementation of egl::Surface for PBuffers for the CLG backend,
+// currently implemented using renderbuffers
+
+#ifndef LIBANGLE_RENDERER_GL_CGL_PBUFFERSURFACECGL_H_
+#define LIBANGLE_RENDERER_GL_CGL_PBUFFERSURFACECGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class PbufferSurfaceCGL : public SurfaceGL
+{
+ public:
+ PbufferSurfaceCGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLint width,
+ EGLint height,
+ const FunctionsGL *functions);
+ ~PbufferSurfaceCGL() override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+ private:
+ unsigned mWidth;
+ unsigned mHeight;
+
+ const FunctionsGL *mFunctions;
+ StateManagerGL *mStateManager;
+ RendererGL *mRenderer;
+
+ GLuint mFramebuffer;
+ GLuint mColorRenderbuffer;
+ GLuint mDSRenderbuffer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_CGL_PBUFFERSURFACECGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm b/gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm
new file mode 100755
index 000000000..c03d3836f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 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.
+//
+
+// PBufferSurfaceCGL.cpp: an implementation of egl::Surface for PBuffers for the CLG backend,
+// currently implemented using renderbuffers
+
+#include "libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+namespace rx
+{
+
+PbufferSurfaceCGL::PbufferSurfaceCGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLint width,
+ EGLint height,
+ const FunctionsGL *functions)
+ : SurfaceGL(state, renderer),
+ mWidth(width),
+ mHeight(height),
+ mFunctions(functions),
+ mStateManager(renderer->getStateManager()),
+ mRenderer(renderer),
+ mFramebuffer(0),
+ mColorRenderbuffer(0),
+ mDSRenderbuffer(0)
+{
+}
+
+PbufferSurfaceCGL::~PbufferSurfaceCGL()
+{
+ if (mFramebuffer != 0)
+ {
+ mFunctions->deleteFramebuffers(1, &mFramebuffer);
+ mFramebuffer = 0;
+ }
+
+ if (mColorRenderbuffer != 0)
+ {
+ mFunctions->deleteRenderbuffers(1, &mColorRenderbuffer);
+ mColorRenderbuffer = 0;
+ }
+ if (mDSRenderbuffer != 0)
+ {
+ mFunctions->deleteRenderbuffers(1, &mDSRenderbuffer);
+ mDSRenderbuffer = 0;
+ }
+}
+
+egl::Error PbufferSurfaceCGL::initialize()
+{
+ mFunctions->genRenderbuffers(1, &mColorRenderbuffer);
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbuffer);
+ mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, mWidth, mHeight);
+
+ mFunctions->genRenderbuffers(1, &mDSRenderbuffer);
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
+ mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mWidth, mHeight);
+
+ mFunctions->genFramebuffers(1, &mFramebuffer);
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+ mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+ mColorRenderbuffer);
+ mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, mDSRenderbuffer);
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceCGL::makeCurrent()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceCGL::swap()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceCGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceCGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceCGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceCGL::releaseTexImage(EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+void PbufferSurfaceCGL::setSwapInterval(EGLint interval)
+{
+}
+
+EGLint PbufferSurfaceCGL::getWidth() const
+{
+ return mWidth;
+}
+
+EGLint PbufferSurfaceCGL::getHeight() const
+{
+ return mHeight;
+}
+
+EGLint PbufferSurfaceCGL::isPostSubBufferSupported() const
+{
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLint PbufferSurfaceCGL::getSwapBehavior() const
+{
+ return EGL_BUFFER_PRESERVED;
+}
+
+FramebufferImpl *PbufferSurfaceCGL::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+ // TODO(cwallez) assert it happens only once?
+ return new FramebufferGL(mFramebuffer, state, mFunctions, mRenderer->getWorkarounds(),
+ mRenderer->getBlitter(), mStateManager);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h b/gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h
new file mode 100755
index 000000000..165ab0486
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h
@@ -0,0 +1,100 @@
+//
+// Copyright (c) 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.
+//
+
+// WindowSurfaceCGL.h: CGL implementation of egl::Surface for windows
+
+#ifndef LIBANGLE_RENDERER_GL_CGL_WINDOWSURFACECGL_H_
+#define LIBANGLE_RENDERER_GL_CGL_WINDOWSURFACECGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+struct _CGLContextObject;
+typedef _CGLContextObject *CGLContextObj;
+@class CALayer;
+struct __IOSurface;
+typedef __IOSurface *IOSurfaceRef;
+
+@class SwapLayer;
+
+namespace rx
+{
+
+class DisplayCGL;
+class FramebufferGL;
+class FunctionsGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+struct SharedSwapState
+{
+ struct SwapTexture
+ {
+ GLuint texture;
+ unsigned int width;
+ unsigned int height;
+ uint64_t swapId;
+ };
+
+ SwapTexture textures[3];
+
+ // This code path is not going to be used by Chrome so we take the liberty
+ // to use pthreads directly instead of using mutexes and condition variables
+ // via the Platform API.
+ pthread_mutex_t mutex;
+ // The following members should be accessed only when holding the mutex
+ // (or doing construction / destruction)
+ SwapTexture *beingRendered;
+ SwapTexture *lastRendered;
+ SwapTexture *beingPresented;
+};
+
+class WindowSurfaceCGL : public SurfaceGL
+{
+ public:
+ WindowSurfaceCGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ CALayer *layer,
+ const FunctionsGL *functions,
+ CGLContextObj context);
+ ~WindowSurfaceCGL() override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+ private:
+ SwapLayer *mSwapLayer;
+ SharedSwapState mSwapState;
+ uint64_t mCurrentSwapId;
+
+ CALayer *mLayer;
+ CGLContextObj mContext;
+ const FunctionsGL *mFunctions;
+ StateManagerGL *mStateManager;
+ RendererGL *mRenderer;
+ const WorkaroundsGL &mWorkarounds;
+
+ GLuint mFramebuffer;
+ GLuint mDSRenderbuffer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_CGL_WINDOWSURFACECGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm b/gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
new file mode 100755
index 000000000..c2ac4dca4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
@@ -0,0 +1,332 @@
+//
+// Copyright (c) 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.
+//
+
+// WindowSurfaceCGL.cpp: CGL implementation of egl::Surface for windows
+
+#include "libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h"
+
+#import <Cocoa/Cocoa.h>
+#include <OpenGL/OpenGL.h>
+#import <QuartzCore/QuartzCore.h>
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+@interface SwapLayer : CAOpenGLLayer
+{
+ CGLContextObj mDisplayContext;
+
+ bool initialized;
+ rx::SharedSwapState *mSwapState;
+ const rx::FunctionsGL *mFunctions;
+
+ GLuint mReadFramebuffer;
+}
+- (id)initWithSharedState:(rx::SharedSwapState *)swapState
+ withContext:(CGLContextObj)displayContext
+ withFunctions:(const rx::FunctionsGL *)functions;
+@end
+
+@implementation SwapLayer
+- (id)initWithSharedState:(rx::SharedSwapState *)swapState
+ withContext:(CGLContextObj)displayContext
+ withFunctions:(const rx::FunctionsGL *)functions
+ {
+ self = [super init];
+ if (self != nil)
+ {
+ self.asynchronous = YES;
+ mDisplayContext = displayContext;
+
+ initialized = false;
+ mSwapState = swapState;
+ mFunctions = functions;
+
+ [self setFrame:CGRectMake(0, 0, mSwapState->textures[0].width,
+ mSwapState->textures[0].height)];
+ }
+ return self;
+ }
+
+ - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
+ {
+ CGLPixelFormatAttribute attribs[] = {
+ kCGLPFADisplayMask, static_cast<CGLPixelFormatAttribute>(mask), kCGLPFAOpenGLProfile,
+ static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_3_2_Core),
+ static_cast<CGLPixelFormatAttribute>(0)};
+
+ CGLPixelFormatObj pixelFormat = nullptr;
+ GLint numFormats = 0;
+ CGLChoosePixelFormat(attribs, &pixelFormat, &numFormats);
+
+ return pixelFormat;
+ }
+
+ - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
+ {
+ CGLContextObj context = nullptr;
+ CGLCreateContext(pixelFormat, mDisplayContext, &context);
+ return context;
+ }
+
+ - (BOOL)canDrawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp *)timeStamp
+ {
+ BOOL result = NO;
+
+ pthread_mutex_lock(&mSwapState->mutex);
+ {
+ if (mSwapState->lastRendered->swapId > mSwapState->beingPresented->swapId)
+ {
+ std::swap(mSwapState->lastRendered, mSwapState->beingPresented);
+ result = YES;
+ }
+ }
+ pthread_mutex_unlock(&mSwapState->mutex);
+
+ return result;
+ }
+
+ - (void)drawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp *)timeStamp
+ {
+ CGLSetCurrentContext(glContext);
+ if (!initialized)
+ {
+ initialized = true;
+
+ mFunctions->genFramebuffers(1, &mReadFramebuffer);
+ }
+
+ const auto &texture = *mSwapState->beingPresented;
+ if ([self frame].size.width != texture.width || [self frame].size.height != texture.height)
+ {
+ [self setFrame:CGRectMake(0, 0, texture.width, texture.height)];
+
+ // Without this, the OSX compositor / window system doesn't see the resize.
+ [self setNeedsDisplay];
+ }
+
+ // TODO(cwallez) support 2.1 contexts too that don't have blitFramebuffer nor the
+ // GL_DRAW_FRAMEBUFFER_BINDING query
+ GLint drawFBO;
+ mFunctions->getIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFBO);
+
+ mFunctions->bindFramebuffer(GL_FRAMEBUFFER, mReadFramebuffer);
+ mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ texture.texture, 0);
+
+ mFunctions->bindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer);
+ mFunctions->bindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
+ mFunctions->blitFramebuffer(0, 0, texture.width, texture.height, 0, 0, texture.width,
+ texture.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ // Call the super method to flush the context
+ [super drawInCGLContext:glContext
+ pixelFormat:pixelFormat
+ forLayerTime:timeInterval
+ displayTime:timeStamp];
+ }
+ @end
+
+ namespace rx
+ {
+
+ WindowSurfaceCGL::WindowSurfaceCGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ CALayer *layer,
+ const FunctionsGL *functions,
+ CGLContextObj context)
+ : SurfaceGL(state, renderer),
+ mSwapLayer(nil),
+ mCurrentSwapId(0),
+ mLayer(layer),
+ mContext(context),
+ mFunctions(functions),
+ mStateManager(renderer->getStateManager()),
+ mRenderer(renderer),
+ mWorkarounds(renderer->getWorkarounds()),
+ mFramebuffer(0),
+ mDSRenderbuffer(0)
+ {
+ pthread_mutex_init(&mSwapState.mutex, nullptr);
+}
+
+WindowSurfaceCGL::~WindowSurfaceCGL()
+{
+ pthread_mutex_destroy(&mSwapState.mutex);
+ if (mFramebuffer != 0)
+ {
+ mFunctions->deleteFramebuffers(1, &mFramebuffer);
+ mFramebuffer = 0;
+ }
+
+ if (mDSRenderbuffer != 0)
+ {
+ mFunctions->deleteRenderbuffers(1, &mDSRenderbuffer);
+ mDSRenderbuffer = 0;
+ }
+
+ if (mSwapLayer != nil)
+ {
+ [mSwapLayer removeFromSuperlayer];
+ [mSwapLayer release];
+ mSwapLayer = nil;
+ }
+
+ for (size_t i = 0; i < ArraySize(mSwapState.textures); ++i)
+ {
+ if (mSwapState.textures[i].texture != 0)
+ {
+ mFunctions->deleteTextures(1, &mSwapState.textures[i].texture);
+ mSwapState.textures[i].texture = 0;
+ }
+ }
+}
+
+egl::Error WindowSurfaceCGL::initialize()
+{
+ unsigned width = getWidth();
+ unsigned height = getHeight();
+
+ for (size_t i = 0; i < ArraySize(mSwapState.textures); ++i)
+ {
+ mFunctions->genTextures(1, &mSwapState.textures[i].texture);
+ mStateManager->bindTexture(GL_TEXTURE_2D, mSwapState.textures[i].texture);
+ mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+ mSwapState.textures[i].width = width;
+ mSwapState.textures[i].height = height;
+ mSwapState.textures[i].swapId = 0;
+ }
+ mSwapState.beingRendered = &mSwapState.textures[0];
+ mSwapState.lastRendered = &mSwapState.textures[1];
+ mSwapState.beingPresented = &mSwapState.textures[2];
+
+ mSwapLayer = [[SwapLayer alloc] initWithSharedState:&mSwapState
+ withContext:mContext
+ withFunctions:mFunctions];
+ [mLayer addSublayer:mSwapLayer];
+
+ mFunctions->genRenderbuffers(1, &mDSRenderbuffer);
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
+ mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
+
+ mFunctions->genFramebuffers(1, &mFramebuffer);
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+ mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ mSwapState.beingRendered->texture, 0);
+ mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+ mDSRenderbuffer);
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceCGL::makeCurrent()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceCGL::swap()
+{
+ mFunctions->flush();
+ mSwapState.beingRendered->swapId = ++mCurrentSwapId;
+
+ pthread_mutex_lock(&mSwapState.mutex);
+ {
+ std::swap(mSwapState.beingRendered, mSwapState.lastRendered);
+ }
+ pthread_mutex_unlock(&mSwapState.mutex);
+
+ unsigned width = getWidth();
+ unsigned height = getHeight();
+ auto &texture = *mSwapState.beingRendered;
+
+ if (texture.width != width || texture.height != height)
+ {
+ mStateManager->bindTexture(GL_TEXTURE_2D, texture.texture);
+ mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
+ mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
+
+ texture.width = width;
+ texture.height = height;
+ }
+
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+ mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ mSwapState.beingRendered->texture, 0);
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceCGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceCGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceCGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceCGL::releaseTexImage(EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+void WindowSurfaceCGL::setSwapInterval(EGLint interval)
+{
+ // TODO(cwallez) investigate implementing swap intervals other than 0
+}
+
+EGLint WindowSurfaceCGL::getWidth() const
+{
+ return CGRectGetWidth([mLayer frame]);
+}
+
+EGLint WindowSurfaceCGL::getHeight() const
+{
+ return CGRectGetHeight([mLayer frame]);
+}
+
+EGLint WindowSurfaceCGL::isPostSubBufferSupported() const
+{
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLint WindowSurfaceCGL::getSwapBehavior() const
+{
+ return EGL_BUFFER_DESTROYED;
+}
+
+FramebufferImpl *WindowSurfaceCGL::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+ // TODO(cwallez) assert it happens only once?
+ return new FramebufferGL(mFramebuffer, state, mFunctions, mWorkarounds, mRenderer->getBlitter(),
+ mStateManager);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
new file mode 100755
index 000000000..988b233b4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
@@ -0,0 +1,116 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayEGL.cpp: Common across EGL parts of platform specific egl::Display implementations
+
+#include "libANGLE/renderer/gl/egl/DisplayEGL.h"
+
+namespace rx
+{
+
+#define EGL_NO_CONFIG ((EGLConfig)0)
+
+DisplayEGL::DisplayEGL()
+ : DisplayGL(),
+ mEGL(nullptr),
+ mConfig(EGL_NO_CONFIG),
+ mContext(EGL_NO_CONTEXT),
+ mFunctionsGL(nullptr)
+{
+}
+
+DisplayEGL::~DisplayEGL()
+{
+}
+
+std::string DisplayEGL::getVendorString() const
+{
+ const char *vendor = mEGL->queryString(EGL_VENDOR);
+ ASSERT(vendor);
+ return vendor;
+}
+
+egl::Error DisplayEGL::initializeContext(const egl::AttributeMap &eglAttributes)
+{
+ gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
+
+ EGLint requestedMajor =
+ eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
+ EGLint requestedMinor =
+ eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
+ bool initializeRequested = requestedMajor != EGL_DONT_CARE && requestedMinor != EGL_DONT_CARE;
+
+ static_assert(EGL_CONTEXT_MAJOR_VERSION == EGL_CONTEXT_MAJOR_VERSION_KHR,
+ "Major Version define should match");
+ static_assert(EGL_CONTEXT_MINOR_VERSION == EGL_CONTEXT_MINOR_VERSION_KHR,
+ "Minor Version define should match");
+
+ std::vector<std::vector<EGLint>> contextAttribLists;
+ if (eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_create_context"))
+ {
+ if (initializeRequested)
+ {
+ contextAttribLists.push_back({EGL_CONTEXT_MAJOR_VERSION, requestedMajor,
+ EGL_CONTEXT_MINOR_VERSION, requestedMinor, EGL_NONE});
+ }
+ else
+ {
+ // clang-format off
+ const gl::Version esVersionsFrom2_0[] = {
+ gl::Version(3, 2),
+ gl::Version(3, 1),
+ gl::Version(3, 0),
+ gl::Version(2, 0),
+ };
+ // clang-format on
+
+ for (const auto &version : esVersionsFrom2_0)
+ {
+ contextAttribLists.push_back(
+ {EGL_CONTEXT_MAJOR_VERSION, static_cast<EGLint>(version.major),
+ EGL_CONTEXT_MINOR_VERSION, static_cast<EGLint>(version.minor), EGL_NONE});
+ }
+ }
+ }
+ else
+ {
+ if (initializeRequested && (requestedMajor != 2 || requestedMinor != 0))
+ {
+ return egl::Error(EGL_BAD_ATTRIBUTE, "Unsupported requested context version");
+ }
+ contextAttribLists.push_back({EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE});
+ }
+
+ for (auto &attribList : contextAttribLists)
+ {
+ mContext = mEGL->createContext(mConfig, EGL_NO_CONTEXT, attribList.data());
+ if (mContext != EGL_NO_CONTEXT)
+ {
+ return egl::Error(EGL_SUCCESS);
+ }
+ }
+
+ return egl::Error(mEGL->getError(), "eglCreateContext failed");
+}
+
+void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ outExtensions->createContextRobustness =
+ mEGL->hasExtension("EGL_EXT_create_context_robustness");
+
+ outExtensions->postSubBuffer = false; // Since SurfaceEGL::postSubBuffer is not implemented
+}
+
+void DisplayEGL::generateCaps(egl::Caps *outCaps) const
+{
+ outCaps->textureNPOT = true; // Since we request GLES >= 2
+}
+
+const FunctionsGL *DisplayEGL::getFunctionsGL() const
+{
+ return mFunctionsGL;
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h
new file mode 100755
index 000000000..e498cd79a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayEGL.h: Common across EGL parts of platform specific egl::Display implementations
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_DISPLAYEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_DISPLAYEGL_H_
+
+#include "libANGLE/renderer/gl/DisplayGL.h"
+#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
+
+namespace rx
+{
+
+class DisplayEGL : public DisplayGL
+{
+ public:
+ DisplayEGL();
+ ~DisplayEGL() override;
+
+ std::string getVendorString() const override;
+
+ protected:
+ egl::Error initializeContext(const egl::AttributeMap &eglAttributes);
+
+ FunctionsEGL *mEGL;
+ EGLConfig mConfig;
+ EGLContext mContext;
+ FunctionsGL *mFunctionsGL;
+
+ private:
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+ void generateCaps(egl::Caps *outCaps) const override;
+
+ const FunctionsGL *getFunctionsGL() const override;
+};
+
+} // namespace rx
+
+#endif /* LIBANGLE_RENDERER_GL_EGL_DISPLAYEGL_H_ */
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp
new file mode 100755
index 000000000..c0b0f846f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp
@@ -0,0 +1,340 @@
+//
+// Copyright (c) 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.
+//
+
+// FunctionsEGL.cpp: Implements the FunctionsEGL class.
+
+#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
+
+#include <algorithm>
+
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/egl/functionsegl_typedefs.h"
+#include "common/string_utils.h"
+
+namespace
+{
+
+template <typename T>
+bool SetPtr(T *dst, void *src)
+{
+ if (src)
+ {
+ *dst = reinterpret_cast<T>(src);
+ return true;
+ }
+ return false;
+}
+} // namespace
+
+namespace rx
+{
+
+struct FunctionsEGL::EGLDispatchTable
+{
+ EGLDispatchTable()
+ : bindAPIPtr(nullptr),
+ chooseConfigPtr(nullptr),
+ createContextPtr(nullptr),
+ createPbufferSurfacePtr(nullptr),
+ createWindowSurfacePtr(nullptr),
+ destroyContextPtr(nullptr),
+ destroySurfacePtr(nullptr),
+ getConfigAttribPtr(nullptr),
+ getDisplayPtr(nullptr),
+ getErrorPtr(nullptr),
+ initializePtr(nullptr),
+ makeCurrentPtr(nullptr),
+ queryStringPtr(nullptr),
+ querySurfacePtr(nullptr),
+ swapBuffersPtr(nullptr),
+ terminatePtr(nullptr),
+
+ bindTexImagePtr(nullptr),
+ releaseTexImagePtr(nullptr),
+ swapIntervalPtr(nullptr),
+
+ createImageKHRPtr(nullptr),
+ destroyImageKHRPtr(nullptr),
+
+ clientWaitSyncKHRPtr(nullptr),
+ createSyncKHRPtr(nullptr),
+ destroySyncKHRPtr(nullptr),
+ getSyncAttribKHRPtr(nullptr)
+ {
+ }
+
+ // 1.0
+ PFNEGLBINDAPIPROC bindAPIPtr;
+ PFNEGLCHOOSECONFIGPROC chooseConfigPtr;
+ PFNEGLCREATECONTEXTPROC createContextPtr;
+ PFNEGLCREATEPBUFFERSURFACEPROC createPbufferSurfacePtr;
+ PFNEGLCREATEWINDOWSURFACEPROC createWindowSurfacePtr;
+ PFNEGLDESTROYCONTEXTPROC destroyContextPtr;
+ PFNEGLDESTROYSURFACEPROC destroySurfacePtr;
+ PFNEGLGETCONFIGATTRIBPROC getConfigAttribPtr;
+ PFNEGLGETDISPLAYPROC getDisplayPtr;
+ PFNEGLGETERRORPROC getErrorPtr;
+ PFNEGLINITIALIZEPROC initializePtr;
+ PFNEGLMAKECURRENTPROC makeCurrentPtr;
+ PFNEGLQUERYSTRINGPROC queryStringPtr;
+ PFNEGLQUERYSURFACEPROC querySurfacePtr;
+ PFNEGLSWAPBUFFERSPROC swapBuffersPtr;
+ PFNEGLTERMINATEPROC terminatePtr;
+
+ // 1.1
+ PFNEGLBINDTEXIMAGEPROC bindTexImagePtr;
+ PFNEGLRELEASETEXIMAGEPROC releaseTexImagePtr;
+ PFNEGLSWAPINTERVALPROC swapIntervalPtr;
+
+ // EGL_KHR_image
+ PFNEGLCREATEIMAGEKHRPROC createImageKHRPtr;
+ PFNEGLDESTROYIMAGEKHRPROC destroyImageKHRPtr;
+
+ // EGL_KHR_fence_sync
+ PFNEGLCLIENTWAITSYNCKHRPROC clientWaitSyncKHRPtr;
+ PFNEGLCREATESYNCKHRPROC createSyncKHRPtr;
+ PFNEGLDESTROYSYNCKHRPROC destroySyncKHRPtr;
+ PFNEGLGETSYNCATTRIBKHRPROC getSyncAttribKHRPtr;
+};
+
+FunctionsEGL::FunctionsEGL()
+ : majorVersion(0), minorVersion(0), mFnPtrs(new EGLDispatchTable()), mEGLDisplay(EGL_NO_DISPLAY)
+{
+}
+
+FunctionsEGL::~FunctionsEGL()
+{
+ SafeDelete(mFnPtrs);
+}
+
+egl::Error FunctionsEGL::initialize(EGLNativeDisplayType nativeDisplay)
+{
+#define ANGLE_GET_PROC_OR_ERROR(MEMBER, NAME) \
+ if (!SetPtr(MEMBER, getProcAddress(#NAME))) \
+ { \
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not load EGL entry point " #NAME); \
+ }
+
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->bindAPIPtr, eglBindAPI);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->chooseConfigPtr, eglChooseConfig);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createContextPtr, eglCreateContext);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createPbufferSurfacePtr, eglCreatePbufferSurface);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createWindowSurfacePtr, eglCreateWindowSurface);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroyContextPtr, eglDestroyContext);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroySurfacePtr, eglDestroySurface);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getConfigAttribPtr, eglGetConfigAttrib);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getDisplayPtr, eglGetDisplay);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getErrorPtr, eglGetError);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->initializePtr, eglInitialize);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->makeCurrentPtr, eglMakeCurrent);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->queryStringPtr, eglQueryString);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->querySurfacePtr, eglQuerySurface);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->swapBuffersPtr, eglSwapBuffers);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->terminatePtr, eglTerminate);
+
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->bindTexImagePtr, eglBindTexImage);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->releaseTexImagePtr, eglReleaseTexImage);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalPtr, eglSwapInterval);
+
+ mEGLDisplay = mFnPtrs->getDisplayPtr(nativeDisplay);
+ if (mEGLDisplay == EGL_NO_DISPLAY)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to get system egl display");
+ }
+ if (mFnPtrs->initializePtr(mEGLDisplay, &majorVersion, &minorVersion) != EGL_TRUE)
+ {
+ return egl::Error(mFnPtrs->getErrorPtr(), "Failed to initialize system egl");
+ }
+ if (majorVersion < 1 || (majorVersion == 1 && minorVersion < 4))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Unsupported EGL version (require at least 1.4).");
+ }
+ if (mFnPtrs->bindAPIPtr(EGL_OPENGL_ES_API) != EGL_TRUE)
+ {
+ return egl::Error(mFnPtrs->getErrorPtr(), "Failed to bind API in system egl");
+ }
+
+ const char *extensions = queryString(EGL_EXTENSIONS);
+ if (!extensions)
+ {
+ return egl::Error(mFnPtrs->getErrorPtr(), "Faild to query extensions in system egl");
+ }
+ angle::SplitStringAlongWhitespace(extensions, &mExtensions);
+
+ if (hasExtension("EGL_KHR_image_base"))
+ {
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createImageKHRPtr, eglCreateImageKHR);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroyImageKHRPtr, eglDestroyImageKHR);
+ }
+ if (hasExtension("EGL_KHR_fence_sync"))
+ {
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->clientWaitSyncKHRPtr, eglClientWaitSyncKHR);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createSyncKHRPtr, eglCreateSyncKHR);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroySyncKHRPtr, eglDestroySyncKHR);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getSyncAttribKHRPtr, eglGetSyncAttribKHR);
+ }
+
+#undef ANGLE_GET_PROC_OR_ERROR
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error FunctionsEGL::terminate()
+{
+ if (mFnPtrs->terminatePtr(mEGLDisplay) == EGL_TRUE)
+ {
+ mEGLDisplay = nullptr;
+ return egl::Error(EGL_SUCCESS);
+ }
+ return egl::Error(mFnPtrs->getErrorPtr());
+}
+
+class FunctionsGLEGL : public FunctionsGL
+{
+ public:
+ FunctionsGLEGL(const FunctionsEGL &egl) : mEGL(egl) {}
+
+ ~FunctionsGLEGL() override {}
+
+ private:
+ void *loadProcAddress(const std::string &function) override
+ {
+ return mEGL.getProcAddress(function.c_str());
+ }
+
+ const FunctionsEGL &mEGL;
+};
+
+FunctionsGL *FunctionsEGL::makeFunctionsGL(void) const
+{
+ return new FunctionsGLEGL(*this);
+}
+
+bool FunctionsEGL::hasExtension(const char *extension) const
+{
+ return std::find(mExtensions.begin(), mExtensions.end(), extension) != mExtensions.end();
+}
+
+EGLDisplay FunctionsEGL::getDisplay() const
+{
+ return mEGLDisplay;
+}
+
+EGLint FunctionsEGL::getError() const
+{
+ return mFnPtrs->getErrorPtr();
+}
+
+EGLBoolean FunctionsEGL::chooseConfig(EGLint const *attribList,
+ EGLConfig *configs,
+ EGLint configSize,
+ EGLint *numConfig) const
+{
+ return mFnPtrs->chooseConfigPtr(mEGLDisplay, attribList, configs, configSize, numConfig);
+}
+
+EGLBoolean FunctionsEGL::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) const
+{
+ return mFnPtrs->getConfigAttribPtr(mEGLDisplay, config, attribute, value);
+}
+
+EGLContext FunctionsEGL::createContext(EGLConfig config,
+ EGLContext share_context,
+ EGLint const *attrib_list) const
+{
+ return mFnPtrs->createContextPtr(mEGLDisplay, config, share_context, attrib_list);
+}
+
+EGLSurface FunctionsEGL::createPbufferSurface(EGLConfig config, const EGLint *attrib_list) const
+{
+ return mFnPtrs->createPbufferSurfacePtr(mEGLDisplay, config, attrib_list);
+}
+
+EGLSurface FunctionsEGL::createWindowSurface(EGLConfig config,
+ EGLNativeWindowType win,
+ const EGLint *attrib_list) const
+{
+ return mFnPtrs->createWindowSurfacePtr(mEGLDisplay, config, win, attrib_list);
+}
+
+EGLBoolean FunctionsEGL::destroyContext(EGLContext context) const
+{
+ return mFnPtrs->destroyContextPtr(mEGLDisplay, context);
+}
+
+EGLBoolean FunctionsEGL::destroySurface(EGLSurface surface) const
+{
+ return mFnPtrs->destroySurfacePtr(mEGLDisplay, surface);
+}
+
+EGLBoolean FunctionsEGL::makeCurrent(EGLSurface surface, EGLContext context) const
+{
+ return mFnPtrs->makeCurrentPtr(mEGLDisplay, surface, surface, context);
+}
+
+char const *FunctionsEGL::queryString(EGLint name) const
+{
+ return mFnPtrs->queryStringPtr(mEGLDisplay, name);
+}
+
+EGLBoolean FunctionsEGL::querySurface(EGLSurface surface, EGLint attribute, EGLint *value) const
+{
+ return mFnPtrs->querySurfacePtr(mEGLDisplay, surface, attribute, value);
+}
+
+EGLBoolean FunctionsEGL::swapBuffers(EGLSurface surface) const
+{
+ return mFnPtrs->swapBuffersPtr(mEGLDisplay, surface);
+}
+
+EGLBoolean FunctionsEGL::bindTexImage(EGLSurface surface, EGLint buffer) const
+{
+ return mFnPtrs->bindTexImagePtr(mEGLDisplay, surface, buffer);
+}
+
+EGLBoolean FunctionsEGL::releaseTexImage(EGLSurface surface, EGLint buffer) const
+{
+ return mFnPtrs->releaseTexImagePtr(mEGLDisplay, surface, buffer);
+}
+
+EGLBoolean FunctionsEGL::swapInterval(EGLint interval) const
+{
+ return mFnPtrs->swapIntervalPtr(mEGLDisplay, interval);
+}
+
+EGLImageKHR FunctionsEGL::createImageKHR(EGLContext context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const EGLint *attrib_list) const
+{
+ return mFnPtrs->createImageKHRPtr(mEGLDisplay, context, target, buffer, attrib_list);
+}
+
+EGLBoolean FunctionsEGL::destroyImageKHR(EGLImageKHR image) const
+{
+ return mFnPtrs->destroyImageKHRPtr(mEGLDisplay, image);
+}
+
+EGLSyncKHR FunctionsEGL::createSyncKHR(EGLenum type, const EGLint *attrib_list)
+{
+ return mFnPtrs->createSyncKHRPtr(mEGLDisplay, type, attrib_list);
+}
+
+EGLBoolean FunctionsEGL::destroySyncKHR(EGLSyncKHR sync)
+{
+ return mFnPtrs->destroySyncKHRPtr(mEGLDisplay, sync);
+}
+
+EGLint FunctionsEGL::clientWaitSyncKHR(EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
+{
+ return mFnPtrs->clientWaitSyncKHRPtr(mEGLDisplay, sync, flags, timeout);
+}
+
+EGLBoolean FunctionsEGL::getSyncAttribKHR(EGLSyncKHR sync, EGLint attribute, EGLint *value)
+{
+ return mFnPtrs->getSyncAttribKHRPtr(mEGLDisplay, sync, attribute, value);
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h
new file mode 100755
index 000000000..43d5622e6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 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.
+//
+
+// FunctionsEGL.h: Defines the FunctionsEGL class to load functions and data from EGL
+
+#ifndef LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGL_H_
+#define LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGL_H_
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <string>
+#include <vector>
+
+#include "libANGLE/Error.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+
+class FunctionsEGL
+{
+ public:
+ FunctionsEGL();
+ virtual ~FunctionsEGL();
+
+ int majorVersion;
+ int minorVersion;
+
+ egl::Error initialize(EGLNativeDisplayType nativeDisplay);
+ egl::Error terminate();
+
+ virtual void *getProcAddress(const char *name) const = 0;
+
+ FunctionsGL *makeFunctionsGL() const;
+ bool hasExtension(const char *extension) const;
+ EGLDisplay getDisplay() const;
+ EGLint getError() const;
+
+ EGLBoolean chooseConfig(EGLint const *attrib_list,
+ EGLConfig *configs,
+ EGLint config_size,
+ EGLint *num_config) const;
+ EGLBoolean getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) const;
+ EGLContext createContext(EGLConfig config,
+ EGLContext share_context,
+ EGLint const *attrib_list) const;
+ EGLSurface createPbufferSurface(EGLConfig config, const EGLint *attrib_list) const;
+ EGLSurface createWindowSurface(EGLConfig config,
+ EGLNativeWindowType win,
+ const EGLint *attrib_list) const;
+ EGLBoolean destroyContext(EGLContext context) const;
+ EGLBoolean destroySurface(EGLSurface surface) const;
+ EGLBoolean makeCurrent(EGLSurface surface, EGLContext context) const;
+ const char *queryString(EGLint name) const;
+ EGLBoolean querySurface(EGLSurface surface, EGLint attribute, EGLint *value) const;
+ EGLBoolean swapBuffers(EGLSurface surface) const;
+
+ EGLBoolean bindTexImage(EGLSurface surface, EGLint buffer) const;
+ EGLBoolean releaseTexImage(EGLSurface surface, EGLint buffer) const;
+ EGLBoolean swapInterval(EGLint interval) const;
+
+ EGLImageKHR createImageKHR(EGLContext context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const EGLint *attrib_list) const;
+ EGLBoolean destroyImageKHR(EGLImageKHR image) const;
+
+ EGLSyncKHR createSyncKHR(EGLenum type, const EGLint *attrib_list);
+ EGLBoolean destroySyncKHR(EGLSyncKHR sync);
+ EGLint clientWaitSyncKHR(EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+ EGLBoolean getSyncAttribKHR(EGLSyncKHR sync, EGLint attribute, EGLint *value);
+
+ private:
+ // So as to isolate from angle we do not include angleutils.h and cannot
+ // use angle::NonCopyable so we replicated it here instead.
+ FunctionsEGL(const FunctionsEGL &) = delete;
+ void operator=(const FunctionsEGL &) = delete;
+
+ struct EGLDispatchTable;
+ EGLDispatchTable *mFnPtrs;
+ EGLDisplay mEGLDisplay;
+ std::vector<std::string> mExtensions;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp
new file mode 100755
index 000000000..e6ef45d8d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 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.
+//
+
+// FunctionsEGLDL.cpp: Implements the FunctionsEGLDL class.
+
+#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
+
+#include <dlfcn.h>
+
+namespace rx
+{
+
+DynamicLib::DynamicLib() : handle(nullptr)
+{
+}
+
+DynamicLib::~DynamicLib()
+{
+ if (handle)
+ {
+ dlclose(handle);
+ handle = nullptr;
+ }
+}
+
+// Due to a bug in Mesa (or maybe libdl) it's not possible to close and re-open libEGL.so
+// an arbitrary number of times. End2end tests would die after a couple hundred tests.
+// So we use a static object with a destructor to close the library when the program exits.
+// TODO(fjhenigman) File a bug and put a link here.
+DynamicLib FunctionsEGLDL::sNativeLib;
+
+FunctionsEGLDL::FunctionsEGLDL() : mGetProcAddressPtr(nullptr)
+{
+}
+
+FunctionsEGLDL::~FunctionsEGLDL()
+{
+}
+
+egl::Error FunctionsEGLDL::initialize(EGLNativeDisplayType nativeDisplay, const char *libName)
+{
+ if (!sNativeLib.handle)
+ {
+ sNativeLib.handle = dlopen(libName, RTLD_NOW);
+ if (!sNativeLib.handle)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not dlopen native EGL: %s", dlerror());
+ }
+ }
+
+ mGetProcAddressPtr =
+ reinterpret_cast<PFNEGLGETPROCADDRESSPROC>(dlsym(sNativeLib.handle, "eglGetProcAddress"));
+ if (!mGetProcAddressPtr)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not find eglGetProcAddress");
+ }
+
+ return FunctionsEGL::initialize(nativeDisplay);
+}
+
+void *FunctionsEGLDL::getProcAddress(const char *name) const
+{
+ void *f = reinterpret_cast<void *>(mGetProcAddressPtr(name));
+ if (f)
+ {
+ return f;
+ }
+ return dlsym(sNativeLib.handle, name);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h
new file mode 100755
index 000000000..d69df77ab
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h
@@ -0,0 +1,42 @@
+//
+// Copyright (c) 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.
+//
+
+// FunctionsEGL.h: Implements FunctionsEGL with dlopen/dlsym/dlclose
+
+#ifndef LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGLDL_H_
+#define LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGLDL_H_
+
+#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
+#include "libANGLE/renderer/gl/egl/functionsegl_typedefs.h"
+
+namespace rx
+{
+
+class DynamicLib final
+{
+ public:
+ void *handle;
+
+ DynamicLib();
+ ~DynamicLib();
+};
+
+class FunctionsEGLDL : public FunctionsEGL
+{
+ public:
+ FunctionsEGLDL();
+ ~FunctionsEGLDL() override;
+
+ egl::Error initialize(EGLNativeDisplayType nativeDisplay, const char *libName);
+ void *getProcAddress(const char *name) const override;
+
+ private:
+ PFNEGLGETPROCADDRESSPROC mGetProcAddressPtr;
+ static DynamicLib sNativeLib;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGLDL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp
new file mode 100755
index 000000000..68da9f2b8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 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.
+//
+
+// PbufferSurfaceEGL.h: EGL implementation of egl::Surface for pbuffers
+
+#include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h"
+
+namespace rx
+{
+
+PbufferSurfaceEGL::PbufferSurfaceEGL(const egl::SurfaceState &state,
+ const FunctionsEGL *egl,
+ EGLConfig config,
+ const std::vector<EGLint> &attribList,
+ EGLContext context,
+ RendererGL *renderer)
+ : SurfaceEGL(state, egl, config, attribList, context, renderer)
+{
+}
+
+PbufferSurfaceEGL::~PbufferSurfaceEGL()
+{
+}
+
+egl::Error PbufferSurfaceEGL::initialize()
+{
+ mSurface = mEGL->createPbufferSurface(mConfig, mAttribList.data());
+ if (mSurface == EGL_NO_SURFACE)
+ {
+ return egl::Error(mEGL->getError(), "eglCreatePbufferSurface failed");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h
new file mode 100755
index 000000000..ff557f2ca
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 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.
+//
+
+// PbufferSurfaceEGL.h: EGL implementation of egl::Surface for pbuffers
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_PBUFFERSURFACEEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_PBUFFERSURFACEEGL_H_
+
+#include <vector>
+#include <EGL/egl.h>
+
+#include "libANGLE/renderer/gl/egl/SurfaceEGL.h"
+
+namespace rx
+{
+
+class PbufferSurfaceEGL : public SurfaceEGL
+{
+ public:
+ PbufferSurfaceEGL(const egl::SurfaceState &state,
+ const FunctionsEGL *egl,
+ EGLConfig config,
+ const std::vector<EGLint> &attribList,
+ EGLContext context,
+ RendererGL *renderer);
+ ~PbufferSurfaceEGL() override;
+
+ egl::Error initialize() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_PBUFFERSURFACEEGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp
new file mode 100755
index 000000000..693b61c9c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp
@@ -0,0 +1,132 @@
+//
+// Copyright (c) 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.
+//
+
+// SurfaceEGL.cpp: EGL implementation of egl::Surface
+
+#include "libANGLE/renderer/gl/egl/SurfaceEGL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+SurfaceEGL::SurfaceEGL(const egl::SurfaceState &state,
+ const FunctionsEGL *egl,
+ EGLConfig config,
+ const std::vector<EGLint> &attribList,
+ EGLContext context,
+ RendererGL *renderer)
+ : SurfaceGL(state, renderer),
+ mEGL(egl),
+ mConfig(config),
+ mAttribList(attribList),
+ mSurface(EGL_NO_SURFACE),
+ mContext(context)
+{
+}
+
+SurfaceEGL::~SurfaceEGL()
+{
+ if (mSurface != EGL_NO_SURFACE)
+ {
+ EGLBoolean success = mEGL->destroySurface(mSurface);
+ ASSERT(success == EGL_TRUE);
+ }
+}
+
+egl::Error SurfaceEGL::makeCurrent()
+{
+ EGLBoolean success = mEGL->makeCurrent(mSurface, mContext);
+ if (success == EGL_FALSE)
+ {
+ return egl::Error(mEGL->getError(), "eglMakeCurrent failed");
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceEGL::swap()
+{
+ EGLBoolean success = mEGL->swapBuffers(mSurface);
+ if (success == EGL_FALSE)
+ {
+ return egl::Error(mEGL->getError(), "eglSwapBuffers failed");
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceEGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_SURFACE);
+}
+
+egl::Error SurfaceEGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_SURFACE);
+}
+
+egl::Error SurfaceEGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ EGLBoolean success = mEGL->bindTexImage(mSurface, buffer);
+ if (success == EGL_FALSE)
+ {
+ return egl::Error(mEGL->getError(), "eglBindTexImage failed");
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceEGL::releaseTexImage(EGLint buffer)
+{
+ EGLBoolean success = mEGL->releaseTexImage(mSurface, buffer);
+ if (success == EGL_FALSE)
+ {
+ return egl::Error(mEGL->getError(), "eglReleaseTexImage failed");
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+void SurfaceEGL::setSwapInterval(EGLint interval)
+{
+ EGLBoolean success = mEGL->swapInterval(interval);
+ if (success == EGL_FALSE)
+ {
+ ERR("eglSwapInterval error 0x%04x", mEGL->getError());
+ ASSERT(false);
+ }
+}
+
+EGLint SurfaceEGL::getWidth() const
+{
+ EGLint value;
+ EGLBoolean success = mEGL->querySurface(mSurface, EGL_WIDTH, &value);
+ ASSERT(success == EGL_TRUE);
+ return value;
+}
+
+EGLint SurfaceEGL::getHeight() const
+{
+ EGLint value;
+ EGLBoolean success = mEGL->querySurface(mSurface, EGL_HEIGHT, &value);
+ ASSERT(success == EGL_TRUE);
+ return value;
+}
+
+EGLint SurfaceEGL::isPostSubBufferSupported() const
+{
+ UNIMPLEMENTED();
+ return 0;
+}
+
+EGLint SurfaceEGL::getSwapBehavior() const
+{
+ EGLint value;
+ EGLBoolean success = mEGL->querySurface(mSurface, EGL_SWAP_BEHAVIOR, &value);
+ ASSERT(success == EGL_TRUE);
+ return value;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h
new file mode 100755
index 000000000..ee1568c9e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h
@@ -0,0 +1,55 @@
+//
+// Copyright (c) 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.
+//
+
+// SurfaceEGL.h: common interface for EGL surfaces
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_SURFACEEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_SURFACEEGL_H_
+
+#include <EGL/egl.h>
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
+
+namespace rx
+{
+
+class SurfaceEGL : public SurfaceGL
+{
+ public:
+ SurfaceEGL(const egl::SurfaceState &state,
+ const FunctionsEGL *egl,
+ EGLConfig config,
+ const std::vector<EGLint> &attribList,
+ EGLContext context,
+ RendererGL *renderer);
+ ~SurfaceEGL() override;
+
+ egl::Error makeCurrent() override;
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ protected:
+ const FunctionsEGL *mEGL;
+ EGLConfig mConfig;
+ std::vector<EGLint> mAttribList;
+ EGLSurface mSurface;
+
+ private:
+ EGLContext mContext;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_SURFACEEGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp
new file mode 100755
index 000000000..db226ee18
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 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.
+//
+
+// WindowSurfaceEGL.h: EGL implementation of egl::Surface for windows
+
+#include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h"
+
+namespace rx
+{
+
+WindowSurfaceEGL::WindowSurfaceEGL(const egl::SurfaceState &state,
+ const FunctionsEGL *egl,
+ EGLConfig config,
+ EGLNativeWindowType window,
+ const std::vector<EGLint> &attribList,
+ EGLContext context,
+ RendererGL *renderer)
+ : SurfaceEGL(state, egl, config, attribList, context, renderer), mWindow(window)
+{
+}
+
+WindowSurfaceEGL::~WindowSurfaceEGL()
+{
+}
+
+egl::Error WindowSurfaceEGL::initialize()
+{
+ mSurface = mEGL->createWindowSurface(mConfig, mWindow, mAttribList.data());
+ if (mSurface == EGL_NO_SURFACE)
+ {
+ return egl::Error(mEGL->getError(), "eglCreateWindowSurface failed");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h
new file mode 100755
index 000000000..f9da4c27c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 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.
+//
+
+// WindowSurfaceEGL.h: EGL implementation of egl::Surface for windows
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_WINDOWSURFACEEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_WINDOWSURFACEEGL_H_
+
+#include "libANGLE/renderer/gl/egl/SurfaceEGL.h"
+
+namespace rx
+{
+
+class WindowSurfaceEGL : public SurfaceEGL
+{
+ public:
+ WindowSurfaceEGL(const egl::SurfaceState &state,
+ const FunctionsEGL *egl,
+ EGLConfig config,
+ EGLNativeWindowType window,
+ const std::vector<EGLint> &attribList,
+ EGLContext context,
+ RendererGL *renderer);
+ ~WindowSurfaceEGL() override;
+
+ egl::Error initialize() override;
+
+ private:
+ EGLNativeWindowType mWindow;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_WINDOWSURFACEEGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
new file mode 100755
index 000000000..b689578c9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
@@ -0,0 +1,385 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayAndroid.cpp: Android implementation of egl::Display
+
+#include <android/native_window.h>
+
+#include "common/debug.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+#include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h"
+#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
+#include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h"
+#include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h"
+
+namespace
+{
+const char *GetEGLPath()
+{
+#if defined(__LP64__)
+ return "/system/lib64/libEGL.so";
+#else
+ return "/system/lib/libEGL.so";
+#endif
+}
+} // namespace
+
+namespace rx
+{
+
+DisplayAndroid::DisplayAndroid() : DisplayEGL(), mDummyPbuffer(EGL_NO_SURFACE)
+{
+}
+
+DisplayAndroid::~DisplayAndroid()
+{
+}
+
+egl::Error DisplayAndroid::initialize(egl::Display *display)
+{
+ FunctionsEGLDL *egl = new FunctionsEGLDL();
+ mEGL = egl;
+ ANGLE_TRY(egl->initialize(display->getNativeDisplayId(), GetEGLPath()));
+
+ gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
+ ASSERT(eglVersion >= gl::Version(1, 4));
+
+ static_assert(EGL_OPENGL_ES3_BIT == EGL_OPENGL_ES3_BIT_KHR, "Extension define must match core");
+ EGLint esBit = (eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_create_context"))
+ ? EGL_OPENGL_ES3_BIT
+ : EGL_OPENGL_ES2_BIT;
+
+ // clang-format off
+ mConfigAttribList =
+ {
+ // Choose RGBA8888
+ EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ // EGL1.5 spec Section 2.2 says that depth, multisample and stencil buffer depths
+ // must match for contexts to be compatible.
+ EGL_DEPTH_SIZE, 24,
+ EGL_STENCIL_SIZE, 8,
+ EGL_SAMPLE_BUFFERS, 0,
+ // Android doesn't support pixmaps
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_CONFORMANT, esBit,
+ EGL_RENDERABLE_TYPE, esBit,
+ EGL_NONE
+ };
+ // clang-format on
+ EGLint numConfig;
+
+ EGLBoolean success = mEGL->chooseConfig(mConfigAttribList.data(), &mConfig, 1, &numConfig);
+ if (success == EGL_FALSE)
+ {
+ return egl::Error(mEGL->getError(), "eglChooseConfig failed");
+ }
+
+ ANGLE_TRY(initializeContext(display->getAttributeMap()));
+
+ int dummyPbufferAttribs[] = {
+ EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE,
+ };
+ mDummyPbuffer = mEGL->createPbufferSurface(mConfig, dummyPbufferAttribs);
+ if (mDummyPbuffer == EGL_NO_SURFACE)
+ {
+ return egl::Error(mEGL->getError(), "eglCreatePbufferSurface failed");
+ }
+
+ success = mEGL->makeCurrent(mDummyPbuffer, mContext);
+ if (success == EGL_FALSE)
+ {
+ return egl::Error(mEGL->getError(), "eglMakeCurrent failed");
+ }
+
+ mFunctionsGL = mEGL->makeFunctionsGL();
+ mFunctionsGL->initialize();
+
+ return DisplayGL::initialize(display);
+}
+
+void DisplayAndroid::terminate()
+{
+ DisplayGL::terminate();
+
+ EGLBoolean success = mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (success == EGL_FALSE)
+ {
+ ERR("eglMakeCurrent error 0x%04x", mEGL->getError());
+ }
+
+ if (mDummyPbuffer != EGL_NO_SURFACE)
+ {
+ success = mEGL->destroySurface(mDummyPbuffer);
+ mDummyPbuffer = EGL_NO_SURFACE;
+ if (success == EGL_FALSE)
+ {
+ ERR("eglDestroySurface error 0x%04x", mEGL->getError());
+ }
+ }
+
+ if (mContext != EGL_NO_CONTEXT)
+ {
+ success = mEGL->destroyContext(mContext);
+ mContext = EGL_NO_CONTEXT;
+ if (success == EGL_FALSE)
+ {
+ ERR("eglDestroyContext error 0x%04x", mEGL->getError());
+ }
+ }
+
+ egl::Error result = mEGL->terminate();
+ if (result.isError())
+ {
+ ERR("eglTerminate error 0x%04x", result.getCode());
+ }
+
+ SafeDelete(mEGL);
+ SafeDelete(mFunctionsGL);
+}
+
+SurfaceImpl *DisplayAndroid::createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ EGLConfig config;
+ EGLint numConfig;
+ EGLBoolean success;
+
+ const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[configuration->configID],
+ EGL_NONE};
+ success = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig);
+ ASSERT(success && numConfig == 1);
+
+ return new WindowSurfaceEGL(state, mEGL, config, window, attribs.toIntVector(), mContext,
+ getRenderer());
+}
+
+SurfaceImpl *DisplayAndroid::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs)
+{
+ EGLConfig config;
+ EGLint numConfig;
+ EGLBoolean success;
+
+ const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[configuration->configID],
+ EGL_NONE};
+ success = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig);
+ ASSERT(success && numConfig == 1);
+
+ return new PbufferSurfaceEGL(state, mEGL, config, attribs.toIntVector(), mContext,
+ getRenderer());
+}
+
+SurfaceImpl *DisplayAndroid::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+SurfaceImpl *DisplayAndroid::createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+ImageImpl *DisplayAndroid::createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return DisplayGL::createImage(target, buffer, attribs);
+}
+
+template <typename T>
+void DisplayAndroid::getConfigAttrib(EGLConfig config, EGLint attribute, T *value) const
+{
+ EGLint tmp;
+ EGLBoolean success = mEGL->getConfigAttrib(config, attribute, &tmp);
+ ASSERT(success == EGL_TRUE);
+ *value = tmp;
+}
+
+egl::ConfigSet DisplayAndroid::generateConfigs()
+{
+ egl::ConfigSet configSet;
+ mConfigIds.clear();
+
+ EGLint numConfigs;
+ EGLBoolean success = mEGL->chooseConfig(mConfigAttribList.data(), nullptr, 0, &numConfigs);
+ ASSERT(success == EGL_TRUE && numConfigs > 0);
+
+ std::vector<EGLConfig> configs(numConfigs);
+ EGLint numConfigs2;
+ success =
+ mEGL->chooseConfig(mConfigAttribList.data(), configs.data(), numConfigs, &numConfigs2);
+ ASSERT(success == EGL_TRUE && numConfigs2 == numConfigs);
+
+ for (int i = 0; i < numConfigs; i++)
+ {
+ egl::Config config;
+
+ getConfigAttrib(configs[i], EGL_BUFFER_SIZE, &config.bufferSize);
+ getConfigAttrib(configs[i], EGL_RED_SIZE, &config.redSize);
+ getConfigAttrib(configs[i], EGL_GREEN_SIZE, &config.greenSize);
+ getConfigAttrib(configs[i], EGL_BLUE_SIZE, &config.blueSize);
+ getConfigAttrib(configs[i], EGL_LUMINANCE_SIZE, &config.luminanceSize);
+ getConfigAttrib(configs[i], EGL_ALPHA_SIZE, &config.alphaSize);
+ getConfigAttrib(configs[i], EGL_ALPHA_MASK_SIZE, &config.alphaMaskSize);
+ getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGB, &config.bindToTextureRGB);
+ getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGBA, &config.bindToTextureRGBA);
+ getConfigAttrib(configs[i], EGL_COLOR_BUFFER_TYPE, &config.colorBufferType);
+ getConfigAttrib(configs[i], EGL_CONFIG_CAVEAT, &config.configCaveat);
+ getConfigAttrib(configs[i], EGL_CONFIG_ID, &config.configID);
+ getConfigAttrib(configs[i], EGL_CONFORMANT, &config.conformant);
+ getConfigAttrib(configs[i], EGL_DEPTH_SIZE, &config.depthSize);
+ getConfigAttrib(configs[i], EGL_LEVEL, &config.level);
+ getConfigAttrib(configs[i], EGL_MAX_PBUFFER_WIDTH, &config.maxPBufferWidth);
+ getConfigAttrib(configs[i], EGL_MAX_PBUFFER_HEIGHT, &config.maxPBufferHeight);
+ getConfigAttrib(configs[i], EGL_MAX_PBUFFER_PIXELS, &config.maxPBufferPixels);
+ getConfigAttrib(configs[i], EGL_MAX_SWAP_INTERVAL, &config.maxSwapInterval);
+ getConfigAttrib(configs[i], EGL_MIN_SWAP_INTERVAL, &config.minSwapInterval);
+ getConfigAttrib(configs[i], EGL_NATIVE_RENDERABLE, &config.nativeRenderable);
+ getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_ID, &config.nativeVisualID);
+ getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_TYPE, &config.nativeVisualType);
+ getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE, &config.renderableType);
+ getConfigAttrib(configs[i], EGL_SAMPLE_BUFFERS, &config.sampleBuffers);
+ getConfigAttrib(configs[i], EGL_SAMPLES, &config.samples);
+ getConfigAttrib(configs[i], EGL_STENCIL_SIZE, &config.stencilSize);
+ getConfigAttrib(configs[i], EGL_SURFACE_TYPE, &config.surfaceType);
+ getConfigAttrib(configs[i], EGL_TRANSPARENT_TYPE, &config.transparentType);
+ getConfigAttrib(configs[i], EGL_TRANSPARENT_RED_VALUE, &config.transparentRedValue);
+ getConfigAttrib(configs[i], EGL_TRANSPARENT_GREEN_VALUE, &config.transparentGreenValue);
+ getConfigAttrib(configs[i], EGL_TRANSPARENT_BLUE_VALUE, &config.transparentBlueValue);
+
+ if (config.colorBufferType == EGL_RGB_BUFFER)
+ {
+ if (config.redSize == 8 && config.greenSize == 8 && config.blueSize == 8 &&
+ config.alphaSize == 8)
+ {
+ config.renderTargetFormat = GL_RGBA8;
+ }
+ else if (config.redSize == 8 && config.greenSize == 8 && config.blueSize == 8 &&
+ config.alphaSize == 0)
+ {
+ config.renderTargetFormat = GL_RGB8;
+ }
+ else if (config.redSize == 5 && config.greenSize == 6 && config.blueSize == 5 &&
+ config.alphaSize == 0)
+ {
+ config.renderTargetFormat = GL_RGB565;
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ if (config.depthSize == 0 && config.stencilSize == 0)
+ {
+ config.depthStencilFormat = GL_ZERO;
+ }
+ else if (config.depthSize == 16 && config.stencilSize == 0)
+ {
+ config.depthStencilFormat = GL_DEPTH_COMPONENT16;
+ }
+ else if (config.depthSize == 24 && config.stencilSize == 0)
+ {
+ config.depthStencilFormat = GL_DEPTH_COMPONENT24;
+ }
+ else if (config.depthSize == 24 && config.stencilSize == 8)
+ {
+ config.depthStencilFormat = GL_DEPTH24_STENCIL8;
+ }
+ else if (config.depthSize == 0 && config.stencilSize == 8)
+ {
+ config.depthStencilFormat = GL_STENCIL_INDEX8;
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ config.matchNativePixmap = EGL_NONE;
+ config.optimalOrientation = 0;
+
+ int internalId = configSet.add(config);
+ mConfigIds[internalId] = config.configID;
+ }
+
+ return configSet;
+}
+
+bool DisplayAndroid::testDeviceLost()
+{
+ return false;
+}
+
+egl::Error DisplayAndroid::restoreLostDevice()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+bool DisplayAndroid::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return ANativeWindow_getFormat(window) >= 0;
+}
+
+egl::Error DisplayAndroid::getDevice(DeviceImpl **device)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayAndroid::waitClient() const
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayAndroid::waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayAndroid::getDriverVersion(std::string *version) const
+{
+ VendorID vendor = GetVendorID(mFunctionsGL);
+
+ switch (vendor)
+ {
+ case VENDOR_ID_QUALCOMM:
+ *version = reinterpret_cast<const char *>(mFunctionsGL->getString(GL_VERSION));
+ return egl::Error(EGL_SUCCESS);
+ default:
+ *version = "";
+ return egl::Error(EGL_SUCCESS);
+ }
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h b/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h
new file mode 100755
index 000000000..0be9bb465
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h
@@ -0,0 +1,78 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayAndroid.h: Android implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_ANDROID_DISPLAYANDROID_H_
+#define LIBANGLE_RENDERER_GL_EGL_ANDROID_DISPLAYANDROID_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "libANGLE/renderer/gl/egl/DisplayEGL.h"
+
+namespace rx
+{
+
+class DisplayAndroid : public DisplayEGL
+{
+ public:
+ DisplayAndroid();
+ ~DisplayAndroid() override;
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ ImageImpl *createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() override;
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+ egl::Error getDevice(DeviceImpl **device) override;
+
+ egl::Error waitClient() const override;
+ egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const override;
+
+ egl::Error getDriverVersion(std::string *version) const override;
+
+ private:
+ template <typename T>
+ void getConfigAttrib(EGLConfig config, EGLint attribute, T *value) const;
+
+ std::vector<EGLint> mConfigAttribList;
+ std::map<EGLint, EGLint> mConfigIds;
+ EGLSurface mDummyPbuffer;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_ANDROID_DISPLAYANDROID_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h b/gfx/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h
new file mode 100755
index 000000000..78f9009bf
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h
@@ -0,0 +1,131 @@
+//
+// Copyright (c) 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.
+//
+
+// functionsegl_typedefs.h: Typedefs of EGL functions.
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_FUNCTIONSEGLTYPEDEFS_H_
+#define LIBANGLE_RENDERER_GL_EGL_FUNCTIONSEGLTYPEDEFS_H_
+
+#include <EGL/egl.h>
+
+namespace rx
+{
+// EGL 1.0
+typedef EGLBoolean (*PFNEGLCHOOSECONFIGPROC)(EGLDisplay dpy,
+ const EGLint *attrib_list,
+ EGLConfig *configs,
+ EGLint config_size,
+ EGLint *num_config);
+typedef EGLBoolean (*PFNEGLCOPYBUFFERSPROC)(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLNativePixmapType target);
+typedef EGLContext (*PFNEGLCREATECONTEXTPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ EGLContext share_context,
+ const EGLint *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEPBUFFERSURFACEPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ const EGLint *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEPIXMAPSURFACEPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ EGLNativePixmapType pixmap,
+ const EGLint *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ EGLNativeWindowType win,
+ const EGLint *attrib_list);
+typedef EGLBoolean (*PFNEGLDESTROYCONTEXTPROC)(EGLDisplay dpy, EGLContext ctx);
+typedef EGLBoolean (*PFNEGLDESTROYSURFACEPROC)(EGLDisplay dpy, EGLSurface surface);
+typedef EGLBoolean (*PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ EGLint attribute,
+ EGLint *value);
+typedef EGLBoolean (*PFNEGLGETCONFIGSPROC)(EGLDisplay dpy,
+ EGLConfig *configs,
+ EGLint config_size,
+ EGLint *num_config);
+typedef EGLDisplay (*PFNEGLGETCURRENTDISPLAYPROC)(void);
+typedef EGLSurface (*PFNEGLGETCURRENTSURFACEPROC)(EGLint readdraw);
+typedef EGLDisplay (*PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType display_id);
+typedef EGLint (*PFNEGLGETERRORPROC)(void);
+typedef __eglMustCastToProperFunctionPointerType (*PFNEGLGETPROCADDRESSPROC)(const char *procname);
+typedef EGLBoolean (*PFNEGLINITIALIZEPROC)(EGLDisplay dpy, EGLint *major, EGLint *minor);
+typedef EGLBoolean (*PFNEGLMAKECURRENTPROC)(EGLDisplay dpy,
+ EGLSurface draw,
+ EGLSurface read,
+ EGLContext ctx);
+typedef EGLBoolean (*PFNEGLQUERYCONTEXTPROC)(EGLDisplay dpy,
+ EGLContext ctx,
+ EGLint attribute,
+ EGLint *value);
+typedef const char *(*PFNEGLQUERYSTRINGPROC)(EGLDisplay dpy, EGLint name);
+typedef EGLBoolean (*PFNEGLQUERYSURFACEPROC)(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLint attribute,
+ EGLint *value);
+typedef EGLBoolean (*PFNEGLSWAPBUFFERSPROC)(EGLDisplay dpy, EGLSurface surface);
+typedef EGLBoolean (*PFNEGLTERMINATEPROC)(EGLDisplay dpy);
+typedef EGLBoolean (*PFNEGLWAITGLPROC)(void);
+typedef EGLBoolean (*PFNEGLWAITNATIVEPROC)(EGLint engine);
+
+// EGL 1.1
+typedef EGLBoolean (*PFNEGLBINDTEXIMAGEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+typedef EGLBoolean (*PFNEGLRELEASETEXIMAGEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+typedef EGLBoolean (*PFNEGLSURFACEATTRIBPROC)(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLint attribute,
+ EGLint value);
+typedef EGLBoolean (*PFNEGLSWAPINTERVALPROC)(EGLDisplay dpy, EGLint interval);
+
+// EGL 1.2
+typedef EGLBoolean (*PFNEGLBINDAPIPROC)(EGLenum api);
+typedef EGLenum (*PFNEGLQUERYAPIPROC)(void);
+typedef EGLSurface (*PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC)(EGLDisplay dpy,
+ EGLenum buftype,
+ EGLClientBuffer buffer,
+ EGLConfig config,
+ const EGLint *attrib_list);
+typedef EGLBoolean (*PFNEGLRELEASETHREADPROC)(void);
+typedef EGLBoolean (*PFNEGLWAITCLIENTPROC)(void);
+
+// EGL 1.3
+
+// EGL 1.4
+typedef EGLContext (*PFNEGLGETCURRENTCONTEXTPROC)(void);
+
+// EGL 1.5
+typedef EGLSync (*PFNEGLCREATESYNCPROC)(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
+typedef EGLBoolean (*PFNEGLDESTROYSYNCPROC)(EGLDisplay dpy, EGLSync sync);
+typedef EGLint (*PFNEGLCLIENTWAITSYNCPROC)(EGLDisplay dpy,
+ EGLSync sync,
+ EGLint flags,
+ EGLTime timeout);
+typedef EGLBoolean (*PFNEGLGETSYNCATTRIBPROC)(EGLDisplay dpy,
+ EGLSync sync,
+ EGLint attribute,
+ EGLAttrib *value);
+typedef EGLImage (*PFNEGLCREATEIMAGEPROC)(EGLDisplay dpy,
+ EGLContext ctx,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const EGLAttrib *attrib_list);
+typedef EGLBoolean (*PFNEGLDESTROYIMAGEPROC)(EGLDisplay dpy, EGLImage image);
+typedef EGLDisplay (*PFNEGLGETPLATFORMDISPLAYPROC)(EGLenum platform,
+ void *native_display,
+ const EGLAttrib *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEPLATFORMWINDOWSURFACEPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ void *native_window,
+ const EGLAttrib *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ void *native_pixmap,
+ const EGLAttrib *attrib_list);
+typedef EGLBoolean (*PFNEGLWAITSYNCPROC)(EGLDisplay dpy, EGLSync sync, EGLint flags);
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_FUNCTIONSEGLTYPEDEFS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp
new file mode 100755
index 000000000..01549fcfa
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp
@@ -0,0 +1,945 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayOzone.cpp: Ozone implementation of egl::Display
+
+#include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
+
+#include <fcntl.h>
+#include <poll.h>
+#include <iostream>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include <EGL/eglext.h>
+
+#include <gbm.h>
+#include <drm_fourcc.h>
+
+#include "common/debug.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
+#include "libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h"
+#include "platform/Platform.h"
+
+// ARM-specific extension needed to make Mali GPU behave - not in any
+// published header file.
+#ifndef EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM
+#define EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A
+#endif
+
+#ifndef EGL_NO_CONFIG_MESA
+#define EGL_NO_CONFIG_MESA ((EGLConfig)0)
+#endif
+
+namespace
+{
+
+EGLint UnsignedToSigned(uint32_t u)
+{
+ return *reinterpret_cast<const EGLint *>(&u);
+}
+
+drmModeModeInfoPtr ChooseMode(drmModeConnectorPtr conn)
+{
+ drmModeModeInfoPtr mode = nullptr;
+ ASSERT(conn);
+ ASSERT(conn->connection == DRM_MODE_CONNECTED);
+ // use first preferred mode if any, else end up with last mode in list
+ for (int i = 0; i < conn->count_modes; ++i)
+ {
+ mode = conn->modes + i;
+ if (mode->type & DRM_MODE_TYPE_PREFERRED)
+ {
+ break;
+ }
+ }
+ return mode;
+}
+
+int ChooseCRTC(int fd, drmModeConnectorPtr conn)
+{
+ for (int i = 0; i < conn->count_encoders; ++i)
+ {
+ drmModeEncoderPtr enc = drmModeGetEncoder(fd, conn->encoders[i]);
+ unsigned long crtcs = enc->possible_crtcs;
+ drmModeFreeEncoder(enc);
+ if (crtcs)
+ {
+ return __builtin_ctzl(crtcs);
+ }
+ }
+ return -1;
+}
+} // namespace
+
+namespace rx
+{
+
+// TODO(fjhenigman) Implement swap control. Until then this is unused.
+SwapControlData::SwapControlData()
+ : targetSwapInterval(0), maxSwapInterval(-1), currentSwapInterval(-1)
+{
+}
+
+DisplayOzone::Buffer::Buffer(DisplayOzone *display,
+ uint32_t useFlags,
+ uint32_t gbmFormat,
+ uint32_t drmFormat,
+ uint32_t drmFormatFB,
+ int depthBits,
+ int stencilBits)
+ : mDisplay(display),
+ mNative(nullptr),
+ mWidth(0),
+ mHeight(0),
+ mDepthBits(depthBits),
+ mStencilBits(stencilBits),
+ mUseFlags(useFlags),
+ mGBMFormat(gbmFormat),
+ mDRMFormat(drmFormat),
+ mDRMFormatFB(drmFormatFB),
+ mBO(nullptr),
+ mDMABuf(-1),
+ mHasDRMFB(false),
+ mDRMFB(0),
+ mImage(EGL_NO_IMAGE_KHR),
+ mColorBuffer(0),
+ mDSBuffer(0),
+ mGLFB(0),
+ mTexture(0)
+{
+}
+
+DisplayOzone::Buffer::~Buffer()
+{
+ mDisplay->mFunctionsGL->deleteFramebuffers(1, &mGLFB);
+ reset();
+}
+
+void DisplayOzone::Buffer::reset()
+{
+ if (mHasDRMFB)
+ {
+ int fd = gbm_device_get_fd(mDisplay->mGBM);
+ drmModeRmFB(fd, mDRMFB);
+ mHasDRMFB = false;
+ }
+
+ FunctionsGL *gl = mDisplay->mFunctionsGL;
+ gl->deleteRenderbuffers(1, &mColorBuffer);
+ mColorBuffer = 0;
+ gl->deleteRenderbuffers(1, &mDSBuffer);
+ mDSBuffer = 0;
+
+ // Here we might destroy the GL framebuffer (mGLFB) but unlike every other resource in Buffer,
+ // it does not get destroyed (and recreated) because when it is the default framebuffer for
+ // an ANGLE surface then ANGLE expects it to have the same lifetime as that surface.
+
+ if (mImage != EGL_NO_IMAGE_KHR)
+ {
+ mDisplay->mEGL->destroyImageKHR(mImage);
+ mImage = EGL_NO_IMAGE_KHR;
+ }
+
+ if (mTexture)
+ {
+ gl->deleteTextures(1, &mTexture);
+ mTexture = 0;
+ }
+
+ if (mDMABuf >= 0)
+ {
+ close(mDMABuf);
+ mDMABuf = -1;
+ }
+
+ if (mBO)
+ {
+ gbm_bo_destroy(mBO);
+ mBO = nullptr;
+ }
+}
+
+bool DisplayOzone::Buffer::resize(int32_t width, int32_t height)
+{
+ if (mWidth == width && mHeight == height)
+ {
+ return true;
+ }
+
+ reset();
+
+ if (width <= 0 || height <= 0)
+ {
+ return true;
+ }
+
+ mBO = gbm_bo_create(mDisplay->mGBM, width, height, mGBMFormat, mUseFlags);
+ if (!mBO)
+ {
+ return false;
+ }
+
+ mDMABuf = gbm_bo_get_fd(mBO);
+ if (mDMABuf < 0)
+ {
+ return false;
+ }
+
+ // clang-format off
+ const EGLint attr[] =
+ {
+ EGL_WIDTH, width,
+ EGL_HEIGHT, height,
+ EGL_LINUX_DRM_FOURCC_EXT, UnsignedToSigned(mDRMFormat),
+ EGL_DMA_BUF_PLANE0_FD_EXT, mDMABuf,
+ EGL_DMA_BUF_PLANE0_PITCH_EXT, UnsignedToSigned(gbm_bo_get_stride(mBO)),
+ EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
+ EGL_NONE,
+ };
+ // clang-format on
+
+ mImage = mDisplay->mEGL->createImageKHR(EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attr);
+ if (mImage == EGL_NO_IMAGE_KHR)
+ {
+ return false;
+ }
+
+ FunctionsGL *gl = mDisplay->mFunctionsGL;
+ StateManagerGL *sm = mDisplay->getRenderer()->getStateManager();
+
+ gl->genRenderbuffers(1, &mColorBuffer);
+ sm->bindRenderbuffer(GL_RENDERBUFFER, mColorBuffer);
+ gl->eglImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mImage);
+
+ sm->bindFramebuffer(GL_FRAMEBUFFER, mGLFB);
+ gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER,
+ mColorBuffer);
+
+ if (mDepthBits || mStencilBits)
+ {
+ gl->genRenderbuffers(1, &mDSBuffer);
+ sm->bindRenderbuffer(GL_RENDERBUFFER, mDSBuffer);
+ gl->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height);
+ }
+
+ if (mDepthBits)
+ {
+ gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
+ mDSBuffer);
+ }
+
+ if (mStencilBits)
+ {
+ gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+ mDSBuffer);
+ }
+
+ mWidth = width;
+ mHeight = height;
+ return true;
+}
+
+bool DisplayOzone::Buffer::initialize(const NativeWindow *native)
+{
+ mNative = native;
+ mDisplay->mFunctionsGL->genFramebuffers(1, &mGLFB);
+ return resize(native->width, native->height);
+}
+
+bool DisplayOzone::Buffer::initialize(int width, int height)
+{
+ mDisplay->mFunctionsGL->genFramebuffers(1, &mGLFB);
+ return resize(width, height);
+}
+
+void DisplayOzone::Buffer::bindTexImage()
+{
+ mDisplay->mFunctionsGL->eglImageTargetTexture2DOES(GL_TEXTURE_2D, mImage);
+}
+
+GLuint DisplayOzone::Buffer::getTexture()
+{
+ // TODO(fjhenigman) Try not to create a new texture every time. That already works on Intel
+ // and should work on Mali with proper fences.
+ FunctionsGL *gl = mDisplay->mFunctionsGL;
+ StateManagerGL *sm = mDisplay->getRenderer()->getStateManager();
+
+ gl->genTextures(1, &mTexture);
+ sm->bindTexture(GL_TEXTURE_2D, mTexture);
+ gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ ASSERT(mImage != EGL_NO_IMAGE_KHR);
+ gl->eglImageTargetTexture2DOES(GL_TEXTURE_2D, mImage);
+ return mTexture;
+}
+
+uint32_t DisplayOzone::Buffer::getDRMFB()
+{
+ if (!mHasDRMFB)
+ {
+ int fd = gbm_device_get_fd(mDisplay->mGBM);
+ uint32_t handles[4] = {gbm_bo_get_handle(mBO).u32};
+ uint32_t pitches[4] = {gbm_bo_get_stride(mBO)};
+ uint32_t offsets[4] = {0};
+ if (drmModeAddFB2(fd, mWidth, mHeight, mDRMFormatFB, handles, pitches, offsets, &mDRMFB, 0))
+ {
+ std::cerr << "drmModeAddFB2 failed" << std::endl;
+ }
+ else
+ {
+ mHasDRMFB = true;
+ }
+ }
+
+ return mDRMFB;
+}
+
+FramebufferGL *DisplayOzone::Buffer::framebufferGL(const gl::FramebufferState &state)
+{
+ return new FramebufferGL(
+ mGLFB, state, mDisplay->mFunctionsGL, mDisplay->getRenderer()->getWorkarounds(),
+ mDisplay->getRenderer()->getBlitter(), mDisplay->getRenderer()->getStateManager());
+}
+
+void DisplayOzone::Buffer::present()
+{
+ if (mNative)
+ {
+ if (mNative->visible)
+ {
+ mDisplay->drawBuffer(this);
+ }
+ resize(mNative->width, mNative->height);
+ }
+}
+
+DisplayOzone::DisplayOzone()
+ : DisplayEGL(),
+ mSwapControl(SwapControl::ABSENT),
+ mMinSwapInterval(0),
+ mMaxSwapInterval(0),
+ mCurrentSwapInterval(-1),
+ mGBM(nullptr),
+ mConnector(nullptr),
+ mMode(nullptr),
+ mCRTC(nullptr),
+ mSetCRTC(true),
+ mWidth(0),
+ mHeight(0),
+ mScanning(nullptr),
+ mPending(nullptr),
+ mDrawing(nullptr),
+ mUnused(nullptr),
+ mProgram(0),
+ mVertexShader(0),
+ mFragmentShader(0),
+ mVertexBuffer(0),
+ mIndexBuffer(0),
+ mCenterUniform(0),
+ mWindowSizeUniform(0),
+ mBorderSizeUniform(0),
+ mDepthUniform(0)
+{
+}
+
+DisplayOzone::~DisplayOzone()
+{
+}
+
+egl::Error DisplayOzone::initialize(egl::Display *display)
+{
+ int fd;
+ char deviceName[30];
+ drmModeResPtr resources = nullptr;
+
+ for (int i = 0; i < 9; ++i)
+ {
+ snprintf(deviceName, sizeof(deviceName), "/dev/dri/card%d", i);
+ fd = open(deviceName, O_RDWR | O_CLOEXEC);
+ if (fd >= 0)
+ {
+ resources = drmModeGetResources(fd);
+ if (resources)
+ {
+ if (resources->count_connectors > 0)
+ {
+ break;
+ }
+ drmModeFreeResources(resources);
+ resources = nullptr;
+ }
+ close(fd);
+ }
+ }
+ if (!resources)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not open drm device.");
+ }
+
+ mGBM = gbm_create_device(fd);
+ if (!mGBM)
+ {
+ close(fd);
+ drmModeFreeResources(resources);
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create gbm device.");
+ }
+
+ mConnector = nullptr;
+ bool monitorConnected = false;
+ for (int i = 0; !mCRTC && i < resources->count_connectors; ++i)
+ {
+ drmModeFreeConnector(mConnector);
+ mConnector = drmModeGetConnector(fd, resources->connectors[i]);
+ if (!mConnector || mConnector->connection != DRM_MODE_CONNECTED)
+ {
+ continue;
+ }
+ monitorConnected = true;
+ mMode = ChooseMode(mConnector);
+ if (!mMode)
+ {
+ continue;
+ }
+ int n = ChooseCRTC(fd, mConnector);
+ if (n < 0)
+ {
+ continue;
+ }
+ mCRTC = drmModeGetCrtc(fd, resources->crtcs[n]);
+ }
+ drmModeFreeResources(resources);
+
+ if (mCRTC)
+ {
+ mWidth = mMode->hdisplay;
+ mHeight = mMode->vdisplay;
+ }
+ else if (!monitorConnected)
+ {
+ // Even though there is no monitor to show it, we still do
+ // everything the same as if there were one, so we need an
+ // arbitrary size for our buffers.
+ mWidth = 1280;
+ mHeight = 1024;
+ }
+ else
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to choose mode/crtc.");
+ }
+
+ // ANGLE builds its executables with an RPATH so they pull in ANGLE's libGL and libEGL.
+ // Here we need to open the native libEGL. An absolute path would work, but then we
+ // couldn't use LD_LIBRARY_PATH which is often useful during development. Instead we take
+ // advantage of the fact that the system lib is available under multiple names (for example
+ // with a .1 suffix) while Angle only installs libEGL.so.
+ FunctionsEGLDL *egl = new FunctionsEGLDL();
+ mEGL = egl;
+ ANGLE_TRY(egl->initialize(display->getNativeDisplayId(), "libEGL.so.1"));
+
+ const char *necessaryExtensions[] = {
+ "EGL_KHR_image_base", "EGL_EXT_image_dma_buf_import", "EGL_KHR_surfaceless_context",
+ };
+ for (auto &ext : necessaryExtensions)
+ {
+ if (!mEGL->hasExtension(ext))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "need %s", ext);
+ }
+ }
+
+ if (mEGL->hasExtension("EGL_MESA_configless_context"))
+ {
+ mConfig = EGL_NO_CONFIG_MESA;
+ }
+ else
+ {
+ // clang-format off
+ const EGLint attrib[] =
+ {
+ // We want RGBA8 and DEPTH24_STENCIL8
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 24,
+ EGL_STENCIL_SIZE, 8,
+ EGL_NONE,
+ };
+ // clang-format on
+ EGLint numConfig;
+ EGLConfig config[1];
+ if (!mEGL->chooseConfig(attrib, config, 1, &numConfig) || numConfig < 1)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not get EGL config.");
+ }
+ mConfig = config[0];
+ }
+
+ ANGLE_TRY(initializeContext(display->getAttributeMap()));
+
+ if (!mEGL->makeCurrent(EGL_NO_SURFACE, mContext))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not make context current.");
+ }
+
+ mFunctionsGL = mEGL->makeFunctionsGL();
+ mFunctionsGL->initialize();
+
+ return DisplayGL::initialize(display);
+}
+
+void DisplayOzone::pageFlipHandler(int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *data)
+{
+ DisplayOzone *display = reinterpret_cast<DisplayOzone *>(data);
+ uint64_t tv = tv_sec;
+ display->pageFlipHandler(sequence, tv * 1000000 + tv_usec);
+}
+
+void DisplayOzone::pageFlipHandler(unsigned int sequence, uint64_t tv)
+{
+ ASSERT(mPending);
+ mUnused = mScanning;
+ mScanning = mPending;
+ mPending = nullptr;
+}
+
+void DisplayOzone::presentScreen()
+{
+ if (!mCRTC)
+ {
+ // no monitor
+ return;
+ }
+
+ // see if pending flip has finished, without blocking
+ int fd = gbm_device_get_fd(mGBM);
+ if (mPending)
+ {
+ pollfd pfd;
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+ if (poll(&pfd, 1, 0) < 0)
+ {
+ std::cerr << "poll failed: " << errno << " " << strerror(errno) << std::endl;
+ }
+ if (pfd.revents & POLLIN)
+ {
+ drmEventContext event;
+ event.version = DRM_EVENT_CONTEXT_VERSION;
+ event.page_flip_handler = pageFlipHandler;
+ drmHandleEvent(fd, &event);
+ }
+ }
+
+ // if pending flip has finished, schedule next one
+ if (!mPending && mDrawing)
+ {
+ flushGL();
+ if (mSetCRTC)
+ {
+ if (drmModeSetCrtc(fd, mCRTC->crtc_id, mDrawing->getDRMFB(), 0, 0,
+ &mConnector->connector_id, 1, mMode))
+ {
+ std::cerr << "set crtc failed: " << errno << " " << strerror(errno) << std::endl;
+ }
+ mSetCRTC = false;
+ }
+ if (drmModePageFlip(fd, mCRTC->crtc_id, mDrawing->getDRMFB(), DRM_MODE_PAGE_FLIP_EVENT,
+ this))
+ {
+ std::cerr << "page flip failed: " << errno << " " << strerror(errno) << std::endl;
+ }
+ mPending = mDrawing;
+ mDrawing = nullptr;
+ }
+}
+
+GLuint DisplayOzone::makeShader(GLuint type, const char *src)
+{
+ FunctionsGL *gl = mFunctionsGL;
+ GLuint shader = gl->createShader(type);
+ gl->shaderSource(shader, 1, &src, nullptr);
+ gl->compileShader(shader);
+
+ GLchar buf[999];
+ GLsizei len;
+ GLint compiled;
+ gl->getShaderInfoLog(shader, sizeof(buf), &len, buf);
+ gl->getShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+ if (compiled != GL_TRUE)
+ {
+ ANGLEPlatformCurrent()->logError("DisplayOzone shader compilation error:");
+ ANGLEPlatformCurrent()->logError(buf);
+ }
+
+ return shader;
+}
+
+void DisplayOzone::drawWithTexture(Buffer *buffer)
+{
+ FunctionsGL *gl = mFunctionsGL;
+ StateManagerGL *sm = getRenderer()->getStateManager();
+
+ if (!mProgram)
+ {
+ const GLchar *vertexSource =
+ "#version 100\n"
+ "attribute vec3 vertex;\n"
+ "uniform vec2 center;\n"
+ "uniform vec2 windowSize;\n"
+ "uniform vec2 borderSize;\n"
+ "uniform float depth;\n"
+ "varying vec3 texCoord;\n"
+ "void main()\n"
+ "{\n"
+ " vec2 pos = vertex.xy * (windowSize + borderSize * vertex.z);\n"
+ " gl_Position = vec4(center + pos, depth, 1);\n"
+ " texCoord = vec3(pos / windowSize * vec2(.5, -.5) + vec2(.5, .5), vertex.z);\n"
+ "}\n";
+
+ const GLchar *fragmentSource =
+ "#version 100\n"
+ "precision mediump float;\n"
+ "uniform sampler2D tex;\n"
+ "varying vec3 texCoord;\n"
+ "void main()\n"
+ "{\n"
+ " if (texCoord.z > 0.)\n"
+ " {\n"
+ " float c = abs((texCoord.z * 2.) - 1.);\n"
+ " gl_FragColor = vec4(c, c, c, 1);\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " gl_FragColor = texture2D(tex, texCoord.xy);\n"
+ " }\n"
+ "}\n";
+
+ mVertexShader = makeShader(GL_VERTEX_SHADER, vertexSource);
+ mFragmentShader = makeShader(GL_FRAGMENT_SHADER, fragmentSource);
+ mProgram = gl->createProgram();
+ gl->attachShader(mProgram, mVertexShader);
+ gl->attachShader(mProgram, mFragmentShader);
+ gl->bindAttribLocation(mProgram, 0, "vertex");
+ gl->linkProgram(mProgram);
+ GLint linked;
+ gl->getProgramiv(mProgram, GL_LINK_STATUS, &linked);
+ ASSERT(linked);
+ mCenterUniform = gl->getUniformLocation(mProgram, "center");
+ mWindowSizeUniform = gl->getUniformLocation(mProgram, "windowSize");
+ mBorderSizeUniform = gl->getUniformLocation(mProgram, "borderSize");
+ mDepthUniform = gl->getUniformLocation(mProgram, "depth");
+ GLint texUniform = gl->getUniformLocation(mProgram, "tex");
+ sm->useProgram(mProgram);
+ gl->uniform1i(texUniform, 0);
+
+ // clang-format off
+ const GLfloat vertices[] =
+ {
+ // window corners, and window border inside corners
+ 1, -1, 0,
+ -1, -1, 0,
+ 1, 1, 0,
+ -1, 1, 0,
+ // window border outside corners
+ 1, -1, 1,
+ -1, -1, 1,
+ 1, 1, 1,
+ -1, 1, 1,
+ };
+ // clang-format on
+ gl->genBuffers(1, &mVertexBuffer);
+ sm->bindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+ gl->bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+ // window border triangle strip
+ const GLuint borderStrip[] = {5, 0, 4, 2, 6, 3, 7, 1, 5, 0};
+
+ gl->genBuffers(1, &mIndexBuffer);
+ sm->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+ gl->bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(borderStrip), borderStrip, GL_STATIC_DRAW);
+ }
+ else
+ {
+ sm->useProgram(mProgram);
+ sm->bindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+ sm->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+ }
+
+ // convert from pixels to "-1 to 1" space
+ const NativeWindow *n = buffer->getNative();
+ double x = n->x * 2. / mWidth - 1;
+ double y = n->y * 2. / mHeight - 1;
+ double halfw = n->width * 1. / mWidth;
+ double halfh = n->height * 1. / mHeight;
+ double borderw = n->borderWidth * 2. / mWidth;
+ double borderh = n->borderHeight * 2. / mHeight;
+
+ gl->uniform2f(mCenterUniform, x + halfw, y + halfh);
+ gl->uniform2f(mWindowSizeUniform, halfw, halfh);
+ gl->uniform2f(mBorderSizeUniform, borderw, borderh);
+ gl->uniform1f(mDepthUniform, n->depth / 1e6);
+
+ sm->setBlendEnabled(false);
+ sm->setCullFaceEnabled(false);
+ sm->setStencilTestEnabled(false);
+ sm->setScissorTestEnabled(false);
+ sm->setDepthTestEnabled(true);
+ sm->setColorMask(true, true, true, true);
+ sm->setDepthMask(true);
+ sm->setDepthRange(0, 1);
+ sm->setDepthFunc(GL_LESS);
+ sm->setViewport(gl::Rectangle(0, 0, mWidth, mHeight));
+ sm->activeTexture(0);
+ GLuint tex = buffer->getTexture();
+ sm->bindTexture(GL_TEXTURE_2D, tex);
+ gl->vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
+ gl->enableVertexAttribArray(0);
+ sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawing->getGLFB());
+ gl->drawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ gl->drawElements(GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, 0);
+ sm->deleteTexture(tex);
+}
+
+void DisplayOzone::drawBuffer(Buffer *buffer)
+{
+ if (!mDrawing)
+ {
+ // get buffer on which to draw window
+ if (mUnused)
+ {
+ mDrawing = mUnused;
+ mUnused = nullptr;
+ }
+ else
+ {
+ mDrawing = new Buffer(this, GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT,
+ GBM_FORMAT_ARGB8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888,
+ true, true); // XXX shouldn't need stencil
+ if (!mDrawing || !mDrawing->initialize(mWidth, mHeight))
+ {
+ return;
+ }
+ }
+
+ StateManagerGL *sm = getRenderer()->getStateManager();
+ sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawing->getGLFB());
+ sm->setClearColor(gl::ColorF(0, 0, 0, 1));
+ sm->setClearDepth(1);
+ sm->setScissorTestEnabled(false);
+ sm->setColorMask(true, true, true, true);
+ sm->setDepthMask(true);
+ mFunctionsGL->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+
+ drawWithTexture(buffer);
+ presentScreen();
+}
+
+void DisplayOzone::flushGL()
+{
+ mFunctionsGL->flush();
+ if (mEGL->hasExtension("EGL_KHR_fence_sync"))
+ {
+ const EGLint attrib[] = {EGL_SYNC_CONDITION_KHR,
+ EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, EGL_NONE};
+ EGLSyncKHR fence = mEGL->createSyncKHR(EGL_SYNC_FENCE_KHR, attrib);
+ if (fence)
+ {
+ // TODO(fjhenigman) Figure out the right way to use fences on Mali GPU
+ // to maximize throughput and avoid hangs when a program is interrupted.
+ // This busy wait was an attempt to reduce hangs when interrupted by SIGINT,
+ // but we still get some.
+ for (;;)
+ {
+ EGLint r = mEGL->clientWaitSyncKHR(fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 0);
+ if (r != EGL_TIMEOUT_EXPIRED_KHR)
+ {
+ break;
+ }
+ usleep(99);
+ }
+ mEGL->destroySyncKHR(fence);
+ return;
+ }
+ }
+}
+
+void DisplayOzone::terminate()
+{
+ SafeDelete(mScanning);
+ SafeDelete(mPending);
+ SafeDelete(mDrawing);
+ SafeDelete(mUnused);
+
+ if (mProgram)
+ {
+ mFunctionsGL->deleteProgram(mProgram);
+ mFunctionsGL->deleteShader(mVertexShader);
+ mFunctionsGL->deleteShader(mFragmentShader);
+ mFunctionsGL->deleteBuffers(1, &mVertexBuffer);
+ mFunctionsGL->deleteBuffers(1, &mIndexBuffer);
+ mProgram = 0;
+ }
+
+ DisplayGL::terminate();
+
+ if (mContext)
+ {
+ // Mesa might crash if you terminate EGL with a context current
+ // then re-initialize EGL, so make our context not current.
+ mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ mEGL->destroyContext(mContext);
+ mContext = nullptr;
+ }
+
+ SafeDelete(mFunctionsGL);
+
+ if (mEGL)
+ {
+ mEGL->terminate();
+ SafeDelete(mEGL);
+ }
+
+ drmModeFreeCrtc(mCRTC);
+
+ if (mGBM)
+ {
+ int fd = gbm_device_get_fd(mGBM);
+ gbm_device_destroy(mGBM);
+ mGBM = nullptr;
+ close(fd);
+ }
+}
+
+SurfaceImpl *DisplayOzone::createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ Buffer *buffer = new Buffer(this, GBM_BO_USE_RENDERING, GBM_FORMAT_ARGB8888,
+ DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, true, true);
+ if (!buffer || !buffer->initialize(reinterpret_cast<const NativeWindow *>(window)))
+ {
+ return nullptr;
+ }
+ return new SurfaceOzone(state, getRenderer(), buffer);
+}
+
+SurfaceImpl *DisplayOzone::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs)
+{
+ EGLAttrib width = attribs.get(EGL_WIDTH, 0);
+ EGLAttrib height = attribs.get(EGL_HEIGHT, 0);
+ Buffer *buffer = new Buffer(this, GBM_BO_USE_RENDERING, GBM_FORMAT_ARGB8888,
+ DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, true, true);
+ if (!buffer || !buffer->initialize(width, height))
+ {
+ return nullptr;
+ }
+ return new SurfaceOzone(state, getRenderer(), buffer);
+}
+
+SurfaceImpl *DisplayOzone::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+SurfaceImpl *DisplayOzone::createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+egl::Error DisplayOzone::getDevice(DeviceImpl **device)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+egl::ConfigSet DisplayOzone::generateConfigs()
+{
+ egl::ConfigSet configs;
+
+ egl::Config config;
+ config.redSize = 8;
+ config.greenSize = 8;
+ config.blueSize = 8;
+ config.alphaSize = 8;
+ config.depthSize = 24;
+ config.stencilSize = 8;
+ config.bindToTextureRGBA = EGL_TRUE;
+ config.renderableType = EGL_OPENGL_ES2_BIT;
+ config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
+
+ configs.add(config);
+ return configs;
+}
+
+bool DisplayOzone::testDeviceLost()
+{
+ return false;
+}
+
+egl::Error DisplayOzone::restoreLostDevice()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+bool DisplayOzone::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return true;
+}
+
+egl::Error DisplayOzone::getDriverVersion(std::string *version) const
+{
+ *version = "";
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayOzone::waitClient() const
+{
+ // TODO(fjhenigman) Implement this.
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayOzone::waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const
+{
+ // TODO(fjhenigman) Implement this.
+ return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayOzone::setSwapInterval(EGLSurface drawable, SwapControlData *data)
+{
+ ASSERT(data != nullptr);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h
new file mode 100755
index 000000000..77c669314
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h
@@ -0,0 +1,211 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayOzone.h: Ozone implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_
+#define LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <string>
+
+#include "libANGLE/renderer/gl/egl/DisplayEGL.h"
+
+struct gbm_device;
+struct gbm_bo;
+
+namespace gl
+{
+class FramebufferState;
+}
+
+namespace rx
+{
+
+class FramebufferGL;
+
+// TODO(fjhenigman) Implement swap control. The following struct will be used for that.
+// State-tracking data for the swap control to allow DisplayOzone to remember per
+// drawable information for swap control.
+struct SwapControlData final
+{
+ SwapControlData();
+
+ // Set by the drawable
+ int targetSwapInterval;
+
+ // DisplayOzone-side state-tracking
+ int maxSwapInterval;
+ int currentSwapInterval;
+};
+
+class DisplayOzone final : public DisplayEGL
+{
+ public:
+ struct NativeWindow
+ {
+ int32_t x;
+ int32_t y;
+ int32_t width;
+ int32_t height;
+ int32_t borderWidth;
+ int32_t borderHeight;
+ int32_t visible;
+ int32_t depth;
+ };
+
+ class Buffer final : angle::NonCopyable
+ {
+ public:
+ Buffer(DisplayOzone *display,
+ uint32_t useFlags,
+ uint32_t gbmFormat,
+ uint32_t drmFormat,
+ uint32_t drmFormatFB,
+ int depthBits,
+ int stencilBits);
+
+ ~Buffer();
+ bool initialize(const NativeWindow *window);
+ bool initialize(int32_t width, int32_t height);
+ void reset();
+ bool resize(int32_t width, int32_t height);
+ FramebufferGL *framebufferGL(const gl::FramebufferState &state);
+ void present();
+ uint32_t getDRMFB();
+ void bindTexImage();
+ GLuint getTexture();
+ int32_t getWidth() const { return mWidth; }
+ int32_t getHeight() const { return mHeight; }
+ GLuint getGLFB() const { return mGLFB; }
+ const NativeWindow *getNative() const { return mNative; }
+
+ private:
+ DisplayOzone *mDisplay;
+ const NativeWindow *mNative;
+ int mWidth;
+ int mHeight;
+ const int mDepthBits;
+ const int mStencilBits;
+ const uint32_t mUseFlags;
+ const uint32_t mGBMFormat;
+ const uint32_t mDRMFormat;
+ const uint32_t mDRMFormatFB;
+ gbm_bo *mBO;
+ int mDMABuf;
+ bool mHasDRMFB;
+ uint32_t mDRMFB;
+ EGLImageKHR mImage;
+ GLuint mColorBuffer;
+ GLuint mDSBuffer;
+ GLuint mGLFB;
+ GLuint mTexture;
+ };
+
+ DisplayOzone();
+ ~DisplayOzone() override;
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() override;
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+ egl::Error getDevice(DeviceImpl **device) override;
+
+ egl::Error waitClient() const override;
+ egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const override;
+
+ // TODO(fjhenigman) Implement this.
+ // Swap interval can be set globally or per drawable.
+ // This function will make sure the drawable's swap interval is the
+ // one required so that the subsequent swapBuffers acts as expected.
+ void setSwapInterval(EGLSurface drawable, SwapControlData *data);
+
+ egl::Error getDriverVersion(std::string *version) const override;
+
+ private:
+ GLuint makeShader(GLuint type, const char *src);
+ void drawBuffer(Buffer *buffer);
+ void drawWithBlit(Buffer *buffer);
+ void drawWithTexture(Buffer *buffer);
+ void flushGL();
+ void presentScreen();
+ static void pageFlipHandler(int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *data);
+ void pageFlipHandler(unsigned int sequence, uint64_t tv);
+
+ // TODO(fjhenigman) Implement swap control. The following stuff will be used for that.
+ enum class SwapControl
+ {
+ ABSENT,
+ EXT,
+ MESA,
+ SGI,
+ };
+ SwapControl mSwapControl;
+ int mMinSwapInterval;
+ int mMaxSwapInterval;
+ int mCurrentSwapInterval;
+
+ gbm_device *mGBM;
+ drmModeConnectorPtr mConnector;
+ drmModeModeInfoPtr mMode;
+ drmModeCrtcPtr mCRTC;
+ bool mSetCRTC;
+
+ int32_t mWidth;
+ int32_t mHeight;
+
+ // Three scanout buffers cycle through four states. The state of a buffer
+ // is indicated by which of these pointers points to it.
+ // TODO(fjhenigman) It might be simpler/clearer to use a ring buffer.
+ Buffer *mScanning;
+ Buffer *mPending;
+ Buffer *mDrawing;
+ Buffer *mUnused;
+
+ GLuint mProgram;
+ GLuint mVertexShader;
+ GLuint mFragmentShader;
+ GLuint mVertexBuffer;
+ GLuint mIndexBuffer;
+ GLint mCenterUniform;
+ GLint mWindowSizeUniform;
+ GLint mBorderSizeUniform;
+ GLint mDepthUniform;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp
new file mode 100755
index 000000000..614fed0fd
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 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.
+//
+
+// SurfaceOzone.cpp: Ozone implementation of egl::SurfaceGL
+
+#include "libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h"
+
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
+
+namespace rx
+{
+
+SurfaceOzone::SurfaceOzone(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ DisplayOzone::Buffer *buffer)
+ : SurfaceGL(state, renderer), mBuffer(buffer)
+{
+}
+
+SurfaceOzone::~SurfaceOzone()
+{
+ delete mBuffer;
+}
+
+egl::Error SurfaceOzone::initialize()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+FramebufferImpl *SurfaceOzone::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+ return mBuffer->framebufferGL(state);
+}
+
+egl::Error SurfaceOzone::makeCurrent()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::swap()
+{
+ mBuffer->present();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ mBuffer->bindTexImage();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::releaseTexImage(EGLint buffer)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+void SurfaceOzone::setSwapInterval(EGLint interval)
+{
+ mSwapControl.targetSwapInterval = interval;
+}
+
+EGLint SurfaceOzone::getWidth() const
+{
+ return mBuffer->getWidth();
+}
+
+EGLint SurfaceOzone::getHeight() const
+{
+ return mBuffer->getHeight();
+}
+
+EGLint SurfaceOzone::isPostSubBufferSupported() const
+{
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLint SurfaceOzone::getSwapBehavior() const
+{
+ return EGL_BUFFER_PRESERVED;
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h
new file mode 100755
index 000000000..24b8ec8c9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 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.
+//
+
+// SurfaceOzone.h: Ozone implementation of egl::SurfaceGL
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_OZONE_SURFACEOZONE_H_
+#define LIBANGLE_RENDERER_GL_EGL_OZONE_SURFACEOZONE_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+#include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
+
+namespace rx
+{
+
+class SurfaceOzone : public SurfaceGL
+{
+ public:
+ SurfaceOzone(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ DisplayOzone::Buffer *buffer);
+ ~SurfaceOzone() override;
+
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ private:
+ DisplayOzone::Buffer *mBuffer;
+
+ // TODO(fjhenigman) Implement swap control. This will be used for that.
+ SwapControlData mSwapControl;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_OZONE_SURFACEOZONE_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp b/gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp
new file mode 100755
index 000000000..c5219b4b8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp
@@ -0,0 +1,553 @@
+//
+// Copyright (c) 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.
+//
+
+// formatutilsgl.cpp: Queries for GL image formats and their translations to native
+// GL formats.
+
+#include "libANGLE/renderer/gl/formatutilsgl.h"
+
+#include <limits>
+
+#include "common/string_utils.h"
+#include "libANGLE/formatutils.h"
+
+namespace rx
+{
+
+namespace nativegl
+{
+
+SupportRequirement::SupportRequirement()
+ : version(std::numeric_limits<GLuint>::max(), std::numeric_limits<GLuint>::max()),
+ versionExtensions(),
+ requiredExtensions()
+{
+}
+
+InternalFormat::InternalFormat()
+ : texture(),
+ filter(),
+ renderbuffer(),
+ framebufferAttachment()
+{
+}
+
+// supported = version || vertexExt
+static inline SupportRequirement VersionOrExts(GLuint major, GLuint minor, const std::string &versionExt)
+{
+ SupportRequirement requirement;
+ requirement.version.major = major;
+ requirement.version.minor = minor;
+ angle::SplitStringAlongWhitespace(versionExt, &requirement.versionExtensions);
+ return requirement;
+}
+
+// supported = (version || vertexExt) && requiredExt
+static inline SupportRequirement VersionOrExtsAndExts(GLuint major,
+ GLuint minor,
+ const std::string &versionExt,
+ const std::string &requiredExt)
+{
+ SupportRequirement requirement;
+ requirement.version.major = major;
+ requirement.version.minor = minor;
+ angle::SplitStringAlongWhitespace(versionExt, &requirement.versionExtensions);
+ angle::SplitStringAlongWhitespace(requiredExt, &requirement.requiredExtensions);
+ return requirement;
+}
+
+// supported = version
+static inline SupportRequirement VersionOnly(GLuint major, GLuint minor)
+{
+ SupportRequirement requirement;
+ requirement.version.major = major;
+ requirement.version.minor = minor;
+ return requirement;
+}
+
+// supported = ext
+static inline SupportRequirement ExtsOnly(const std::string &ext)
+{
+ SupportRequirement requirement;
+ requirement.version.major = 0;
+ requirement.version.minor = 0;
+ angle::SplitStringAlongWhitespace(ext, &requirement.requiredExtensions);
+ return requirement;
+}
+
+// supported = true
+static inline SupportRequirement AlwaysSupported()
+{
+ SupportRequirement requirement;
+ requirement.version.major = 0;
+ requirement.version.minor = 0;
+ return requirement;
+}
+
+// supported = false
+static inline SupportRequirement NeverSupported()
+{
+ SupportRequirement requirement;
+ requirement.version.major = std::numeric_limits<GLuint>::max();
+ requirement.version.minor = std::numeric_limits<GLuint>::max();
+ return requirement;
+}
+
+struct InternalFormatInfo
+{
+ InternalFormat glesInfo;
+ InternalFormat glInfo;
+};
+
+typedef std::pair<GLenum, InternalFormatInfo> InternalFormatInfoPair;
+typedef std::map<GLenum, InternalFormatInfo> InternalFormatInfoMap;
+
+// A helper function to insert data into the format map with fewer characters.
+static inline void InsertFormatMapping(InternalFormatInfoMap *map, GLenum internalFormat,
+ const SupportRequirement &desktopTexture, const SupportRequirement &desktopFilter, const SupportRequirement &desktopRender,
+ const SupportRequirement &esTexture, const SupportRequirement &esFilter, const SupportRequirement &esRender)
+{
+ InternalFormatInfo formatInfo;
+ formatInfo.glInfo.texture = desktopTexture;
+ formatInfo.glInfo.filter = desktopFilter;
+ formatInfo.glInfo.renderbuffer = desktopRender;
+ formatInfo.glInfo.framebufferAttachment = desktopRender;
+ formatInfo.glesInfo.texture = esTexture;
+ formatInfo.glesInfo.filter = esTexture;
+ formatInfo.glesInfo.renderbuffer = esFilter;
+ formatInfo.glesInfo.framebufferAttachment = esRender;
+ map->insert(std::make_pair(internalFormat, formatInfo));
+}
+
+static InternalFormatInfoMap BuildInternalFormatInfoMap()
+{
+ InternalFormatInfoMap map;
+
+ // clang-format off
+ // | Format | OpenGL texture support | Filter | OpenGL render support | OpenGL ES texture support | Filter | OpenGL ES render support |
+ InsertFormatMapping(&map, GL_R8, VersionOrExts(3, 0, "GL_ARB_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOrExts(3, 0, "GL_EXT_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_EXT_texture_rg") );
+ InsertFormatMapping(&map, GL_R8_SNORM, VersionOnly(3, 1), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_RG8, VersionOrExts(3, 0, "GL_ARB_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOrExts(3, 0, "GL_EXT_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg") );
+ InsertFormatMapping(&map, GL_RG8_SNORM, VersionOnly(3, 1), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_RGB8, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), VersionOrExts(3, 0, "GL_OES_rgb8_rgba8"), AlwaysSupported(), AlwaysSupported() );
+ InsertFormatMapping(&map, GL_RG8_SNORM, VersionOnly(3, 1), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_RGB565, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported() );
+ InsertFormatMapping(&map, GL_RGBA4, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported() );
+ InsertFormatMapping(&map, GL_RGB5_A1, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported() );
+ InsertFormatMapping(&map, GL_RGBA8, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), VersionOrExts(3, 0, "GL_OES_rgb8_rgba8"), AlwaysSupported(), VersionOrExts(3, 0, "GL_OES_rgb8_rgba8") );
+ InsertFormatMapping(&map, GL_RGBA8_SNORM, VersionOnly(3, 1), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_RGB10_A2, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), VersionOnly(3, 0), AlwaysSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RGB10_A2UI, VersionOrExts(3, 3, "GL_ARB_texture_rgb10_a2ui"), NeverSupported(), AlwaysSupported(), VersionOnly(3, 0), NeverSupported(), AlwaysSupported() );
+ InsertFormatMapping(&map, GL_SRGB8, VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), AlwaysSupported(), VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), VersionOnly(3, 0), AlwaysSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_SRGB8_ALPHA8, VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), AlwaysSupported(), VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), VersionOnly(3, 0), AlwaysSupported(), VersionOrExts(3, 0, "GL_EXT_sRGB") );
+ InsertFormatMapping(&map, GL_R8I, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_R8UI, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_R16I, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_R16UI, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_R32I, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_R32UI, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RG8I, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RG8UI, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RG16I, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RG16UI, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RG32I, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RG32UI, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RGB8I, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_RGB8UI, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_RGB16I, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_RGB16UI, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_RGB32I, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_RGB32UI, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_RGBA8I, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RGBA8UI, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RGBA16I, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RGBA16UI, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RGBA32I, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RGBA32UI, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+
+ // Unsized formats
+ InsertFormatMapping(&map, GL_ALPHA, NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_LUMINANCE, NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_RED, VersionOrExts(3, 0, "GL_ARB_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOrExts(3, 0, "GL_EXT_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg") );
+ InsertFormatMapping(&map, GL_RG, VersionOrExts(3, 0, "GL_ARB_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOrExts(3, 0, "GL_EXT_texture_rg"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg") );
+ InsertFormatMapping(&map, GL_RGB, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported() );
+ InsertFormatMapping(&map, GL_RGBA, AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported(), AlwaysSupported() );
+ InsertFormatMapping(&map, GL_RED_INTEGER, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RG_INTEGER, VersionOrExts(3, 0, "GL_ARB_texture_rg"), NeverSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_RGB_INTEGER, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), NeverSupported(), VersionOnly(3, 0), NeverSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, VersionOrExts(3, 0, "GL_EXT_texture_integer"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_texture_integer"), VersionOnly(3, 0), NeverSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_SRGB, VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), AlwaysSupported(), VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), ExtsOnly("GL_EXT_sRGB"), AlwaysSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_SRGB_ALPHA, VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), AlwaysSupported(), VersionOrExts(2, 1, "GL_EXT_texture_sRGB"), ExtsOnly("GL_EXT_sRGB"), AlwaysSupported(), NeverSupported() );
+
+ // From GL_EXT_texture_format_BGRA8888
+ InsertFormatMapping(&map, GL_BGRA8_EXT, VersionOrExts(1, 2, "GL_EXT_bgra"), AlwaysSupported(), VersionOrExts(1, 2, "GL_EXT_bgra"), ExtsOnly("GL_EXT_texture_format_BGRA8888"), AlwaysSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_BGRA_EXT, VersionOrExts(1, 2, "GL_EXT_bgra"), AlwaysSupported(), VersionOrExts(1, 2, "GL_EXT_bgra"), ExtsOnly("GL_EXT_texture_format_BGRA8888"), AlwaysSupported(), NeverSupported() );
+
+ // Floating point formats
+ // | Format | OpenGL texture support | Filter | OpenGL render support | OpenGL ES texture support | Filter | OpenGL ES render support |
+ InsertFormatMapping(&map, GL_R11F_G11F_B10F, VersionOrExts(3, 0, "GL_EXT_packed_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_EXT_packed_float GL_ARB_color_buffer_float"), VersionOnly(3, 0), AlwaysSupported(), ExtsOnly("GL_EXT_color_buffer_float") );
+ InsertFormatMapping(&map, GL_RGB9_E5, VersionOrExts(3, 0, "GL_EXT_texture_shared_exponent"), AlwaysSupported(), VersionOrExts(3, 0, "GL_EXT_texture_shared_exponent GL_ARB_color_buffer_float"), VersionOnly(3, 0), AlwaysSupported(), NeverSupported() );
+ InsertFormatMapping(&map, GL_R16F, VersionOrExts(3, 0, "GL_ARB_texture_rg ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float GL_EXT_texture_rg"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), VersionOrExtsAndExts(3, 0, "GL_EXT_texture_rg", "GL_EXT_color_buffer_half_float"));
+ InsertFormatMapping(&map, GL_RG16F, VersionOrExts(3, 0, "GL_ARB_texture_rg ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float GL_EXT_texture_rg"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), VersionOrExtsAndExts(3, 0, "GL_EXT_texture_rg", "GL_EXT_color_buffer_half_float"));
+ InsertFormatMapping(&map, GL_RGB16F, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), ExtsOnly("GL_EXT_color_buffer_half_float") );
+ InsertFormatMapping(&map, GL_RGBA16F, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float"), VersionOrExts(3, 0, "GL_OES_texture_half_float_linear"), ExtsOnly("GL_EXT_color_buffer_half_float") );
+ InsertFormatMapping(&map, GL_R32F, VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_float GL_EXT_texture_rg"), VersionOrExts(3, 0, "GL_OES_texture_float_linear"), ExtsOnly("GL_EXT_color_buffer_float") );
+ InsertFormatMapping(&map, GL_RG32F, VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_rg GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_float GL_EXT_texture_rg"), VersionOrExts(3, 0, "GL_OES_texture_float_linear"), ExtsOnly("GL_EXT_color_buffer_float") );
+ InsertFormatMapping(&map, GL_RGB32F, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_float"), VersionOrExts(3, 0, "GL_OES_texture_float_linear"), NeverSupported() );
+ InsertFormatMapping(&map, GL_RGBA32F, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_texture_float GL_ARB_color_buffer_float"), VersionOrExts(3, 0, "GL_OES_texture_float"), VersionOrExts(3, 0, "GL_OES_texture_float_linear"), ExtsOnly("GL_EXT_color_buffer_float") );
+
+ // Depth stencil formats
+ // | Format | OpenGL texture support | Filter | OpenGL render support | OpenGL ES texture support | Filter | OpenGL ES render support |
+ InsertFormatMapping(&map, GL_DEPTH_COMPONENT16, VersionOnly(1, 5), VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5), VersionOnly(2, 0), VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(2, 0) );
+ InsertFormatMapping(&map, GL_DEPTH_COMPONENT24, VersionOnly(1, 5), VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5), VersionOnly(2, 0), VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(2, 0) );
+ InsertFormatMapping(&map, GL_DEPTH_COMPONENT32_OES, VersionOnly(1, 5), VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5), ExtsOnly("GL_OES_depth_texture"), AlwaysSupported(), ExtsOnly("GL_OES_depth32") );
+ InsertFormatMapping(&map, GL_DEPTH_COMPONENT32F, VersionOrExts(3, 0, "GL_ARB_depth_buffer_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_depth_buffer_float"), VersionOnly(3, 0), VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_STENCIL_INDEX8, VersionOrExts(3, 0, "GL_EXT_packed_depth_stencil"), NeverSupported(), VersionOrExts(3, 0, "GL_EXT_packed_depth_stencil"), VersionOnly(2, 0), NeverSupported(), VersionOnly(2, 0) );
+ InsertFormatMapping(&map, GL_DEPTH24_STENCIL8, VersionOrExts(3, 0, "GL_ARB_framebuffer_object"), VersionOrExts(3, 0, "GL_ARB_depth_texture"), VersionOrExts(3, 0, "GL_ARB_framebuffer_object"), VersionOrExts(3, 0, "GL_OES_depth_texture"), AlwaysSupported(), VersionOrExts(3, 0, "GL_OES_depth_texture GL_OES_packed_depth_stencil"));
+ InsertFormatMapping(&map, GL_DEPTH32F_STENCIL8, VersionOrExts(3, 0, "GL_ARB_depth_buffer_float"), AlwaysSupported(), VersionOrExts(3, 0, "GL_ARB_depth_buffer_float"), VersionOnly(3, 0), AlwaysSupported(), VersionOnly(3, 0) );
+ InsertFormatMapping(&map, GL_DEPTH_COMPONENT, VersionOnly(1, 5), VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5), VersionOnly(2, 0), VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(2, 0) );
+ InsertFormatMapping(&map, GL_DEPTH_STENCIL, VersionOnly(1, 5), VersionOrExts(1, 5, "GL_ARB_depth_texture"), VersionOnly(1, 5), VersionOnly(2, 0), VersionOrExts(3, 0, "GL_OES_depth_texture"), VersionOnly(2, 0) );
+
+ // Luminance alpha formats
+ // | Format | OpenGL texture support | Filter | Render | OpenGL ES texture support | Filter | Render |
+ InsertFormatMapping(&map, GL_ALPHA8_EXT, AlwaysSupported(), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_LUMINANCE8_EXT, AlwaysSupported(), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_ALPHA32F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_LUMINANCE32F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_ALPHA16F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_LUMINANCE16F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_LUMINANCE8_ALPHA8_EXT, AlwaysSupported(), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_LUMINANCE_ALPHA32F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_LUMINANCE_ALPHA16F_EXT, VersionOrExts(3, 0, "GL_ARB_texture_float"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_storage"), AlwaysSupported(), NeverSupported());
+
+ // Compressed formats, From ES 3.0.1 spec, table 3.16
+ InsertFormatMapping(&map, GL_COMPRESSED_R11_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_COMPRESSED_SIGNED_R11_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_COMPRESSED_RG11_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_COMPRESSED_SIGNED_RG11_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_COMPRESSED_RGB8_ETC2, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_COMPRESSED_SRGB8_ETC2, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOnly(3, 0), AlwaysSupported(), NeverSupported());
+
+ // From GL_EXT_texture_compression_dxt1
+ // | Format | OpenGL texture support | Filter | Render | OpenGL ES texture support | Filter | Render |
+ InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, ExtsOnly("GL_EXT_texture_compression_s3tc"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_compression_dxt1"), AlwaysSupported(), NeverSupported());
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, ExtsOnly("GL_EXT_texture_compression_s3tc"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_EXT_texture_compression_dxt1"), AlwaysSupported(), NeverSupported());
+
+ // From GL_ANGLE_texture_compression_dxt3
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_ANGLE_texture_compression_dxt3"), AlwaysSupported(), NeverSupported());
+
+ // From GL_ANGLE_texture_compression_dxt5
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"), AlwaysSupported(), NeverSupported(), ExtsOnly("GL_ANGLE_texture_compression_dxt5"), AlwaysSupported(), NeverSupported());
+
+ // From GL_ETC1_RGB8_OES
+ InsertFormatMapping(&map, GL_ETC1_RGB8_OES, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), AlwaysSupported(), NeverSupported(), VersionOrExts(3, 0, "GL_ETC1_RGB8_OES"), AlwaysSupported(), NeverSupported());
+
+ // clang-format on
+
+ return map;
+}
+
+static const InternalFormatInfoMap &GetInternalFormatMap()
+{
+ static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap();
+ return formatMap;
+}
+
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, StandardGL standard)
+{
+ const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
+ InternalFormatInfoMap::const_iterator iter = formatMap.find(internalFormat);
+ if (iter != formatMap.end())
+ {
+ const InternalFormatInfo &info = iter->second;
+ switch (standard)
+ {
+ case STANDARD_GL_ES: return info.glesInfo;
+ case STANDARD_GL_DESKTOP: return info.glInfo;
+ default: UNREACHABLE(); break;
+ }
+ }
+
+ static const InternalFormat defaultInternalFormat;
+ return defaultInternalFormat;
+}
+
+static GLenum GetNativeInternalFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum internalFormat,
+ GLenum sizedInternalFormat)
+{
+ GLenum result = internalFormat;
+
+ if (functions->standard == STANDARD_GL_DESKTOP)
+ {
+ // Use sized internal formats whenever possible to guarantee the requested precision.
+ // On Desktop GL, passing an internal format of GL_RGBA will generate a GL_RGBA8 texture
+ // even if the provided type is GL_FLOAT.
+ result = sizedInternalFormat;
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
+
+ if (workarounds.avoid1BitAlphaTextureFormats && formatInfo.alphaBits == 1)
+ {
+ // Use an 8-bit format instead
+ result = GL_RGBA8;
+ }
+
+ if (workarounds.rgba4IsNotSupportedForColorRendering && sizedInternalFormat == GL_RGBA4)
+ {
+ // Use an 8-bit format instead
+ result = GL_RGBA8;
+ }
+
+ if (sizedInternalFormat == GL_RGB565 && !functions->isAtLeastGL(gl::Version(4, 1)) &&
+ !functions->hasGLExtension("GL_ARB_ES2_compatibility"))
+ {
+ // GL_RGB565 is required for basic ES2 functionality but was not added to desktop GL
+ // until 4.1.
+ // Work around this by using an 8-bit format instead.
+ result = GL_RGB8;
+ }
+
+ if (sizedInternalFormat == GL_BGRA8_EXT)
+ {
+ // GLES accepts GL_BGRA as an internal format but desktop GL only accepts it as a type.
+ // Update the internal format to GL_RGBA.
+ result = GL_RGBA8;
+ }
+
+ if ((functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
+ {
+ // Work around deprecated luminance alpha formats in the OpenGL core profile by backing
+ // them with R or RG textures.
+ if (formatInfo.format == GL_LUMINANCE || formatInfo.format == GL_ALPHA)
+ {
+ result = gl::GetSizedInternalFormat(GL_RED, formatInfo.type);
+ }
+
+ if (formatInfo.format == GL_LUMINANCE_ALPHA)
+ {
+ result = gl::GetSizedInternalFormat(GL_RG, formatInfo.type);
+ }
+ }
+ }
+
+ return result;
+}
+
+static GLenum GetNativeFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum format)
+{
+ GLenum result = format;
+
+ if (functions->standard == STANDARD_GL_DESKTOP)
+ {
+ // The ES SRGB extensions require that the provided format is GL_SRGB or SRGB_ALPHA but
+ // the desktop GL extensions only accept GL_RGB or GL_RGBA. Convert them.
+ if (format == GL_SRGB)
+ {
+ result = GL_RGB;
+ }
+
+ if (format == GL_SRGB_ALPHA)
+ {
+ result = GL_RGBA;
+ }
+
+ if ((functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
+ {
+ // Work around deprecated luminance alpha formats in the OpenGL core profile by backing
+ // them with R or RG textures.
+ if (format == GL_LUMINANCE || format == GL_ALPHA)
+ {
+ result = GL_RED;
+ }
+
+ if (format == GL_LUMINANCE_ALPHA)
+ {
+ result = GL_RG;
+ }
+ }
+ }
+
+ return result;
+}
+
+static GLenum GetNativeCompressedFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum format)
+{
+ GLenum result = format;
+
+ if (functions->standard == STANDARD_GL_DESKTOP)
+ {
+ if (format == GL_ETC1_RGB8_OES)
+ {
+ // GL_ETC1_RGB8_OES is not available in any desktop GL extension but the compression
+ // format is forwards compatible so just use the ETC2 format.
+ result = GL_COMPRESSED_RGB8_ETC2;
+ }
+ }
+
+ if (functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ if (format == GL_ETC1_RGB8_OES)
+ {
+ // Pass GL_COMPRESSED_RGB8_ETC2 as the target format in ES3 and higher because it
+ // becomes a core format.
+ result = GL_COMPRESSED_RGB8_ETC2;
+ }
+ }
+
+ return result;
+}
+
+static GLenum GetNativeType(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum type)
+{
+ GLenum result = type;
+
+ if (functions->standard == STANDARD_GL_DESKTOP)
+ {
+ if (type == GL_HALF_FLOAT_OES)
+ {
+ // The enums differ for the OES half float extensions and desktop GL spec. Update it.
+ result = GL_HALF_FLOAT;
+ }
+ }
+
+ if (functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ if (type == GL_HALF_FLOAT_OES)
+ {
+ // The enums differ for the OES half float extensions and ES 3 spec. Update it.
+ result = GL_HALF_FLOAT;
+ }
+ }
+
+ return result;
+}
+
+static GLenum GetNativeReadType(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum type)
+{
+ GLenum result = type;
+
+ if (functions->standard == STANDARD_GL_DESKTOP)
+ {
+ if (type == GL_HALF_FLOAT_OES)
+ {
+ // The enums differ for the OES half float extensions and desktop GL spec. Update it.
+ result = GL_HALF_FLOAT;
+ }
+ }
+
+ return result;
+}
+
+static GLenum GetNativeReadFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum format)
+{
+ GLenum result = format;
+ return result;
+}
+
+TexImageFormat GetTexImageFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum internalFormat,
+ GLenum format,
+ GLenum type)
+{
+ TexImageFormat result;
+ result.internalFormat = GetNativeInternalFormat(
+ functions, workarounds, internalFormat, gl::GetSizedInternalFormat(internalFormat, type));
+ result.format = GetNativeFormat(functions, workarounds, format);
+ result.type = GetNativeType(functions, workarounds, type);
+ return result;
+}
+
+TexSubImageFormat GetTexSubImageFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum format,
+ GLenum type)
+{
+ TexSubImageFormat result;
+ result.format = GetNativeFormat(functions, workarounds, format);
+ result.type = GetNativeType(functions, workarounds, type);
+ return result;
+}
+
+CompressedTexImageFormat GetCompressedTexImageFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum internalFormat)
+{
+ CompressedTexImageFormat result;
+ result.internalFormat = GetNativeCompressedFormat(functions, workarounds, internalFormat);
+ return result;
+}
+
+CompressedTexSubImageFormat GetCompressedSubTexImageFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum format)
+{
+ CompressedTexSubImageFormat result;
+ result.format = GetNativeCompressedFormat(functions, workarounds, format);
+ return result;
+}
+
+CopyTexImageImageFormat GetCopyTexImageImageFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum internalFormat,
+ GLenum framebufferType)
+{
+ CopyTexImageImageFormat result;
+ result.internalFormat =
+ GetNativeInternalFormat(functions, workarounds, internalFormat,
+ gl::GetSizedInternalFormat(internalFormat, framebufferType));
+ return result;
+}
+
+TexStorageFormat GetTexStorageFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum internalFormat)
+{
+ TexStorageFormat result;
+ result.internalFormat =
+ GetNativeInternalFormat(functions, workarounds, internalFormat, internalFormat);
+ return result;
+}
+
+RenderbufferFormat GetRenderbufferFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum internalFormat)
+{
+ RenderbufferFormat result;
+ result.internalFormat =
+ GetNativeInternalFormat(functions, workarounds, internalFormat, internalFormat);
+ return result;
+}
+ReadPixelsFormat GetReadPixelsFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum format,
+ GLenum type)
+{
+ ReadPixelsFormat result;
+ result.format = GetNativeReadFormat(functions, workarounds, format);
+ result.type = GetNativeReadType(functions, workarounds, type);
+ return result;
+}
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.h b/gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.h
new file mode 100755
index 000000000..616f37af2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.h
@@ -0,0 +1,129 @@
+//
+// Copyright (c) 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.
+//
+
+// formatutilsgl.h: Queries for GL image formats and their translations to native
+// GL formats.
+
+#ifndef LIBANGLE_RENDERER_GL_FORMATUTILSGL_H_
+#define LIBANGLE_RENDERER_GL_FORMATUTILSGL_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "angle_gl.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+
+namespace rx
+{
+
+namespace nativegl
+{
+
+struct SupportRequirement
+{
+ SupportRequirement();
+
+ // Version that this format became supported without extensions
+ gl::Version version;
+
+ // Extensions that are required if the minimum version is not met
+ std::vector<std::string> versionExtensions;
+
+ // Extensions that are always required to support this format
+ std::vector<std::string> requiredExtensions;
+};
+
+struct InternalFormat
+{
+ InternalFormat();
+
+ SupportRequirement texture;
+ SupportRequirement filter;
+ SupportRequirement renderbuffer;
+ SupportRequirement framebufferAttachment;
+};
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, StandardGL standard);
+
+struct TexImageFormat
+{
+ GLenum internalFormat;
+ GLenum format;
+ GLenum type;
+};
+TexImageFormat GetTexImageFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum internalFormat,
+ GLenum format,
+ GLenum type);
+
+struct TexSubImageFormat
+{
+ GLenum format;
+ GLenum type;
+};
+TexSubImageFormat GetTexSubImageFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum format,
+ GLenum type);
+
+struct CompressedTexImageFormat
+{
+ GLenum internalFormat;
+};
+CompressedTexImageFormat GetCompressedTexImageFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum internalFormat);
+
+struct CompressedTexSubImageFormat
+{
+ GLenum format;
+};
+CompressedTexSubImageFormat GetCompressedSubTexImageFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum format);
+
+struct CopyTexImageImageFormat
+{
+ GLenum internalFormat;
+};
+CopyTexImageImageFormat GetCopyTexImageImageFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum internalFormat,
+ GLenum framebufferType);
+
+struct TexStorageFormat
+{
+ GLenum internalFormat;
+};
+TexStorageFormat GetTexStorageFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum internalFormat);
+
+struct RenderbufferFormat
+{
+ GLenum internalFormat;
+};
+RenderbufferFormat GetRenderbufferFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum internalFormat);
+
+struct ReadPixelsFormat
+{
+ GLenum format;
+ GLenum type;
+};
+ReadPixelsFormat GetReadPixelsFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum format,
+ GLenum type);
+}
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_FORMATUTILSGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/functionsgl_enums.h b/gfx/angle/src/libANGLE/renderer/gl/functionsgl_enums.h
new file mode 100755
index 000000000..918a7a1e6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/functionsgl_enums.h
@@ -0,0 +1,1375 @@
+//
+// Copyright (c) 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
+
+#endif // LIBANGLE_RENDERER_GL_FUNCTIONSGLENUMS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/functionsgl_typedefs.h b/gfx/angle/src/libANGLE/renderer/gl/functionsgl_typedefs.h
new file mode 100755
index 000000000..daf7ff74e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/functionsgl_typedefs.h
@@ -0,0 +1,758 @@
+//
+// Copyright (c) 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_typedefs.h: Typedefs of OpenGL types and functions for versions 1.0 through 4.5.
+
+#ifndef LIBANGLE_RENDERER_GL_FUNCTIONSGLTYPEDEFS_H_
+#define LIBANGLE_RENDERER_GL_FUNCTIONSGLTYPEDEFS_H_
+
+#include "common/platform.h"
+
+#include <KHR/khrplatform.h>
+#include <stdint.h>
+
+#ifndef INTERNAL_GL_APIENTRY
+# ifdef ANGLE_PLATFORM_WINDOWS
+# define INTERNAL_GL_APIENTRY __stdcall
+# else
+# define INTERNAL_GL_APIENTRY
+# endif
+#endif
+
+typedef void GLvoid;
+typedef char GLchar;
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef khronos_int8_t GLbyte;
+typedef short GLshort;
+typedef int GLint;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned int GLuint;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef khronos_int32_t GLfixed;
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t GLsizeiptr;
+typedef unsigned short GLhalf;
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef struct __GLsync *GLsync;
+
+namespace rx
+{
+typedef void (INTERNAL_GL_APIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam);
+typedef void (INTERNAL_GL_APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam);
+typedef void (INTERNAL_GL_APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar *message, void *userParam);
+
+// 1.0
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDFUNCPROC)(GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARPROC)(GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARCOLORPROC)(GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARDEPTHPROC)(GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARSTENCILPROC)(GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOLORMASKPROC)(GLboolean, GLboolean, GLboolean, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCULLFACEPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHFUNCPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHMASKPROC)(GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHRANGEPROC)(GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDISABLEPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWBUFFERPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENABLEPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFINISHPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFLUSHPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRONTFACEPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBOOLEANVPROC)(GLenum, GLboolean *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETDOUBLEVPROC)(GLenum, GLdouble *);
+typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLGETERRORPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFLOATVPROC)(GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTEGERVPROC)(GLenum, GLint *);
+typedef const GLubyte * (INTERNAL_GL_APIENTRY *PFNGLGETSTRINGPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXIMAGEPROC)(GLenum, GLint, GLenum, GLenum, GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum, GLint, GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum, GLint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXPARAMETERFVPROC)(GLenum, GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXPARAMETERIVPROC)(GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLHINTPROC)(GLenum, GLenum);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISENABLEDPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLLINEWIDTHPROC)(GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLLOGICOPPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPIXELSTOREFPROC)(GLenum, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPIXELSTOREIPROC)(GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTSIZEPROC)(GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOLYGONMODEPROC)(GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLREADBUFFERPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLREADPIXELSPROC)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSCISSORPROC)(GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILFUNCPROC)(GLenum, GLint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILMASKPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILOPPROC)(GLenum, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE1DPROC)(GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE2DPROC)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERFPROC)(GLenum, GLenum, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERFVPROC)(GLenum, GLenum, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERIPROC)(GLenum, GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERIVPROC)(GLenum, GLenum, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVIEWPORTPROC)(GLint, GLint, GLsizei, GLsizei);
+
+// 1.1
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDTEXTUREPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXIMAGE1DPROC)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXIMAGE2DPROC)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETETEXTURESPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWARRAYSPROC)(GLenum, GLint, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSPROC)(GLenum, GLsizei, GLenum, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENTEXTURESPROC)(GLsizei, GLuint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISTEXTUREPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOLYGONOFFSETPROC)(GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSUBIMAGE1DPROC)(GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSUBIMAGE2DPROC)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+
+// 1.2
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDCOLORPROC)(GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDEQUATIONPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWRANGEELEMENTSPROC)(GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE3DPROC)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+
+// 1.2 Extensions
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEFENCESNVPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENFENCESNVPROC)(GLsizei, GLuint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISFENCENVPROC)(GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLTESTFENCENVPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFENCEIVNVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFINISHFENCENVPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSETFENCENVPROC)(GLuint, GLenum);
+
+// 1.3
+typedef void (INTERNAL_GL_APIENTRY *PFNGLACTIVETEXTUREPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum, GLint, GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLECOVERAGEPROC)(GLfloat, GLboolean);
+
+// 1.4
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDFUNCSEPARATEPROC)(GLenum, GLenum, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWARRAYSPROC)(GLenum, const GLint *, const GLsizei *, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWELEMENTSPROC)(GLenum, const GLsizei *, GLenum, const GLvoid *const*, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTPARAMETERFPROC)(GLenum, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTPARAMETERFVPROC)(GLenum, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTPARAMETERIPROC)(GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOINTPARAMETERIVPROC)(GLenum, const GLint *);
+
+// 1.5
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBEGINQUERYPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBUFFERDATAPROC)(GLenum, GLsizeiptr, const GLvoid *, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBUFFERSUBDATAPROC)(GLenum, GLintptr, GLsizeiptr, const GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEBUFFERSPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEQUERIESPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENDQUERYPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENBUFFERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENQUERIESPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBUFFERPOINTERVPROC)(GLenum, GLenum, GLvoid **);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBUFFERSUBDATAPROC)(GLenum, GLintptr, GLsizeiptr, GLvoid *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYOBJECTIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYOBJECTUIVPROC)(GLuint, GLenum, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYIVPROC)(GLenum, GLenum, GLint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISBUFFERPROC)(GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISQUERYPROC)(GLuint);
+typedef void * (INTERNAL_GL_APIENTRY *PFNGLMAPBUFFERPROC)(GLenum, GLenum);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLUNMAPBUFFERPROC)(GLenum);
+
+// 2.0
+typedef void (INTERNAL_GL_APIENTRY *PFNGLATTACHSHADERPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDATTRIBLOCATIONPROC)(GLuint, GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPILESHADERPROC)(GLuint);
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLCREATEPROGRAMPROC)();
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLCREATESHADERPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEPROGRAMPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETESHADERPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDETACHSHADERPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWBUFFERSPROC)(GLsizei, const GLenum *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEATTRIBPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETATTACHEDSHADERSPROC)(GLuint, GLsizei, GLsizei *, GLuint *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETATTRIBLOCATIONPROC)(GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMINFOLOGPROC)(GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSHADERINFOLOGPROC)(GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSHADERSOURCEPROC)(GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSHADERIVPROC)(GLuint, GLenum, GLint *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMLOCATIONPROC)(GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMFVPROC)(GLuint, GLint, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMIVPROC)(GLuint, GLint, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint, GLenum, GLvoid **);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint, GLenum, GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBFVPROC)(GLuint, GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBIVPROC)(GLuint, GLenum, GLint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISPROGRAMPROC)(GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISSHADERPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLLINKPROGRAMPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSHADERSOURCEPROC)(GLuint, GLsizei, const GLchar *const*, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum, GLenum, GLint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILMASKSEPARATEPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSTENCILOPSEPARATEPROC)(GLenum, GLenum, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1FPROC)(GLint, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1FVPROC)(GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1IPROC)(GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1IVPROC)(GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2FPROC)(GLint, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2FVPROC)(GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2IPROC)(GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2IVPROC)(GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3FPROC)(GLint, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3FVPROC)(GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3IPROC)(GLint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3IVPROC)(GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4FPROC)(GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4FVPROC)(GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4IPROC)(GLint, GLint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4IVPROC)(GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUSEPROGRAMPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVALIDATEPROGRAMPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1DPROC)(GLuint, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1FPROC)(GLuint, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1FVPROC)(GLuint, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1SPROC)(GLuint, GLshort);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB1SVPROC)(GLuint, const GLshort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2DPROC)(GLuint, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2FPROC)(GLuint, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2FVPROC)(GLuint, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2SPROC)(GLuint, GLshort, GLshort);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB2SVPROC)(GLuint, const GLshort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3DPROC)(GLuint, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3FPROC)(GLuint, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3FVPROC)(GLuint, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3SPROC)(GLuint, GLshort, GLshort, GLshort);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB3SVPROC)(GLuint, const GLshort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NBVPROC)(GLuint, const GLbyte *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NIVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NSVPROC)(GLuint, const GLshort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NUBPROC)(GLuint, GLubyte, GLubyte, GLubyte, GLubyte);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NUBVPROC)(GLuint, const GLubyte *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NUIVPROC)(GLuint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4NUSVPROC)(GLuint, const GLushort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4BVPROC)(GLuint, const GLbyte *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4DPROC)(GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4FPROC)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4FVPROC)(GLuint, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4IVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4SPROC)(GLuint, GLshort, GLshort, GLshort, GLshort);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4SVPROC)(GLuint, const GLshort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4UBVPROC)(GLuint, const GLubyte *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4UIVPROC)(GLuint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIB4USVPROC)(GLuint, const GLushort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+
+// 2.1
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint, GLsizei, GLboolean, const GLfloat *);
+
+// 3.0
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBEGINCONDITIONALRENDERPROC)(GLuint, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERBASEPROC)(GLenum, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERRANGEPROC)(GLenum, GLuint, GLuint, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDFRAGDATALOCATIONPROC)(GLuint, GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDFRAMEBUFFERPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDRENDERBUFFERPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDVERTEXARRAYPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLITFRAMEBUFFERPROC)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum);
+typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLAMPCOLORPROC)(GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERFIPROC)(GLenum, GLint, GLfloat, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERFVPROC)(GLenum, GLint, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERIVPROC)(GLenum, GLint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERUIVPROC)(GLenum, GLint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOLORMASKIPROC)(GLuint, GLboolean, GLboolean, GLboolean, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETERENDERBUFFERSPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEVERTEXARRAYSPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDISABLEIPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENABLEIPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENDCONDITIONALRENDERPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENDTRANSFORMFEEDBACKPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum, GLenum, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum, GLenum, GLenum, GLuint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum, GLenum, GLenum, GLuint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum, GLenum, GLenum, GLuint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum, GLenum, GLuint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENFRAMEBUFFERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENRENDERBUFFERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENVERTEXARRAYSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENERATEMIPMAPPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBOOLEANI_VPROC)(GLenum, GLuint, GLboolean *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETFRAGDATALOCATIONPROC)(GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum, GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTEGERI_VPROC)(GLenum, GLuint, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum, GLenum, GLint *);
+typedef const GLubyte * (INTERNAL_GL_APIENTRY *PFNGLGETSTRINGIPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXPARAMETERIIVPROC)(GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXPARAMETERIUIVPROC)(GLenum, GLenum, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMUIVPROC)(GLuint, GLint, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint, GLenum, GLuint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISENABLEDIPROC)(GLenum, GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISFRAMEBUFFERPROC)(GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISRENDERBUFFERPROC)(GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISVERTEXARRAYPROC)(GLuint);
+typedef void * (INTERNAL_GL_APIENTRY *PFNGLMAPBUFFERRANGEPROC)(GLenum, GLintptr, GLsizeiptr, GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum, GLenum, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERIIVPROC)(GLenum, GLenum, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXPARAMETERIUIVPROC)(GLenum, GLenum, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint, GLsizei, const GLchar *const*, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1UIPROC)(GLint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1UIVPROC)(GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2UIPROC)(GLint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2UIVPROC)(GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3UIPROC)(GLint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3UIVPROC)(GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4UIPROC)(GLint, GLuint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4UIVPROC)(GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI1IPROC)(GLuint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI1IVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI1UIPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI1UIVPROC)(GLuint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI2IPROC)(GLuint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI2IVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI2UIPROC)(GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI2UIVPROC)(GLuint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI3IPROC)(GLuint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI3IVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI3UIPROC)(GLuint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI3UIVPROC)(GLuint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4BVPROC)(GLuint, const GLbyte *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4IPROC)(GLuint, GLint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4IVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4SVPROC)(GLuint, const GLshort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4UBVPROC)(GLuint, const GLubyte *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4UIPROC)(GLuint, GLuint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBI4USVPROC)(GLuint, const GLushort *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint, GLint, GLenum, GLsizei, const GLvoid *);
+
+// 3.1
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum, GLsizei, GLenum, const GLvoid *, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint, GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint, GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint, GLsizei, const GLuint *, GLenum, GLint *);
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMINDICESPROC)(GLuint, GLsizei, const GLchar *const*, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXBUFFERPROC)(GLenum, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint, GLuint, GLuint);
+
+// 3.2
+typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLCLIENTWAITSYNCPROC)(GLsync, GLbitfield, GLuint64);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETESYNCPROC)(GLsync);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum, GLsizei, GLenum, const GLvoid *, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum, GLsizei, GLenum, const GLvoid *, GLsizei, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *, GLint);
+typedef GLsync (INTERNAL_GL_APIENTRY *PFNGLFENCESYNCPROC)(GLenum, GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum, GLenum, GLuint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum, GLenum, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTEGER64I_VPROC)(GLenum, GLuint, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTEGER64VPROC)(GLenum, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETMULTISAMPLEFVPROC)(GLenum, GLuint, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSYNCIVPROC)(GLsync, GLenum, GLsizei, GLsizei *, GLint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISSYNCPROC)(GLsync);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum, const GLsizei *, GLenum, const GLvoid *const*, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROVOKINGVERTEXPROC)(GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLEMASKIPROC)(GLuint, GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum, GLsizei, GLint, GLsizei, GLsizei, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum, GLsizei, GLint, GLsizei, GLsizei, GLsizei, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLWAITSYNCPROC)(GLsync, GLbitfield, GLuint64);
+
+// 3.3
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint, GLuint, GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDSAMPLERPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETESAMPLERSPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENSAMPLERSPROC)(GLsizei, GLuint *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETFRAGDATAINDEXPROC)(GLuint, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYOBJECTI64VPROC)(GLuint, GLenum, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYOBJECTUI64VPROC)(GLuint, GLenum, GLuint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint, GLenum, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint, GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint, GLenum, GLint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISSAMPLERPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLQUERYCOUNTERPROC)(GLuint, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERIIVPROC)(GLuint, GLenum, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint, GLenum, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERFPROC)(GLuint, GLenum, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERFVPROC)(GLuint, GLenum, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERIPROC)(GLuint, GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSAMPLERPARAMETERIVPROC)(GLuint, GLenum, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBDIVISORPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP1UIPROC)(GLuint, GLenum, GLboolean, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP1UIVPROC)(GLuint, GLenum, GLboolean, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP2UIPROC)(GLuint, GLenum, GLboolean, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP2UIVPROC)(GLuint, GLenum, GLboolean, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP3UIPROC)(GLuint, GLenum, GLboolean, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP3UIVPROC)(GLuint, GLenum, GLboolean, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP4UIPROC)(GLuint, GLenum, GLboolean, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBP4UIVPROC)(GLuint, GLenum, GLboolean, const GLuint *);
+
+// 4.0
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBEGINQUERYINDEXEDPROC)(GLenum, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDTRANSFORMFEEDBACKPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDEQUATIONSEPARATEIPROC)(GLuint, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDEQUATIONIPROC)(GLuint, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDFUNCSEPARATEIPROC)(GLuint, GLenum, GLenum, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLENDFUNCIPROC)(GLuint, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETETRANSFORMFEEDBACKSPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWARRAYSINDIRECTPROC)(GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINDIRECTPROC)(GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWTRANSFORMFEEDBACKPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC)(GLenum, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENDQUERYINDEXEDPROC)(GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENTRANSFORMFEEDBACKSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVESUBROUTINENAMEPROC)(GLuint, GLenum, GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC)(GLuint, GLenum, GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC)(GLuint, GLenum, GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMSTAGEIVPROC)(GLuint, GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYINDEXEDIVPROC)(GLenum, GLuint, GLenum, GLint *);
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLGETSUBROUTINEINDEXPROC)(GLuint, GLenum, const GLchar *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC)(GLuint, GLenum, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMSUBROUTINEUIVPROC)(GLenum, GLint, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETUNIFORMDVPROC)(GLuint, GLint, GLdouble *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISTRANSFORMFEEDBACKPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMINSAMPLESHADINGPROC)(GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPATCHPARAMETERFVPROC)(GLenum, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPATCHPARAMETERIPROC)(GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPAUSETRANSFORMFEEDBACKPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLRESUMETRANSFORMFEEDBACKPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1DPROC)(GLint, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM1DVPROC)(GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2DPROC)(GLint, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM2DVPROC)(GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3DPROC)(GLint, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM3DVPROC)(GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4DPROC)(GLint, GLdouble, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORM4DVPROC)(GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2X3DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX2X4DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3X2DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX3X4DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4X2DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMMATRIX4X3DVPROC)(GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUNIFORMSUBROUTINESUIVPROC)(GLenum, GLsizei, const GLuint *);
+
+// 4.1
+typedef void (INTERNAL_GL_APIENTRY *PFNGLACTIVESHADERPROGRAMPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDPROGRAMPIPELINEPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARDEPTHFPROC)(GLfloat);
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLCREATESHADERPROGRAMVPROC)(GLenum, GLsizei, const GLchar *const*);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEPROGRAMPIPELINESPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHRANGEARRAYVPROC)(GLuint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHRANGEINDEXEDPROC)(GLuint, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEPTHRANGEFPROC)(GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENPROGRAMPIPELINESPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETDOUBLEI_VPROC)(GLenum, GLuint, GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFLOATI_VPROC)(GLenum, GLuint, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMBINARYPROC)(GLuint, GLsizei, GLsizei *, GLenum *, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMPIPELINEINFOLOGPROC)(GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMPIPELINEIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETSHADERPRECISIONFORMATPROC)(GLenum, GLenum, GLint *, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXATTRIBLDVPROC)(GLuint, GLenum, GLdouble *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISPROGRAMPIPELINEPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMBINARYPROC)(GLuint, GLenum, const void *, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMPARAMETERIPROC)(GLuint, GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1DPROC)(GLuint, GLint, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1DVPROC)(GLuint, GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1FPROC)(GLuint, GLint, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1FVPROC)(GLuint, GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1IPROC)(GLuint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1IVPROC)(GLuint, GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1UIPROC)(GLuint, GLint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM1UIVPROC)(GLuint, GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2DPROC)(GLuint, GLint, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2DVPROC)(GLuint, GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2FPROC)(GLuint, GLint, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2FVPROC)(GLuint, GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2IPROC)(GLuint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2IVPROC)(GLuint, GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2UIPROC)(GLuint, GLint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM2UIVPROC)(GLuint, GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3DPROC)(GLuint, GLint, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3DVPROC)(GLuint, GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3FPROC)(GLuint, GLint, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3FVPROC)(GLuint, GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3IPROC)(GLuint, GLint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3IVPROC)(GLuint, GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3UIPROC)(GLuint, GLint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM3UIVPROC)(GLuint, GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4DPROC)(GLuint, GLint, GLdouble, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4DVPROC)(GLuint, GLint, GLsizei, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4FPROC)(GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4FVPROC)(GLuint, GLint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4IPROC)(GLuint, GLint, GLint, GLint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4IVPROC)(GLuint, GLint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4UIPROC)(GLuint, GLint, GLuint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORM4UIVPROC)(GLuint, GLint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC)(GLuint, GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLRELEASESHADERCOMPILERPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSCISSORARRAYVPROC)(GLuint, GLsizei, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSCISSORINDEXEDPROC)(GLuint, GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSCISSORINDEXEDVPROC)(GLuint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSHADERBINARYPROC)(GLsizei, const GLuint *, GLenum, const void *, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLUSEPROGRAMSTAGESPROC)(GLuint, GLbitfield, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVALIDATEPROGRAMPIPELINEPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL1DPROC)(GLuint, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL1DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL2DPROC)(GLuint, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL2DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL3DPROC)(GLuint, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL3DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL4DPROC)(GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBL4DVPROC)(GLuint, const GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBLPOINTERPROC)(GLuint, GLint, GLenum, GLsizei, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVIEWPORTARRAYVPROC)(GLuint, GLsizei, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVIEWPORTINDEXEDFPROC)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVIEWPORTINDEXEDFVPROC)(GLuint, const GLfloat *);
+
+// 4.2
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDIMAGETEXTUREPROC)(GLuint, GLuint, GLint, GLboolean, GLint, GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC)(GLenum, GLint, GLsizei, GLsizei, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC)(GLenum, GLsizei, GLenum, const void *, GLsizei, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC)(GLenum, GLsizei, GLenum, const void *, GLsizei, GLint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC)(GLenum, GLuint, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC)(GLenum, GLuint, GLuint, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC)(GLuint, GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTERNALFORMATIVPROC)(GLenum, GLenum, GLenum, GLsizei, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMEMORYBARRIERPROC)(GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE1DPROC)(GLenum, GLsizei, GLenum, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE2DPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE3DPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei);
+
+// 4.3
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDVERTEXBUFFERPROC)(GLuint, GLuint, GLintptr, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERDATAPROC)(GLenum, GLenum, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARBUFFERSUBDATAPROC)(GLenum, GLenum, GLintptr, GLsizeiptr, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYIMAGESUBDATAPROC)(GLuint, GLenum, GLint, GLint, GLint, GLint, GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEBUGMESSAGECALLBACKPROC)(GLDEBUGPROC, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEBUGMESSAGECONTROLPROC)(GLenum, GLenum, GLenum, GLsizei, const GLuint *, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDEBUGMESSAGEINSERTPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDISPATCHCOMPUTEPROC)(GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDISPATCHCOMPUTEINDIRECTPROC)(GLintptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFRAMEBUFFERPARAMETERIPROC)(GLenum, GLenum, GLint);
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLGETDEBUGMESSAGELOGPROC)(GLuint, GLsizei, GLenum *, GLenum *, GLuint *, GLenum *, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFRAMEBUFFERPARAMETERIVPROC)(GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETINTERNALFORMATI64VPROC)(GLenum, GLenum, GLenum, GLsizei, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPOINTERVPROC)(GLenum, void **);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETOBJECTLABELPROC)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETOBJECTPTRLABELPROC)(const void *, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMINTERFACEIVPROC)(GLuint, GLenum, GLenum, GLint *);
+typedef GLuint (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCEINDEXPROC)(GLuint, GLenum, const GLchar *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCELOCATIONPROC)(GLuint, GLenum, const GLchar *);
+typedef GLint (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC)(GLuint, GLenum, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCENAMEPROC)(GLuint, GLenum, GLuint, GLsizei, GLsizei *, GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETPROGRAMRESOURCEIVPROC)(GLuint, GLenum, GLuint, GLsizei, const GLenum *, GLsizei, GLsizei *, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATEBUFFERDATAPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATEBUFFERSUBDATAPROC)(GLuint, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATEFRAMEBUFFERPROC)(GLenum, GLsizei, const GLenum *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATESUBFRAMEBUFFERPROC)(GLenum, GLsizei, const GLenum *, GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATETEXIMAGEPROC)(GLuint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATETEXSUBIMAGEPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWARRAYSINDIRECTPROC)(GLenum, const void *, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMULTIDRAWELEMENTSINDIRECTPROC)(GLenum, GLenum, const void *, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLOBJECTLABELPROC)(GLenum, GLuint, GLsizei, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLOBJECTPTRLABELPROC)(const void *, GLsizei, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPOPDEBUGGROUPPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLPUSHDEBUGGROUPPROC)(GLenum, GLuint, GLsizei, const GLchar *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSHADERSTORAGEBLOCKBINDINGPROC)(GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXBUFFERRANGEPROC)(GLenum, GLenum, GLuint, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE2DMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSTORAGE3DMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREVIEWPROC)(GLuint, GLenum, GLuint, GLenum, GLuint, GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBBINDINGPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBFORMATPROC)(GLuint, GLint, GLenum, GLboolean, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBIFORMATPROC)(GLuint, GLint, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXATTRIBLFORMATPROC)(GLuint, GLint, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXBINDINGDIVISORPROC)(GLuint, GLuint);
+
+// NV_framebuffer_mixed_samples
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOVERAGEMODULATIONNVPROC)(GLenum);
+
+// 4.4
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERSBASEPROC)(GLenum, GLuint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDBUFFERSRANGEPROC)(GLenum, GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizeiptr *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDIMAGETEXTURESPROC)(GLuint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDSAMPLERSPROC)(GLuint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDTEXTURESPROC)(GLuint, GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDVERTEXBUFFERSPROC)(GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizei *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBUFFERSTORAGEPROC)(GLenum, GLsizeiptr, const void *, GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARTEXIMAGEPROC)(GLuint, GLint, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARTEXSUBIMAGEPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *);
+
+// 4.5
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBINDTEXTUREUNITPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLBLITNAMEDFRAMEBUFFERPROC)(GLuint, GLuint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum);
+typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC)(GLuint, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDBUFFERDATAPROC)(GLuint, GLenum, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDBUFFERSUBDATAPROC)(GLuint, GLenum, GLintptr, GLsizeiptr, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDFRAMEBUFFERFIPROC)(GLuint, GLenum, const GLfloat, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDFRAMEBUFFERFVPROC)(GLuint, GLenum, GLint, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDFRAMEBUFFERIVPROC)(GLuint, GLenum, GLint, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC)(GLuint, GLenum, GLint, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCLIPCONTROLPROC)(GLenum, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC)(GLuint, GLint, GLint, GLsizei, GLenum, GLsizei, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC)(GLuint, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYNAMEDBUFFERSUBDATAPROC)(GLuint, GLuint, GLintptr, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXTURESUBIMAGE1DPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXTURESUBIMAGE2DPROC)(GLuint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCOPYTEXTURESUBIMAGE3DPROC)(GLuint, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEBUFFERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEFRAMEBUFFERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEPROGRAMPIPELINESPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEQUERIESPROC)(GLenum, GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATERENDERBUFFERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATESAMPLERSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATETEXTURESPROC)(GLenum, GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATETRANSFORMFEEDBACKSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLCREATEVERTEXARRAYSPROC)(GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDISABLEVERTEXARRAYATTRIBPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLENABLEVERTEXARRAYATTRIBPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC)(GLuint, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENERATETEXTUREMIPMAPPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC)(GLuint, GLint, GLsizei, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, void *);
+typedef GLenum (INTERNAL_GL_APIENTRY *PFNGLGETGRAPHICSRESETSTATUSPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDBUFFERPARAMETERI64VPROC)(GLuint, GLenum, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDBUFFERPARAMETERIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDBUFFERPOINTERVPROC)(GLuint, GLenum, void **);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDBUFFERSUBDATAPROC)(GLuint, GLintptr, GLsizeiptr, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLuint, GLenum, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYBUFFEROBJECTI64VPROC)(GLuint, GLuint, GLenum, GLintptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYBUFFEROBJECTIVPROC)(GLuint, GLuint, GLenum, GLintptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYBUFFEROBJECTUI64VPROC)(GLuint, GLuint, GLenum, GLintptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETQUERYBUFFEROBJECTUIVPROC)(GLuint, GLuint, GLenum, GLintptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREIMAGEPROC)(GLuint, GLint, GLenum, GLenum, GLsizei, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTURELEVELPARAMETERFVPROC)(GLuint, GLint, GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTURELEVELPARAMETERIVPROC)(GLuint, GLint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREPARAMETERIIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREPARAMETERIUIVPROC)(GLuint, GLenum, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREPARAMETERFVPROC)(GLuint, GLenum, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTUREPARAMETERIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTEXTURESUBIMAGEPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTRANSFORMFEEDBACKI64_VPROC)(GLuint, GLenum, GLuint, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTRANSFORMFEEDBACKI_VPROC)(GLuint, GLenum, GLuint, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETTRANSFORMFEEDBACKIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXARRAYINDEXED64IVPROC)(GLuint, GLuint, GLenum, GLint64 *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXARRAYINDEXEDIVPROC)(GLuint, GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETVERTEXARRAYIVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNCOMPRESSEDTEXIMAGEPROC)(GLenum, GLint, GLsizei, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNTEXIMAGEPROC)(GLenum, GLint, GLenum, GLenum, GLsizei, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNUNIFORMDVPROC)(GLuint, GLint, GLsizei, GLdouble *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNUNIFORMFVPROC)(GLuint, GLint, GLsizei, GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNUNIFORMIVPROC)(GLuint, GLint, GLsizei, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETNUNIFORMUIVPROC)(GLuint, GLint, GLsizei, GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC)(GLuint, GLsizei, const GLenum *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC)(GLuint, GLsizei, const GLenum *, GLint, GLint, GLsizei, GLsizei);
+typedef void *(INTERNAL_GL_APIENTRY *PFNGLMAPNAMEDBUFFERPROC)(GLuint, GLenum);
+typedef void *(INTERNAL_GL_APIENTRY *PFNGLMAPNAMEDBUFFERRANGEPROC)(GLuint, GLintptr, GLsizeiptr, GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLMEMORYBARRIERBYREGIONPROC)(GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDBUFFERDATAPROC)(GLuint, GLsizeiptr, const void *, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDBUFFERSTORAGEPROC)(GLuint, GLsizeiptr, const void *, GLbitfield);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDBUFFERSUBDATAPROC)(GLuint, GLintptr, GLsizeiptr, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC)(GLuint, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC)(GLuint, GLsizei, const GLenum *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC)(GLuint, GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC)(GLuint, GLenum);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC)(GLuint, GLenum, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERTEXTUREPROC)(GLuint, GLenum, GLuint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC)(GLuint, GLenum, GLuint, GLint, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDRENDERBUFFERSTORAGEPROC)(GLuint, GLenum, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLREADNPIXELSPROC)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREBARRIERPROC)();
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREBUFFERPROC)(GLuint, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREBUFFERRANGEPROC)(GLuint, GLenum, GLuint, GLintptr, GLsizeiptr);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERIIVPROC)(GLuint, GLenum, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERIUIVPROC)(GLuint, GLenum, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERFPROC)(GLuint, GLenum, GLfloat);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERFVPROC)(GLuint, GLenum, const GLfloat *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERIPROC)(GLuint, GLenum, GLint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTUREPARAMETERIVPROC)(GLuint, GLenum, const GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE1DPROC)(GLuint, GLsizei, GLenum, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE2DPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE3DPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC)(GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESUBIMAGE1DPROC)(GLuint, GLint, GLint, GLsizei, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESUBIMAGE2DPROC)(GLuint, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXTURESUBIMAGE3DPROC)(GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC)(GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC)(GLuint, GLuint, GLuint, GLintptr, GLsizeiptr);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLUNMAPNAMEDBUFFERPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYATTRIBBINDINGPROC)(GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYATTRIBFORMATPROC)(GLuint, GLuint, GLint, GLenum, GLboolean, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYATTRIBIFORMATPROC)(GLuint, GLuint, GLint, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYATTRIBLFORMATPROC)(GLuint, GLuint, GLint, GLenum, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYBINDINGDIVISORPROC)(GLuint, GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYELEMENTBUFFERPROC)(GLuint, GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYVERTEXBUFFERPROC)(GLuint, GLuint, GLuint, GLintptr, GLsizei);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLVERTEXARRAYVERTEXBUFFERSPROC)(GLuint, GLuint, GLsizei, const GLuint *, const GLintptr *, const GLsizei *);
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_FUNCTIONSGLTYPEDEFS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp b/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
new file mode 100755
index 000000000..e98401d0a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
@@ -0,0 +1,981 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayGLX.cpp: GLX implementation of egl::Display
+
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+
+#include <EGL/eglext.h>
+#include <algorithm>
+#include <cstring>
+#include <fstream>
+
+#include "common/debug.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h"
+#include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+#include "third_party/libXNVCtrl/NVCtrl.h"
+#include "third_party/libXNVCtrl/NVCtrlLib.h"
+
+namespace
+{
+
+// Scan /etc/ati/amdpcsdb.default for "ReleaseVersion".
+// Return empty string on failing.
+egl::Error GetAMDDriverVersion(std::string *version)
+{
+ *version = "";
+
+ const char kAMDDriverInfoFileName[] = "/etc/ati/amdpcsdb.default";
+ std::ifstream file(kAMDDriverInfoFileName);
+
+ if (!file)
+ {
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ std::string line;
+ while (std::getline(file, line))
+ {
+ static const char kReleaseVersion[] = "ReleaseVersion=";
+ if (line.compare(0, std::strlen(kReleaseVersion), kReleaseVersion) != 0)
+ {
+ continue;
+ }
+
+ const size_t begin = line.find_first_of("0123456789");
+ if (begin == std::string::npos)
+ {
+ continue;
+ }
+
+ const size_t end = line.find_first_not_of("0123456789.", begin);
+ if (end == std::string::npos)
+ {
+ *version = line.substr(begin);
+ }
+ else
+ {
+ *version = line.substr(begin, end - begin);
+ }
+ return egl::Error(EGL_SUCCESS);
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+} // anonymous namespace
+
+namespace rx
+{
+
+static int IgnoreX11Errors(Display *, XErrorEvent *)
+{
+ return 0;
+}
+
+SwapControlData::SwapControlData()
+ : targetSwapInterval(0),
+ maxSwapInterval(-1),
+ currentSwapInterval(-1)
+{
+}
+
+class FunctionsGLGLX : public FunctionsGL
+{
+ public:
+ FunctionsGLGLX(PFNGETPROCPROC getProc)
+ : mGetProc(getProc)
+ {
+ }
+
+ ~FunctionsGLGLX() override {}
+
+ private:
+ void *loadProcAddress(const std::string &function) override
+ {
+ return reinterpret_cast<void*>(mGetProc(function.c_str()));
+ }
+
+ PFNGETPROCPROC mGetProc;
+};
+
+DisplayGLX::DisplayGLX()
+ : DisplayGL(),
+ mFunctionsGL(nullptr),
+ mRequestedVisual(-1),
+ mContextConfig(nullptr),
+ mContext(nullptr),
+ mDummyPbuffer(0),
+ mUsesNewXDisplay(false),
+ mIsMesa(false),
+ mHasMultisample(false),
+ mHasARBCreateContext(false),
+ mHasARBCreateContextProfile(false),
+ mHasARBCreateContextRobustness(false),
+ mHasEXTCreateContextES2Profile(false),
+ mSwapControl(SwapControl::Absent),
+ mMinSwapInterval(0),
+ mMaxSwapInterval(0),
+ mCurrentSwapInterval(-1),
+ mXDisplay(nullptr),
+ mEGLDisplay(nullptr)
+{
+}
+
+DisplayGLX::~DisplayGLX()
+{
+}
+
+egl::Error DisplayGLX::initialize(egl::Display *display)
+{
+ mEGLDisplay = display;
+ mXDisplay = display->getNativeDisplayId();
+ const auto &attribMap = display->getAttributeMap();
+
+ // ANGLE_platform_angle allows the creation of a default display
+ // using EGL_DEFAULT_DISPLAY (= nullptr). In this case just open
+ // the display specified by the DISPLAY environment variable.
+ if (mXDisplay == EGL_DEFAULT_DISPLAY)
+ {
+ mUsesNewXDisplay = true;
+ mXDisplay = XOpenDisplay(NULL);
+ if (!mXDisplay)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not open the default X display.");
+ }
+ }
+
+ std::string glxInitError;
+ if (!mGLX.initialize(mXDisplay, DefaultScreen(mXDisplay), &glxInitError))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, glxInitError.c_str());
+ }
+
+ mHasMultisample = mGLX.minorVersion > 3 || mGLX.hasExtension("GLX_ARB_multisample");
+ mHasARBCreateContext = mGLX.hasExtension("GLX_ARB_create_context");
+ mHasARBCreateContextProfile = mGLX.hasExtension("GLX_ARB_create_context_profile");
+ mHasARBCreateContextRobustness = mGLX.hasExtension("GLX_ARB_create_context_robustness");
+ mHasEXTCreateContextES2Profile = mGLX.hasExtension("GLX_EXT_create_context_es2_profile");
+
+ std::string clientVendor = mGLX.getClientString(GLX_VENDOR);
+ mIsMesa = clientVendor.find("Mesa") != std::string::npos;
+
+ // Choose the swap_control extension to use, if any.
+ // The EXT version is better as it allows glXSwapInterval to be called per
+ // window, while we'll potentially need to change the swap interval on each
+ // swap buffers when using the SGI or MESA versions.
+ if (mGLX.hasExtension("GLX_EXT_swap_control"))
+ {
+ mSwapControl = SwapControl::EXT;
+
+ // In GLX_EXT_swap_control querying these is done on a GLXWindow so we just
+ // set default values.
+ mMinSwapInterval = 0;
+ mMaxSwapInterval = 4;
+ }
+ else if (mGLX.hasExtension("GLX_MESA_swap_control"))
+ {
+ // If we have the Mesa or SGI extension, assume that you can at least set
+ // a swap interval of 0 or 1.
+ mSwapControl = SwapControl::Mesa;
+ mMinSwapInterval = 0;
+ mMinSwapInterval = 1;
+ }
+ else if (mGLX.hasExtension("GLX_SGI_swap_control"))
+ {
+ mSwapControl = SwapControl::SGI;
+ mMinSwapInterval = 0;
+ mMinSwapInterval = 1;
+ }
+ else
+ {
+ mSwapControl = SwapControl::Absent;
+ mMinSwapInterval = 1;
+ mMinSwapInterval = 1;
+ }
+
+ if (attribMap.contains(EGL_X11_VISUAL_ID_ANGLE))
+ {
+ mRequestedVisual = static_cast<EGLint>(attribMap.get(EGL_X11_VISUAL_ID_ANGLE, -1));
+
+ // There is no direct way to get the GLXFBConfig matching an X11 visual ID
+ // so we have to iterate over all the GLXFBConfigs to find the right one.
+ int nConfigs;
+ int attribList[] = {
+ None,
+ };
+ glx::FBConfig *allConfigs = mGLX.chooseFBConfig(attribList, &nConfigs);
+
+ for (int i = 0; i < nConfigs; ++i)
+ {
+ if (getGLXFBConfigAttrib(allConfigs[i], GLX_VISUAL_ID) == mRequestedVisual)
+ {
+ mContextConfig = allConfigs[i];
+ break;
+ }
+ }
+ XFree(allConfigs);
+
+ if (mContextConfig == nullptr)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Invalid visual ID requested.");
+ }
+ }
+ else
+ {
+ // When glXMakeCurrent is called, the context and the surface must be
+ // compatible which in glX-speak means that their config have the same
+ // color buffer type, are both RGBA or ColorIndex, and their buffers have
+ // the same depth, if they exist.
+ // Since our whole EGL implementation is backed by only one GL context, this
+ // context must be compatible with all the GLXFBConfig corresponding to the
+ // EGLconfigs that we will be exposing.
+ int nConfigs;
+ int attribList[] =
+ {
+ // We want RGBA8 and DEPTH24_STENCIL8
+ GLX_RED_SIZE, 8,
+ GLX_GREEN_SIZE, 8,
+ GLX_BLUE_SIZE, 8,
+ GLX_ALPHA_SIZE, 8,
+ GLX_DEPTH_SIZE, 24,
+ GLX_STENCIL_SIZE, 8,
+ // We want RGBA rendering (vs COLOR_INDEX) and doublebuffer
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ // Double buffer is not strictly required as a non-doublebuffer
+ // context can work with a doublebuffered surface, but it still
+ // flickers and all applications want doublebuffer anyway.
+ GLX_DOUBLEBUFFER, True,
+ // All of these must be supported for full EGL support
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PBUFFER_BIT | GLX_PIXMAP_BIT,
+ // This makes sure the config have an associated visual Id
+ GLX_X_RENDERABLE, True,
+ GLX_CONFIG_CAVEAT, GLX_NONE,
+ None
+ };
+ glx::FBConfig *candidates = mGLX.chooseFBConfig(attribList, &nConfigs);
+ if (nConfigs == 0)
+ {
+ XFree(candidates);
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not find a decent GLX FBConfig to create the context.");
+ }
+ mContextConfig = candidates[0];
+ XFree(candidates);
+ }
+
+ const auto &eglAttributes = display->getAttributeMap();
+ if (mHasARBCreateContext)
+ {
+ egl::Error error = initializeContext(mContextConfig, eglAttributes, &mContext);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ else
+ {
+ if (eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE,
+ EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) ==
+ EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED,
+ "Cannot create an OpenGL ES platform on GLX without the "
+ "GLX_ARB_create_context extension.");
+ }
+
+ XVisualInfo visualTemplate;
+ visualTemplate.visualid = getGLXFBConfigAttrib(mContextConfig, GLX_VISUAL_ID);
+
+ int numVisuals = 0;
+ XVisualInfo *visuals =
+ XGetVisualInfo(mXDisplay, VisualIDMask, &visualTemplate, &numVisuals);
+ if (numVisuals <= 0)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED,
+ "Could not get the visual info from the fb config");
+ }
+ ASSERT(numVisuals == 1);
+
+ mContext = mGLX.createContext(&visuals[0], nullptr, true);
+ XFree(visuals);
+
+ if (!mContext)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context.");
+ }
+ }
+ ASSERT(mContext);
+
+ // FunctionsGL and DisplayGL need to make a few GL calls, for example to
+ // query the version of the context so we need to make the context current.
+ // glXMakeCurrent requires a GLXDrawable so we create a temporary Pbuffer
+ // (of size 1, 1) for the duration of these calls.
+ // Ideally we would want to unset the current context and destroy the pbuffer
+ // before going back to the application but this is TODO
+ // We could use a pbuffer of size (0, 0) but it fails on the Intel Mesa driver
+ // as commented on https://bugs.freedesktop.org/show_bug.cgi?id=38869 so we
+ // use (1, 1) instead.
+
+ int dummyPbufferAttribs[] =
+ {
+ GLX_PBUFFER_WIDTH, 1,
+ GLX_PBUFFER_HEIGHT, 1,
+ None,
+ };
+ mDummyPbuffer = mGLX.createPbuffer(mContextConfig, dummyPbufferAttribs);
+ if (!mDummyPbuffer)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create the dummy pbuffer.");
+ }
+
+ if (!mGLX.makeCurrent(mDummyPbuffer, mContext))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not make the dummy pbuffer current.");
+ }
+
+ mFunctionsGL = new FunctionsGLGLX(mGLX.getProc);
+ mFunctionsGL->initialize();
+
+ // TODO(cwallez, angleproject:1303) Disable the OpenGL ES backend on Linux NVIDIA and Intel as
+ // it has problems on our automated testing. An OpenGL ES backend might not trigger this test if
+ // there is no Desktop OpenGL support, but that's not the case in our automated testing.
+ VendorID vendor = GetVendorID(mFunctionsGL);
+ bool isOpenGLES =
+ eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) ==
+ EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
+ if (isOpenGLES && (IsIntel(vendor) || IsNvidia(vendor)))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Intel or NVIDIA OpenGL ES drivers are not supported.");
+ }
+
+ syncXCommands();
+
+ return DisplayGL::initialize(display);
+}
+
+void DisplayGLX::terminate()
+{
+ DisplayGL::terminate();
+
+ if (mDummyPbuffer)
+ {
+ mGLX.destroyPbuffer(mDummyPbuffer);
+ mDummyPbuffer = 0;
+ }
+
+ if (mContext)
+ {
+ mGLX.destroyContext(mContext);
+ mContext = nullptr;
+ }
+
+ mGLX.terminate();
+
+ SafeDelete(mFunctionsGL);
+}
+
+SurfaceImpl *DisplayGLX::createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(configIdToGLXConfig.count(configuration->configID) > 0);
+ glx::FBConfig fbConfig = configIdToGLXConfig[configuration->configID];
+
+ return new WindowSurfaceGLX(state, mGLX, this, getRenderer(), window, mGLX.getDisplay(),
+ mContext, fbConfig);
+}
+
+SurfaceImpl *DisplayGLX::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(configIdToGLXConfig.count(configuration->configID) > 0);
+ glx::FBConfig fbConfig = configIdToGLXConfig[configuration->configID];
+
+ EGLint width = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0));
+ EGLint height = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0));
+ bool largest = (attribs.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
+
+ return new PbufferSurfaceGLX(state, getRenderer(), width, height, largest, mGLX, mContext,
+ fbConfig);
+}
+
+SurfaceImpl *DisplayGLX::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+SurfaceImpl *DisplayGLX::createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+egl::Error DisplayGLX::getDevice(DeviceImpl **device)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+egl::Error DisplayGLX::initializeContext(glx::FBConfig config,
+ const egl::AttributeMap &eglAttributes,
+ glx::Context *context)
+{
+ int profileMask = 0;
+
+ EGLint requestedDisplayType = static_cast<EGLint>(
+ eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
+ if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+ {
+ if (!mHasEXTCreateContextES2Profile)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED,
+ "Cannot create an OpenGL ES platform on GLX without the "
+ "GLX_EXT_create_context_es_profile extension.");
+ }
+
+ ASSERT(mHasARBCreateContextProfile);
+ profileMask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
+ }
+
+ // Create a context of the requested version, if any.
+ gl::Version requestedVersion(static_cast<EGLint>(eglAttributes.get(
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)),
+ static_cast<EGLint>(eglAttributes.get(
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE)));
+ if (static_cast<EGLint>(requestedVersion.major) != EGL_DONT_CARE &&
+ static_cast<EGLint>(requestedVersion.minor) != EGL_DONT_CARE)
+ {
+ if (!(profileMask & GLX_CONTEXT_ES2_PROFILE_BIT_EXT) &&
+ requestedVersion >= gl::Version(3, 2))
+ {
+ profileMask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+ }
+ return createContextAttribs(config, requestedVersion, profileMask, context);
+ }
+
+ // It is commonly assumed that glXCreateContextAttrib will create a context
+ // of the highest version possible but it is not specified in the spec and
+ // is not true on the Mesa drivers. On Mesa, Instead we try to create a
+ // context per GL version until we succeed, starting from newer version.
+ // On both Mesa and other drivers we try to create a desktop context and fall
+ // back to ES context.
+ // The code could be simpler if the Mesa code path was used for all drivers,
+ // however the cost of failing a context creation can be high (3 milliseconds
+ // for the NVIDIA driver). The good thing is that failed context creation only
+ // takes 0.1 milliseconds on Mesa.
+
+ struct ContextCreationInfo
+ {
+ EGLint displayType;
+ int profileFlag;
+ Optional<gl::Version> version;
+ };
+
+ // clang-format off
+ // For regular drivers we try to create a core, compatibility, then ES context.
+ // Without requiring any specific version (the Optional version is undefined).
+ const ContextCreationInfo contextsToTry[] = {
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, {} },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, {} },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, {} },
+ };
+
+ // On Mesa we try to create a core context, except for versions below 3.2
+ // where it is not applicable. (and fallback to ES as well)
+ const ContextCreationInfo mesaContextsToTry[] = {
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 5) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 4) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 3) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 2) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 1) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 0) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(3, 3) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(3, 2) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(3, 1) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(3, 0) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(2, 0) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 5) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 4) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 3) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 2) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 1) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 0) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(3, 2) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(3, 1) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(3, 0) } },
+ { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(2, 0) } },
+ };
+ // clang-format on
+
+ const ContextCreationInfo *toTry = contextsToTry;
+ size_t toTryLength = ArraySize(contextsToTry);
+ if (mIsMesa)
+ {
+ toTry = mesaContextsToTry;
+ toTryLength = ArraySize(mesaContextsToTry);
+ }
+
+ // NOTE: below we return as soon as we're able to create a context so the
+ // "error" variable is EGL_SUCCESS when returned contrary to the common idiom
+ // of returning "error" when there is an actual error.
+ for (size_t i = 0; i < toTryLength; ++i)
+ {
+ const ContextCreationInfo &info = toTry[i];
+ if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE &&
+ requestedDisplayType != info.displayType)
+ {
+ continue;
+ }
+
+ egl::Error error = createContextAttribs(config, info.version, info.profileFlag, context);
+ if (!error.isError())
+ {
+ return error;
+ }
+ }
+
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create a backing OpenGL context.");
+}
+
+egl::ConfigSet DisplayGLX::generateConfigs()
+{
+ egl::ConfigSet configs;
+ configIdToGLXConfig.clear();
+
+ const gl::Version &maxVersion = getMaxSupportedESVersion();
+ ASSERT(maxVersion >= gl::Version(2, 0));
+ bool supportsES3 = maxVersion >= gl::Version(3, 0);
+
+ int contextRedSize = getGLXFBConfigAttrib(mContextConfig, GLX_RED_SIZE);
+ int contextGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_GREEN_SIZE);
+ int contextBlueSize = getGLXFBConfigAttrib(mContextConfig, GLX_BLUE_SIZE);
+ int contextAlphaSize = getGLXFBConfigAttrib(mContextConfig, GLX_ALPHA_SIZE);
+
+ int contextDepthSize = getGLXFBConfigAttrib(mContextConfig, GLX_DEPTH_SIZE);
+ int contextStencilSize = getGLXFBConfigAttrib(mContextConfig, GLX_STENCIL_SIZE);
+
+ int contextSamples = mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLES) : 0;
+ int contextSampleBuffers =
+ mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLE_BUFFERS) : 0;
+
+ int contextAccumRedSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_RED_SIZE);
+ int contextAccumGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_GREEN_SIZE);
+ int contextAccumBlueSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_BLUE_SIZE);
+ int contextAccumAlphaSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_ALPHA_SIZE);
+
+ int attribList[] =
+ {
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_X_RENDERABLE, True,
+ GLX_DOUBLEBUFFER, True,
+ None,
+ };
+
+ int glxConfigCount;
+ glx::FBConfig *glxConfigs = mGLX.chooseFBConfig(attribList, &glxConfigCount);
+
+ for (int i = 0; i < glxConfigCount; i++)
+ {
+ glx::FBConfig glxConfig = glxConfigs[i];
+ egl::Config config;
+
+ // Native stuff
+ config.nativeVisualID = getGLXFBConfigAttrib(glxConfig, GLX_VISUAL_ID);
+ config.nativeVisualType = getGLXFBConfigAttrib(glxConfig, GLX_X_VISUAL_TYPE);
+ config.nativeRenderable = EGL_TRUE;
+
+ // When a visual ID has been specified with EGL_ANGLE_x11_visual we should
+ // only return configs with this visual: it will maximize performance by avoid
+ // blits in the driver when showing the window on the screen.
+ if (mRequestedVisual != -1 && config.nativeVisualID != mRequestedVisual)
+ {
+ continue;
+ }
+
+ // Buffer sizes
+ config.redSize = getGLXFBConfigAttrib(glxConfig, GLX_RED_SIZE);
+ config.greenSize = getGLXFBConfigAttrib(glxConfig, GLX_GREEN_SIZE);
+ config.blueSize = getGLXFBConfigAttrib(glxConfig, GLX_BLUE_SIZE);
+ config.alphaSize = getGLXFBConfigAttrib(glxConfig, GLX_ALPHA_SIZE);
+ config.depthSize = getGLXFBConfigAttrib(glxConfig, GLX_DEPTH_SIZE);
+ config.stencilSize = getGLXFBConfigAttrib(glxConfig, GLX_STENCIL_SIZE);
+
+ // We require RGBA8 and the D24S8 (or no DS buffer)
+ if (config.redSize != contextRedSize || config.greenSize != contextGreenSize ||
+ config.blueSize != contextBlueSize || config.alphaSize != contextAlphaSize)
+ {
+ continue;
+ }
+ // The GLX spec says that it is ok for a whole buffer to not be present
+ // however the Mesa Intel driver (and probably on other Mesa drivers)
+ // fails to make current when the Depth stencil doesn't exactly match the
+ // configuration.
+ bool hasSameDepthStencil =
+ config.depthSize == contextDepthSize && config.stencilSize == contextStencilSize;
+ bool hasNoDepthStencil = config.depthSize == 0 && config.stencilSize == 0;
+ if (!hasSameDepthStencil && (mIsMesa || !hasNoDepthStencil))
+ {
+ continue;
+ }
+
+ config.colorBufferType = EGL_RGB_BUFFER;
+ config.luminanceSize = 0;
+ config.alphaMaskSize = 0;
+
+ config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize;
+
+ // Multisample and accumulation buffers
+ int samples = mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLES) : 0;
+ int sampleBuffers =
+ mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLE_BUFFERS) : 0;
+
+ int accumRedSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_RED_SIZE);
+ int accumGreenSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_GREEN_SIZE);
+ int accumBlueSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_BLUE_SIZE);
+ int accumAlphaSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_ALPHA_SIZE);
+
+ if (samples != contextSamples ||
+ sampleBuffers != contextSampleBuffers ||
+ accumRedSize != contextAccumRedSize ||
+ accumGreenSize != contextAccumGreenSize ||
+ accumBlueSize != contextAccumBlueSize ||
+ accumAlphaSize != contextAccumAlphaSize)
+ {
+ continue;
+ }
+
+ config.samples = samples;
+ config.sampleBuffers = sampleBuffers;
+
+ // Transparency
+ if (getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_TYPE) == GLX_TRANSPARENT_RGB)
+ {
+ config.transparentType = EGL_TRANSPARENT_RGB;
+ config.transparentRedValue = getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_RED_VALUE);
+ config.transparentGreenValue = getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_GREEN_VALUE);
+ config.transparentBlueValue = getGLXFBConfigAttrib(glxConfig, GLX_TRANSPARENT_BLUE_VALUE);
+ }
+ else
+ {
+ config.transparentType = EGL_NONE;
+ }
+
+ // Pbuffer
+ config.maxPBufferWidth = getGLXFBConfigAttrib(glxConfig, GLX_MAX_PBUFFER_WIDTH);
+ config.maxPBufferHeight = getGLXFBConfigAttrib(glxConfig, GLX_MAX_PBUFFER_HEIGHT);
+ config.maxPBufferPixels = getGLXFBConfigAttrib(glxConfig, GLX_MAX_PBUFFER_PIXELS);
+
+ // Caveat
+ config.configCaveat = EGL_NONE;
+
+ int caveat = getGLXFBConfigAttrib(glxConfig, GLX_CONFIG_CAVEAT);
+ if (caveat == GLX_SLOW_CONFIG)
+ {
+ config.configCaveat = EGL_SLOW_CONFIG;
+ }
+ else if (caveat == GLX_NON_CONFORMANT_CONFIG)
+ {
+ continue;
+ }
+
+ // Misc
+ config.level = getGLXFBConfigAttrib(glxConfig, GLX_LEVEL);
+
+ config.bindToTextureRGB = EGL_FALSE;
+ config.bindToTextureRGBA = EGL_FALSE;
+
+ int glxDrawable = getGLXFBConfigAttrib(glxConfig, GLX_DRAWABLE_TYPE);
+ config.surfaceType = 0 |
+ (glxDrawable & GLX_WINDOW_BIT ? EGL_WINDOW_BIT : 0) |
+ (glxDrawable & GLX_PBUFFER_BIT ? EGL_PBUFFER_BIT : 0) |
+ (glxDrawable & GLX_PIXMAP_BIT ? EGL_PIXMAP_BIT : 0);
+
+ config.minSwapInterval = mMinSwapInterval;
+ config.maxSwapInterval = mMaxSwapInterval;
+
+ // TODO(cwallez) wildly guessing these formats, another TODO says they should be removed anyway
+ config.renderTargetFormat = GL_RGBA8;
+ config.depthStencilFormat = GL_DEPTH24_STENCIL8;
+
+ config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+ config.renderableType = config.conformant;
+
+ // TODO(cwallez) I have no idea what this is
+ config.matchNativePixmap = EGL_NONE;
+
+ int id = configs.add(config);
+ configIdToGLXConfig[id] = glxConfig;
+ }
+
+ XFree(glxConfigs);
+
+ return configs;
+}
+
+bool DisplayGLX::testDeviceLost()
+{
+ if (mHasARBCreateContextRobustness)
+ {
+ return getRenderer()->getResetStatus() != GL_NO_ERROR;
+ }
+
+ return false;
+}
+
+egl::Error DisplayGLX::restoreLostDevice()
+{
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+bool DisplayGLX::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ // There is no function in Xlib to check the validity of a Window directly.
+ // However a small number of functions used to obtain window information
+ // return a status code (0 meaning failure) and guarantee that they will
+ // fail if the window doesn't exist (the rational is that these function
+ // are used by window managers). Out of these function we use XQueryTree
+ // as it seems to be the simplest; a drawback is that it will allocate
+ // memory for the list of children, because we use a child window for
+ // WindowSurface.
+ Window root;
+ Window parent;
+ Window *children = nullptr;
+ unsigned nChildren;
+ int status = XQueryTree(mGLX.getDisplay(), window, &root, &parent, &children, &nChildren);
+ if (children)
+ {
+ XFree(children);
+ }
+ return status != 0;
+}
+
+std::string DisplayGLX::getVendorString() const
+{
+ // UNIMPLEMENTED();
+ return "";
+}
+
+egl::Error DisplayGLX::waitClient() const
+{
+ mGLX.waitGL();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayGLX::getDriverVersion(std::string *version) const
+{
+ VendorID vendor = GetVendorID(mFunctionsGL);
+
+ switch (vendor)
+ {
+ case VENDOR_ID_NVIDIA:
+ return getNVIDIADriverVersion(version);
+ case VENDOR_ID_AMD:
+ return GetAMDDriverVersion(version);
+ default:
+ *version = "";
+ return egl::Error(EGL_SUCCESS);
+ }
+}
+
+egl::Error DisplayGLX::waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const
+{
+ // eglWaitNative is used to notice the driver of changes in X11 for the current surface, such as
+ // changes of the window size. We use this event to update the child window of WindowSurfaceGLX
+ // to match its parent window's size.
+ // Handling eglWaitNative this way helps the application control when resize happens. This is
+ // important because drivers have a tendency to clobber the back buffer when the windows are
+ // resized. See http://crbug.com/326995
+ if (drawSurface != nullptr)
+ {
+ SurfaceGLX *glxDrawSurface = GetImplAs<SurfaceGLX>(drawSurface);
+ egl::Error error = glxDrawSurface->checkForResize();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ if (readSurface != drawSurface && readSurface != nullptr)
+ {
+ SurfaceGLX *glxReadSurface = GetImplAs<SurfaceGLX>(readSurface);
+ egl::Error error = glxReadSurface->checkForResize();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ // We still need to forward the resizing of the child window to the driver.
+ mGLX.waitX();
+ return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayGLX::syncXCommands() const
+{
+ if (mUsesNewXDisplay)
+ {
+ XSync(mGLX.getDisplay(), False);
+ }
+}
+
+void DisplayGLX::setSwapInterval(glx::Drawable drawable, SwapControlData *data)
+{
+ ASSERT(data != nullptr);
+
+ // TODO(cwallez) error checking?
+ if (mSwapControl == SwapControl::EXT)
+ {
+ // Prefer the EXT extension, it gives per-drawable swap intervals, which will
+ // minimize the number of driver calls.
+ if (data->maxSwapInterval < 0)
+ {
+ unsigned int maxSwapInterval = 0;
+ mGLX.queryDrawable(drawable, GLX_MAX_SWAP_INTERVAL_EXT, &maxSwapInterval);
+ data->maxSwapInterval = static_cast<int>(maxSwapInterval);
+ }
+
+ // When the egl configs were generated we had to guess what the max swap interval
+ // was because we didn't have a window to query it one (and that this max could
+ // depend on the monitor). This means that the target interval might be higher
+ // than the max interval and needs to be clamped.
+ const int realInterval = std::min(data->targetSwapInterval, data->maxSwapInterval);
+ if (data->currentSwapInterval != realInterval)
+ {
+ mGLX.swapIntervalEXT(drawable, realInterval);
+ data->currentSwapInterval = realInterval;
+ }
+ }
+ else if (mCurrentSwapInterval != data->targetSwapInterval)
+ {
+ // With the Mesa or SGI extensions we can still do per-drawable swap control
+ // manually but it is more expensive in number of driver calls.
+ if (mSwapControl == SwapControl::Mesa)
+ {
+ mGLX.swapIntervalMESA(data->targetSwapInterval);
+ }
+ else if (mSwapControl == SwapControl::SGI)
+ {
+ mGLX.swapIntervalSGI(data->targetSwapInterval);
+ }
+ mCurrentSwapInterval = data->targetSwapInterval;
+ }
+}
+
+bool DisplayGLX::isValidWindowVisualId(unsigned long visualId) const
+{
+ return mRequestedVisual == -1 || static_cast<unsigned long>(mRequestedVisual) == visualId;
+}
+
+const FunctionsGL *DisplayGLX::getFunctionsGL() const
+{
+ return mFunctionsGL;
+}
+
+void DisplayGLX::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ outExtensions->createContextRobustness = mHasARBCreateContextRobustness;
+}
+
+void DisplayGLX::generateCaps(egl::Caps *outCaps) const
+{
+ outCaps->textureNPOT = true;
+}
+
+int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const
+{
+ int result;
+ mGLX.getFBConfigAttrib(config, attrib, &result);
+ return result;
+}
+
+egl::Error DisplayGLX::createContextAttribs(glx::FBConfig,
+ const Optional<gl::Version> &version,
+ int profileMask,
+ glx::Context *context) const
+{
+ std::vector<int> attribs;
+
+ if (mHasARBCreateContextRobustness)
+ {
+ attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
+ attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB);
+ }
+
+ if (version.valid())
+ {
+ attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
+ attribs.push_back(version.value().major);
+
+ attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
+ attribs.push_back(version.value().minor);
+ }
+
+ if (profileMask != 0 && mHasARBCreateContextProfile)
+ {
+ attribs.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
+ attribs.push_back(profileMask);
+ }
+
+ attribs.push_back(None);
+
+ // When creating a context with glXCreateContextAttribsARB, a variety of X11 errors can
+ // be generated. To prevent these errors from crashing our process, we simply ignore
+ // them and only look if GLXContext was created.
+ // Process all events before setting the error handler to avoid desynchronizing XCB instances
+ // (the error handler is NOT per-display).
+ XSync(mXDisplay, False);
+ auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors);
+ *context = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, attribs.data());
+ XSetErrorHandler(oldErrorHandler);
+
+ if (!*context)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context.");
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayGLX::getNVIDIADriverVersion(std::string *version) const
+{
+ *version = "";
+
+ int eventBase = 0;
+ int errorBase = 0;
+ if (XNVCTRLQueryExtension(mXDisplay, &eventBase, &errorBase))
+ {
+ int screenCount = ScreenCount(mXDisplay);
+ for (int screen = 0; screen < screenCount; ++screen)
+ {
+ char *buffer = nullptr;
+ if (XNVCTRLIsNvScreen(mXDisplay, screen) &&
+ XNVCTRLQueryStringAttribute(mXDisplay, screen, 0,
+ NV_CTRL_STRING_NVIDIA_DRIVER_VERSION, &buffer))
+ {
+ *version = buffer;
+ XFree(buffer);
+ }
+ }
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h
new file mode 100755
index 000000000..7e870c2f3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h
@@ -0,0 +1,151 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayGLX.h: GLX implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_DISPLAYGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_DISPLAYGLX_H_
+
+#include <string>
+#include <vector>
+
+#include "common/Optional.h"
+#include "libANGLE/renderer/gl/DisplayGL.h"
+#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
+
+namespace rx
+{
+
+class FunctionsGLX;
+
+// State-tracking data for the swap control to allow DisplayGLX to remember per
+// drawable information for swap control.
+struct SwapControlData
+{
+ SwapControlData();
+
+ // Set by the drawable
+ int targetSwapInterval;
+
+ // DisplayGLX-side state-tracking
+ int maxSwapInterval;
+ int currentSwapInterval;
+};
+
+class DisplayGLX : public DisplayGL
+{
+ public:
+ DisplayGLX();
+ ~DisplayGLX() override;
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() override;
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+ egl::Error getDevice(DeviceImpl **device) override;
+
+ std::string getVendorString() const override;
+
+ egl::Error waitClient() const override;
+ egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const override;
+
+ egl::Error getDriverVersion(std::string *version) const override;
+
+ // Synchronizes with the X server, if the display has been opened by ANGLE.
+ // Calling this is required at the end of every functions that does buffered
+ // X calls (not for glX calls) otherwise there might be race conditions
+ // between the application's display and ANGLE's one.
+ void syncXCommands() const;
+
+ // Depending on the supported GLX extension, swap interval can be set
+ // globally or per drawable. This function will make sure the drawable's
+ // swap interval is the one required so that the subsequent swapBuffers
+ // acts as expected.
+ void setSwapInterval(glx::Drawable drawable, SwapControlData *data);
+
+ bool isValidWindowVisualId(unsigned long visualId) const;
+
+ private:
+ const FunctionsGL *getFunctionsGL() const override;
+
+ egl::Error initializeContext(glx::FBConfig config,
+ const egl::AttributeMap &eglAttributes,
+ glx::Context *context);
+
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+ void generateCaps(egl::Caps *outCaps) const override;
+
+ int getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const;
+ egl::Error createContextAttribs(glx::FBConfig,
+ const Optional<gl::Version> &version,
+ int profileMask,
+ glx::Context *context) const;
+
+ egl::Error getNVIDIADriverVersion(std::string *version) const;
+
+ FunctionsGL *mFunctionsGL;
+
+ std::map<int, glx::FBConfig> configIdToGLXConfig;
+
+ EGLint mRequestedVisual;
+ glx::FBConfig mContextConfig;
+ glx::Context mContext;
+ // A pbuffer the context is current on during ANGLE initialization
+ glx::Pbuffer mDummyPbuffer;
+
+ bool mUsesNewXDisplay;
+ bool mIsMesa;
+ bool mHasMultisample;
+ bool mHasARBCreateContext;
+ bool mHasARBCreateContextProfile;
+ bool mHasARBCreateContextRobustness;
+ bool mHasEXTCreateContextES2Profile;
+
+ enum class SwapControl
+ {
+ Absent,
+ EXT,
+ Mesa,
+ SGI,
+ };
+ SwapControl mSwapControl;
+ int mMinSwapInterval;
+ int mMaxSwapInterval;
+ int mCurrentSwapInterval;
+
+ FunctionsGLX mGLX;
+ Display *mXDisplay;
+ egl::Display *mEGLDisplay;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_DISPLAYGLX_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md b/gfx/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md
new file mode 100755
index 000000000..2343ad086
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md
@@ -0,0 +1,204 @@
+GLX Framebuffer Compatibility investigation
+===========================================
+
+In GLX and EGL, contexts are created with respect to a config that
+describes the type of surfaces they will be used to render to.
+Likewise surfaces are created with respect to a config and for
+a context to be able to render to a surface, both their configs
+must be compatible. Compatibility is losely described in both
+the GLX and EGL specs but the following is clear:
+ * In GLX the config's color buffer must have the same type, including
+RGBA vs. ColorIndex and the buffers must have the same depth, if they
+exist.
+ * In EGL the config's color buffer must have the same type and the
+buffers must have the same depth (not clear if it is only if they exist)
+
+Obviously the EGLconfig we will expose will have a one-to-one
+correspondance with GLXFBConfigs.
+
+Our EGL implementation uses a single OpenGL context to back all
+the EGLcontexts created by the application. Since our GL context
+and GLXContext are the same object but in two APIs, we will make
+the confusion and call the GLX context our backing context.
+
+The problem we have is that the the GLX context is created before
+the application can choose what type of context it wants to use,
+that means we have to expose EGLconfigs whose respective GLXFBConfigs
+are compatible with the GLXFBConfig of our GLX context; we also need
+to choose the GLXFBConfig of our GLX context so that it matches the
+most common needs of application.
+
+Choice of the GLX context GLXFBConfig
+-------------------------------------
+
+We decided that our GLX context's configuration must satisfy the following:
+ * Have a RGBA8 color buffer and D24S8 depth-stencil buffer which is what
+the vast majority of applications use.
+ * It must render in direct colors, i.e. not in a color indexed format.
+ * It must be double-buffered (see later)
+ * It must support rendering to all the types of GLX surfaces so that we can
+use it for all types of EGL surfaces
+ * It must have an associated visual ID so that we can use it with X, it seems
+like this would be strongly tied to it having the ```WINDOW_BIT``` set.
+ * We would like a conformant context.
+
+Study of compatible GLXFBConfigs
+--------------------------------
+
+When using the condition of compatibility defined in the GLX spec and filtering
+out the non-conformant GLXFBConfig we got the following list (see function
+```print_visual_attribs_short``` in [glxinfo's source code](http://cgit.freedesktop.org/mesa/demos/tree/src/xdemos/glxinfo.c)
+to understand how to read the table):
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat Result
+----------------------------------------------------------------------------
+0x02e 24 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail
+0x0e4 32 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None BadMatch
+0x02c 24 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass
+0x0e2 32 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None BadMatch
+0x089 24 dc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail
+0x087 24 dc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass
+0x026 24 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail
+0x0dc 32 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None BadMatch
+0x024 24 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass
+0x0da 32 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None BadMatch
+0x081 24 dc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail
+0x07f 24 dc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass
+```
+
+The last column shows the result of trying to render on a window using the config,
+with a GLX context using config 0x024. The first thing we see is that BadMatch is
+thrown by the X server when creating the subwindow for rendering. This was because
+we didn't set the border pixel of the subwindow *shake fist at X11* (see this [StackOverflow question](http://stackoverflow.com/questions/3645632/how-to-create-a-window-with-a-bit-depth-of-32)).
+The result updated with this fix give:
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x02e 24 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail
+0x0e4 32 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail
+0x02c 24 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass
+0x0e2 32 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass
+0x089 24 dc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail
+0x087 24 dc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass
+0x026 24 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail
+0x0dc 32 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail
+0x024 24 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass
+0x0da 32 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass
+0x081 24 dc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail
+0x07f 24 dc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass
+```
+
+From this we see that our rendering test passed if and only if the config was double
+buffered like 0x024 which is our GLX context config. The compatible configs are then:
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x02c 24 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None
+0x0e2 32 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None
+0x087 24 dc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None
+0x024 24 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None
+0x0da 32 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None
+0x07f 24 dc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None
+```
+
+We can see two dimensions, with our without a depth-stencil buffer and with TrueColor
+or DirectColor. The depth-stencil will be useful to expose to application.
+
+More on double buffering
+------------------------
+The tests above show that double-buffered contexts are not compatible with single-
+buffered surfaces; however other tests show that single-buffered contexts are
+compatible with both single and double-buffered surfaces. The problem is that in
+that case, we can see some flickering even with double-buffered surfaces. If we
+can find a trick to avoid that flicker, then we would be able to expose single
+and double-buffered surfaces at the EGL level. Not exposing them isn't too much
+of a problem though as the vast majority of application want double-buffering.
+
+AMD and extra buffers
+---------------------
+As can be seen above, NVIDIA does not expose conformant context with multisampled
+buffers or non RGBA16 accumulation buffers. The behavior is different on AMD that
+exposes them as conformant, which gives the following list after filtering as
+explained above:
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x023 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 16 16 16 16 0 0 None
+0x027 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x02b 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 2 1 None
+0x02f 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 4 1 None
+0x03b 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 16 16 16 16 0 0 None
+0x03f 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x043 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 2 1 None
+0x047 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 4 1 None
+```
+
+ANGLE's context is created using 0x027 and experimentation shows it is only compatible
+with 0x03f which is the only other config lacking both an accumulation buffer and a
+multisample buffer. The GLX spec seems to hint it should still work ("should have the
+same size, if they exist") but it doesn't work in this case. Filtering the configs to
+have the same multisample and accumulation buffers gives the following:
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x027 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x03f 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+```
+
+Mesa Intel driver
+-----------------
+In GLX, a criterium for context and surface compatibility is that buffers
+should have the same depth, if they exist at all in the surface. This means
+that it should be possible to make a context with a D24S8 depth-stencil
+buffer to a surface without a depth-stencil buffer. This doesn't work on the
+Mesa Intel driver. The list before the workaround was the following, with
+0x020 being the fbconfig chosen for the context:
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x020 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x021 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x08f 32 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x0d0 24 tc 0 32 0 r y . 8 8 8 8 . . 0 0 0 0 0 0 0 0 0 None
+0x0e2 24 dc 0 32 0 r y . 8 8 8 8 . . 0 0 0 0 0 0 0 0 0 None
+0x0e9 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+```
+
+After the workaround that list becomes the following:
+
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x020 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x021 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x08f 32 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x0e9 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+```
+
+Future investigation
+--------------------
+All the non-conformant configs have a multisampled buffer, so it could be interesting
+to see if we can use them to expose another EGL extension.
+
+Finally this document is written with respect to a small number of drivers, before
+using the GLX EGL implementation in the wild it would be good to test it on other
+drivers and hardware.
+
+The drivers tested were:
+
+ - the proprietary NVIDIA driver
+ - the proprietary AMD driver
+ - the open source Intel (Broadwell) Mesa driver
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp b/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
new file mode 100755
index 000000000..4ec38dd81
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
@@ -0,0 +1,398 @@
+//
+// Copyright (c) 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.
+//
+
+// FunctionsGLX.cpp: Implements the FunctionsGLX class.
+
+#define ANGLE_SKIP_GLX_DEFINES 1
+#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
+#undef ANGLE_SKIP_GLX_DEFINES
+
+// We can only include glx.h in files which do not include ANGLE's GLES
+// headers, to avoid doubly-defined GLenum macros, typedefs, etc.
+#include <GL/glx.h>
+
+#include <dlfcn.h>
+#include <algorithm>
+
+#include "common/string_utils.h"
+#include "libANGLE/renderer/gl/glx/functionsglx_typedefs.h"
+
+namespace rx
+{
+
+void* FunctionsGLX::sLibHandle = nullptr;
+
+template<typename T>
+static bool GetProc(PFNGETPROCPROC getProc, T *member, const char *name)
+{
+ *member = reinterpret_cast<T>(getProc(name));
+ return *member != nullptr;
+}
+
+struct FunctionsGLX::GLXFunctionTable
+{
+ GLXFunctionTable()
+ : createContextPtr(nullptr),
+ destroyContextPtr(nullptr),
+ makeCurrentPtr(nullptr),
+ swapBuffersPtr(nullptr),
+ queryExtensionPtr(nullptr),
+ queryVersionPtr(nullptr),
+ getCurrentContextPtr(nullptr),
+ getCurrentDrawablePtr(nullptr),
+ waitXPtr(nullptr),
+ waitGLPtr(nullptr),
+ getClientStringPtr(nullptr),
+ queryExtensionsStringPtr(nullptr),
+ getFBConfigsPtr(nullptr),
+ chooseFBConfigPtr(nullptr),
+ getFBConfigAttribPtr(nullptr),
+ getVisualFromFBConfigPtr(nullptr),
+ createWindowPtr(nullptr),
+ destroyWindowPtr(nullptr),
+ createPbufferPtr(nullptr),
+ destroyPbufferPtr(nullptr),
+ queryDrawablePtr(nullptr),
+ createContextAttribsARBPtr(nullptr),
+ swapIntervalEXTPtr(nullptr),
+ swapIntervalMESAPtr(nullptr),
+ swapIntervalSGIPtr(nullptr)
+ {
+ }
+
+ // GLX 1.0
+ PFNGLXCREATECONTEXTPROC createContextPtr;
+ PFNGLXDESTROYCONTEXTPROC destroyContextPtr;
+ PFNGLXMAKECURRENTPROC makeCurrentPtr;
+ PFNGLXSWAPBUFFERSPROC swapBuffersPtr;
+ PFNGLXQUERYEXTENSIONPROC queryExtensionPtr;
+ PFNGLXQUERYVERSIONPROC queryVersionPtr;
+ PFNGLXGETCURRENTCONTEXTPROC getCurrentContextPtr;
+ PFNGLXGETCURRENTDRAWABLEPROC getCurrentDrawablePtr;
+ PFNGLXWAITXPROC waitXPtr;
+ PFNGLXWAITGLPROC waitGLPtr;
+
+ // GLX 1.1
+ PFNGLXGETCLIENTSTRINGPROC getClientStringPtr;
+ PFNGLXQUERYEXTENSIONSSTRINGPROC queryExtensionsStringPtr;
+
+ //GLX 1.3
+ PFNGLXGETFBCONFIGSPROC getFBConfigsPtr;
+ PFNGLXCHOOSEFBCONFIGPROC chooseFBConfigPtr;
+ PFNGLXGETFBCONFIGATTRIBPROC getFBConfigAttribPtr;
+ PFNGLXGETVISUALFROMFBCONFIGPROC getVisualFromFBConfigPtr;
+ PFNGLXCREATEWINDOWPROC createWindowPtr;
+ PFNGLXDESTROYWINDOWPROC destroyWindowPtr;
+ PFNGLXCREATEPBUFFERPROC createPbufferPtr;
+ PFNGLXDESTROYPBUFFERPROC destroyPbufferPtr;
+ PFNGLXQUERYDRAWABLEPROC queryDrawablePtr;
+
+ // GLX_ARB_create_context
+ PFNGLXCREATECONTEXTATTRIBSARBPROC createContextAttribsARBPtr;
+
+ // GLX_EXT_swap_control
+ PFNGLXSWAPINTERVALEXTPROC swapIntervalEXTPtr;
+
+ // GLX_MESA_swap_control
+ PFNGLXSWAPINTERVALMESAPROC swapIntervalMESAPtr;
+
+ // GLX_SGI_swap_control
+ PFNGLXSWAPINTERVALSGIPROC swapIntervalSGIPtr;
+};
+
+FunctionsGLX::FunctionsGLX()
+ : majorVersion(0),
+ minorVersion(0),
+ mXDisplay(nullptr),
+ mXScreen(-1),
+ mFnPtrs(new GLXFunctionTable())
+{
+}
+
+FunctionsGLX::~FunctionsGLX()
+{
+ delete mFnPtrs;
+ terminate();
+}
+
+bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorString)
+{
+ terminate();
+ mXDisplay = xDisplay;
+ mXScreen = screen;
+
+#if !defined(ANGLE_LINK_GLX)
+ // Some OpenGL implementations can't handle having this library
+ // handle closed while there's any X window still open against
+ // which a GLXWindow was ever created.
+ if (!sLibHandle)
+ {
+ sLibHandle = dlopen("libGL.so.1", RTLD_NOW);
+ if (!sLibHandle)
+ {
+ *errorString = std::string("Could not dlopen libGL.so.1: ") + dlerror();
+ return false;
+ }
+ }
+
+ getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddress"));
+ if (!getProc)
+ {
+ getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddressARB"));
+ }
+ if (!getProc)
+ {
+ *errorString = "Could not retrieve glXGetProcAddress";
+ return false;
+ }
+#else
+ getProc = reinterpret_cast<PFNGETPROCPROC>(glXGetProcAddress);
+#endif
+
+#define GET_PROC_OR_ERROR(MEMBER, NAME) \
+ if (!GetProc(getProc, MEMBER, #NAME)) \
+ { \
+ *errorString = "Could not load GLX entry point " #NAME; \
+ return false; \
+ }
+#if !defined(ANGLE_LINK_GLX)
+#define GET_FNPTR_OR_ERROR(MEMBER, NAME) GET_PROC_OR_ERROR(MEMBER, NAME)
+#else
+#define GET_FNPTR_OR_ERROR(MEMBER, NAME) *MEMBER = NAME;
+#endif
+
+ // GLX 1.0
+ GET_FNPTR_OR_ERROR(&mFnPtrs->createContextPtr, glXCreateContext);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->destroyContextPtr, glXDestroyContext);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->makeCurrentPtr, glXMakeCurrent);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->swapBuffersPtr, glXSwapBuffers);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionPtr, glXQueryExtension);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->queryVersionPtr, glXQueryVersion);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentContextPtr, glXGetCurrentContext);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentDrawablePtr, glXGetCurrentDrawable);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->waitXPtr, glXWaitX);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->waitGLPtr, glXWaitGL);
+
+ // GLX 1.1
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getClientStringPtr, glXGetClientString);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionsStringPtr, glXQueryExtensionsString);
+
+ // Check we have a working GLX
+ {
+ int errorBase;
+ int eventBase;
+ if (!queryExtension(&errorBase, &eventBase))
+ {
+ *errorString = "GLX is not present.";
+ return false;
+ }
+ }
+
+ // Check we have a supported version of GLX
+ if (!queryVersion(&majorVersion, &minorVersion))
+ {
+ *errorString = "Could not query the GLX version.";
+ return false;
+ }
+ if (majorVersion != 1 || minorVersion < 3)
+ {
+ *errorString = "Unsupported GLX version (requires at least 1.3).";
+ return false;
+ }
+
+ const char *extensions = queryExtensionsString();
+ if (!extensions)
+ {
+ *errorString = "glXQueryExtensionsString returned NULL";
+ return false;
+ }
+ angle::SplitStringAlongWhitespace(extensions, &mExtensions);
+
+ // GLX 1.3
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigsPtr, glXGetFBConfigs);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->chooseFBConfigPtr, glXChooseFBConfig);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigAttribPtr, glXGetFBConfigAttrib);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getVisualFromFBConfigPtr, glXGetVisualFromFBConfig);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->createWindowPtr, glXCreateWindow);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->destroyWindowPtr, glXDestroyWindow);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->createPbufferPtr, glXCreatePbuffer);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->destroyPbufferPtr, glXDestroyPbuffer);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->queryDrawablePtr, glXQueryDrawable);
+
+ // Extensions
+ if (hasExtension("GLX_ARB_create_context"))
+ {
+ GET_PROC_OR_ERROR(&mFnPtrs->createContextAttribsARBPtr, glXCreateContextAttribsARB);
+ }
+ if (hasExtension("GLX_EXT_swap_control"))
+ {
+ GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalEXTPtr, glXSwapIntervalEXT);
+ }
+ if (hasExtension("GLX_MESA_swap_control"))
+ {
+ GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalMESAPtr, glXSwapIntervalMESA);
+ }
+ if (hasExtension("GLX_SGI_swap_control"))
+ {
+ GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalSGIPtr, glXSwapIntervalSGI);
+ }
+
+#undef GET_FNPTR_OR_ERROR
+#undef GET_PROC_OR_ERROR
+
+ *errorString = "";
+ return true;
+}
+
+void FunctionsGLX::terminate()
+{
+}
+
+bool FunctionsGLX::hasExtension(const char *extension) const
+{
+ return std::find(mExtensions.begin(), mExtensions.end(), extension) != mExtensions.end();
+}
+
+Display *FunctionsGLX::getDisplay() const
+{
+ return mXDisplay;
+}
+
+int FunctionsGLX::getScreen() const
+{
+ return mXScreen;
+}
+
+// GLX functions
+
+// GLX 1.0
+glx::Context FunctionsGLX::createContext(XVisualInfo *visual, glx::Context share, bool direct) const
+{
+ GLXContext shareCtx = reinterpret_cast<GLXContext>(share);
+ GLXContext context = mFnPtrs->createContextPtr(mXDisplay, visual, shareCtx, direct);
+ return reinterpret_cast<glx::Context>(context);
+}
+void FunctionsGLX::destroyContext(glx::Context context) const
+{
+ GLXContext ctx = reinterpret_cast<GLXContext>(context);
+ mFnPtrs->destroyContextPtr(mXDisplay, ctx);
+}
+Bool FunctionsGLX::makeCurrent(glx::Drawable drawable, glx::Context context) const
+{
+ GLXContext ctx = reinterpret_cast<GLXContext>(context);
+ return mFnPtrs->makeCurrentPtr(mXDisplay, drawable, ctx);
+}
+void FunctionsGLX::swapBuffers(glx::Drawable drawable) const
+{
+ mFnPtrs->swapBuffersPtr(mXDisplay, drawable);
+}
+Bool FunctionsGLX::queryExtension(int *errorBase, int *event) const
+{
+ return mFnPtrs->queryExtensionPtr(mXDisplay, errorBase, event);
+}
+Bool FunctionsGLX::queryVersion(int *major, int *minor) const
+{
+ return mFnPtrs->queryVersionPtr(mXDisplay, major, minor);
+}
+glx::Context FunctionsGLX::getCurrentContext() const
+{
+ GLXContext context = mFnPtrs->getCurrentContextPtr();
+ return reinterpret_cast<glx::Context>(context);
+}
+glx::Drawable FunctionsGLX::getCurrentDrawable() const
+{
+ GLXDrawable drawable = mFnPtrs->getCurrentDrawablePtr();
+ return reinterpret_cast<glx::Drawable>(drawable);
+}
+void FunctionsGLX::waitX() const
+{
+ mFnPtrs->waitXPtr();
+}
+void FunctionsGLX::waitGL() const
+{
+ mFnPtrs->waitGLPtr();
+}
+
+// GLX 1.1
+const char *FunctionsGLX::getClientString(int name) const
+{
+ return mFnPtrs->getClientStringPtr(mXDisplay, name);
+}
+
+const char *FunctionsGLX::queryExtensionsString() const
+{
+ return mFnPtrs->queryExtensionsStringPtr(mXDisplay, mXScreen);
+}
+
+// GLX 1.4
+glx::FBConfig *FunctionsGLX::getFBConfigs(int *nElements) const
+{
+ GLXFBConfig *configs = mFnPtrs->getFBConfigsPtr(mXDisplay, mXScreen, nElements);
+ return reinterpret_cast<glx::FBConfig*>(configs);
+}
+glx::FBConfig *FunctionsGLX::chooseFBConfig(const int *attribList, int *nElements) const
+{
+ GLXFBConfig *configs = mFnPtrs->chooseFBConfigPtr(mXDisplay, mXScreen, attribList, nElements);
+ return reinterpret_cast<glx::FBConfig*>(configs);
+}
+int FunctionsGLX::getFBConfigAttrib(glx::FBConfig config, int attribute, int *value) const
+{
+ GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+ return mFnPtrs->getFBConfigAttribPtr(mXDisplay, cfg, attribute, value);
+}
+XVisualInfo *FunctionsGLX::getVisualFromFBConfig(glx::FBConfig config) const
+{
+ GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+ return mFnPtrs->getVisualFromFBConfigPtr(mXDisplay, cfg);
+}
+GLXWindow FunctionsGLX::createWindow(glx::FBConfig config, Window window, const int *attribList) const
+{
+ GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+ return mFnPtrs->createWindowPtr(mXDisplay, cfg, window, attribList);
+}
+void FunctionsGLX::destroyWindow(glx::Window window) const
+{
+ mFnPtrs->destroyWindowPtr(mXDisplay, window);
+}
+glx::Pbuffer FunctionsGLX::createPbuffer(glx::FBConfig config, const int *attribList) const
+{
+ GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+ return mFnPtrs->createPbufferPtr(mXDisplay, cfg, attribList);
+}
+void FunctionsGLX::destroyPbuffer(glx::Pbuffer pbuffer) const
+{
+ mFnPtrs->destroyPbufferPtr(mXDisplay, pbuffer);
+}
+void FunctionsGLX::queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const
+{
+ mFnPtrs->queryDrawablePtr(mXDisplay, drawable, attribute, value);
+}
+
+// GLX_ARB_create_context
+glx::Context FunctionsGLX::createContextAttribsARB(glx::FBConfig config, glx::Context shareContext, Bool direct, const int *attribList) const
+{
+ GLXContext shareCtx = reinterpret_cast<GLXContext>(shareContext);
+ GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
+ GLXContext ctx = mFnPtrs->createContextAttribsARBPtr(mXDisplay, cfg, shareCtx, direct, attribList);
+ return reinterpret_cast<glx::Context>(ctx);
+}
+
+void FunctionsGLX::swapIntervalEXT(glx::Drawable drawable, int intervals) const
+{
+ mFnPtrs->swapIntervalEXTPtr(mXDisplay, drawable, intervals);
+}
+
+int FunctionsGLX::swapIntervalMESA(int intervals) const
+{
+ return mFnPtrs->swapIntervalMESAPtr(intervals);
+}
+
+int FunctionsGLX::swapIntervalSGI(int intervals) const
+{
+ return mFnPtrs->swapIntervalSGIPtr(intervals);
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h
new file mode 100755
index 000000000..98c2fef46
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 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.
+//
+
+// FunctionsGLX.h: Defines the FunctionsGLX class to load functions and data from GLX
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_
+
+#include <string>
+#include <vector>
+
+#include "libANGLE/renderer/gl/glx/platform_glx.h"
+
+namespace rx
+{
+
+class FunctionsGLX
+{
+ public:
+ FunctionsGLX();
+ ~FunctionsGLX();
+
+ // Load data from GLX, can be called multiple times
+ bool initialize(Display *xDisplay, int screen, std::string *errorString);
+ void terminate();
+
+ bool hasExtension(const char *extension) const;
+ int majorVersion;
+ int minorVersion;
+
+ Display *getDisplay() const;
+ int getScreen() const;
+
+ PFNGETPROCPROC getProc;
+
+ // GLX 1.0
+ glx::Context createContext(XVisualInfo *visual, glx::Context share, bool direct) const;
+ void destroyContext(glx::Context context) const;
+ Bool makeCurrent(glx::Drawable drawable, glx::Context context) const;
+ void swapBuffers(glx::Drawable drawable) const;
+ Bool queryExtension(int *errorBase, int *event) const;
+ Bool queryVersion(int *major, int *minor) const;
+ glx::Context getCurrentContext() const;
+ glx::Drawable getCurrentDrawable() const;
+ void waitX() const;
+ void waitGL() const;
+
+ // GLX 1.1
+ const char *getClientString(int name) const;
+ const char *queryExtensionsString() const;
+
+ // GLX 1.3
+ glx::FBConfig *getFBConfigs(int *nElements) const;
+ glx::FBConfig *chooseFBConfig(const int *attribList, int *nElements) const;
+ int getFBConfigAttrib(glx::FBConfig config, int attribute, int *value) const;
+ XVisualInfo *getVisualFromFBConfig(glx::FBConfig config) const;
+ glx::Window createWindow(glx::FBConfig config, Window window, const int *attribList) const;
+ void destroyWindow(glx::Window window) const;
+ glx::Pbuffer createPbuffer(glx::FBConfig config, const int *attribList) const;
+ void destroyPbuffer(glx::Pbuffer pbuffer) const;
+ void queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const;
+
+ // GLX_ARB_create_context
+ glx::Context createContextAttribsARB(glx::FBConfig config, glx::Context shareContext, Bool direct, const int *attribList) const;
+
+ // GLX_EXT_swap_control
+ void swapIntervalEXT(glx::Drawable drawable, int interval) const;
+
+ // GLX_MESA_swap_control
+ int swapIntervalMESA(int interval) const;
+
+ // GLX_SGI_swap_control
+ int swapIntervalSGI(int interval) const;
+
+ private:
+ // So as to isolate GLX from angle we do not include angleutils.h and cannot
+ // use angle::NonCopyable so we replicated it here instead.
+ FunctionsGLX(const FunctionsGLX&) = delete;
+ void operator=(const FunctionsGLX&) = delete;
+
+ struct GLXFunctionTable;
+
+ static void *sLibHandle;
+ Display *mXDisplay;
+ int mXScreen;
+
+ GLXFunctionTable *mFnPtrs;
+ std::vector<std::string> mExtensions;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp b/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp
new file mode 100755
index 000000000..a97021b40
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 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.
+//
+
+// PbufferSurfaceGLX.cpp: GLX implementation of egl::Surface for PBuffers
+
+#include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
+
+namespace rx
+{
+
+PbufferSurfaceGLX::PbufferSurfaceGLX(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLint width,
+ EGLint height,
+ bool largest,
+ const FunctionsGLX &glx,
+ glx::Context context,
+ glx::FBConfig fbConfig)
+ : SurfaceGLX(state, renderer),
+ mWidth(width),
+ mHeight(height),
+ mLargest(largest),
+ mGLX(glx),
+ mContext(context),
+ mFBConfig(fbConfig),
+ mPbuffer(0)
+{
+}
+
+PbufferSurfaceGLX::~PbufferSurfaceGLX()
+{
+ if (mPbuffer)
+ {
+ mGLX.destroyPbuffer(mPbuffer);
+ }
+}
+
+egl::Error PbufferSurfaceGLX::initialize()
+{
+ // Avoid creating 0-sized PBuffers as it fails on the Intel Mesa driver
+ // as commented on https://bugs.freedesktop.org/show_bug.cgi?id=38869 so we
+ // use (w, 1) or (1, h) instead.
+ int width = std::max(1, static_cast<int>(mWidth));
+ int height = std::max(1, static_cast<int>(mHeight));
+
+ const int attribs[] =
+ {
+ GLX_PBUFFER_WIDTH, width,
+ GLX_PBUFFER_HEIGHT, height,
+ GLX_LARGEST_PBUFFER, mLargest,
+ None
+ };
+
+ mPbuffer = mGLX.createPbuffer(mFBConfig, attribs);
+ if (!mPbuffer)
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to create a native GLX pbuffer.");
+ }
+
+ if (mLargest)
+ {
+ mGLX.queryDrawable(mPbuffer, GLX_WIDTH, &mWidth);
+ mGLX.queryDrawable(mPbuffer, GLX_HEIGHT, &mHeight);
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::makeCurrent()
+{
+ if (mGLX.makeCurrent(mPbuffer, mContext) != True)
+ {
+ return egl::Error(EGL_BAD_DISPLAY);
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::swap()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceGLX::releaseTexImage(EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+void PbufferSurfaceGLX::setSwapInterval(EGLint interval)
+{
+}
+
+EGLint PbufferSurfaceGLX::getWidth() const
+{
+ return mWidth;
+}
+
+EGLint PbufferSurfaceGLX::getHeight() const
+{
+ return mHeight;
+}
+
+EGLint PbufferSurfaceGLX::isPostSubBufferSupported() const
+{
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLint PbufferSurfaceGLX::getSwapBehavior() const
+{
+ return EGL_BUFFER_PRESERVED;
+}
+
+egl::Error PbufferSurfaceGLX::checkForResize()
+{
+ // The size of pbuffers never change
+ return egl::Error(EGL_SUCCESS);
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h
new file mode 100755
index 000000000..d346634b2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 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.
+//
+
+// PBufferSurfaceGLX.h: GLX implementation of egl::Surface for PBuffers
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_PBUFFERSURFACEGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_PBUFFERSURFACEGLX_H_
+
+#include "libANGLE/renderer/gl/glx/platform_glx.h"
+#include "libANGLE/renderer/gl/glx/SurfaceGLX.h"
+
+namespace rx
+{
+
+class FunctionsGLX;
+
+class PbufferSurfaceGLX : public SurfaceGLX
+{
+ public:
+ PbufferSurfaceGLX(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLint width,
+ EGLint height,
+ bool largest,
+ const FunctionsGLX &glx,
+ glx::Context context,
+ glx::FBConfig fbConfig);
+ ~PbufferSurfaceGLX() override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ egl::Error checkForResize() override;
+
+ private:
+ unsigned mWidth;
+ unsigned mHeight;
+ bool mLargest;
+
+ const FunctionsGLX &mGLX;
+ glx::Context mContext;
+ glx::FBConfig mFBConfig;
+ glx::Pbuffer mPbuffer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_PBUFFERSURFACEGLX_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h
new file mode 100755
index 000000000..813516e80
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 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.
+//
+
+// SurfaceGLX.h: common interface for GLX surfaces
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_SURFACEGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_SURFACEGLX_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+namespace rx
+{
+
+class SurfaceGLX : public SurfaceGL
+{
+ public:
+ SurfaceGLX(const egl::SurfaceState &state, RendererGL *renderer) : SurfaceGL(state, renderer) {}
+
+ virtual egl::Error checkForResize() = 0;
+};
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_SURFACEGLX_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp b/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp
new file mode 100755
index 000000000..21b1b316f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp
@@ -0,0 +1,244 @@
+//
+// Copyright (c) 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.
+//
+
+// WindowSurfaceGLX.cpp: GLX implementation of egl::Surface for windows
+
+#include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h"
+
+#include "common/debug.h"
+
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
+
+namespace rx
+{
+
+static int IgnoreX11Errors(Display *, XErrorEvent *)
+{
+ return 0;
+}
+
+WindowSurfaceGLX::WindowSurfaceGLX(const egl::SurfaceState &state,
+ const FunctionsGLX &glx,
+ DisplayGLX *glxDisplay,
+ RendererGL *renderer,
+ Window window,
+ Display *display,
+ glx::Context context,
+ glx::FBConfig fbConfig)
+ : SurfaceGLX(state, renderer),
+ mParent(window),
+ mWindow(0),
+ mDisplay(display),
+ mGLX(glx),
+ mGLXDisplay(glxDisplay),
+ mContext(context),
+ mFBConfig(fbConfig),
+ mGLXWindow(0)
+{
+}
+
+WindowSurfaceGLX::~WindowSurfaceGLX()
+{
+ if (mGLXWindow)
+ {
+ mGLX.destroyWindow(mGLXWindow);
+ }
+
+ if (mWindow)
+ {
+ // When destroying the window, it may happen that the window has already been
+ // destroyed by the application (this happens in Chromium). There is no way to
+ // atomically check that a window exists and to destroy it so instead we call
+ // XDestroyWindow, ignoring any errors.
+ auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors);
+ XDestroyWindow(mDisplay, mWindow);
+ XSync(mDisplay, False);
+ XSetErrorHandler(oldErrorHandler);
+ }
+
+ mGLXDisplay->syncXCommands();
+}
+
+egl::Error WindowSurfaceGLX::initialize()
+{
+ // Check that the window's visual ID is valid, as part of the AMGLE_x11_visual
+ // extension.
+ {
+ XWindowAttributes windowAttributes;
+ XGetWindowAttributes(mDisplay, mParent, &windowAttributes);
+ unsigned long visualId = windowAttributes.visual->visualid;
+
+ if (!mGLXDisplay->isValidWindowVisualId(visualId))
+ {
+ return egl::Error(EGL_BAD_MATCH,
+ "The visual of native_window doesn't match the visual given with "
+ "ANGLE_X11_VISUAL_ID");
+ }
+ }
+
+ // The visual of the X window, GLX window and GLX context must match,
+ // however we received a user-created window that can have any visual
+ // and wouldn't work with our GLX context. To work in all cases, we
+ // create a child window with the right visual that covers all of its
+ // parent.
+ XVisualInfo *visualInfo = mGLX.getVisualFromFBConfig(mFBConfig);
+ if (!visualInfo)
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the XVisualInfo for the child window.");
+ }
+ Visual* visual = visualInfo->visual;
+
+ if (!getWindowDimensions(mParent, &mParentWidth, &mParentHeight))
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the parent window's dimensions.");
+ }
+
+ // The depth, colormap and visual must match otherwise we get a X error
+ // so we specify the colormap attribute. Also we do not want the window
+ // to be taken into account for input so we specify the event and
+ // do-not-propagate masks to 0 (the defaults). Finally we specify the
+ // border pixel attribute so that we can use a different visual depth
+ // than our parent (seems like X uses that as a condition to render
+ // the subwindow in a different buffer)
+ XSetWindowAttributes attributes;
+ unsigned long attributeMask = CWColormap | CWBorderPixel;
+
+ Colormap colormap = XCreateColormap(mDisplay, mParent, visual, AllocNone);
+ if(!colormap)
+ {
+ XFree(visualInfo);
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to create the Colormap for the child window.");
+ }
+ attributes.colormap = colormap;
+ attributes.border_pixel = 0;
+
+ //TODO(cwallez) set up our own error handler to see if the call failed
+ mWindow = XCreateWindow(mDisplay, mParent, 0, 0, mParentWidth, mParentHeight,
+ 0, visualInfo->depth, InputOutput, visual, attributeMask, &attributes);
+ mGLXWindow = mGLX.createWindow(mFBConfig, mWindow, nullptr);
+
+ XMapWindow(mDisplay, mWindow);
+ XFlush(mDisplay);
+
+ XFree(visualInfo);
+ XFreeColormap(mDisplay, colormap);
+
+ mGLXDisplay->syncXCommands();
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::makeCurrent()
+{
+ if (mGLX.makeCurrent(mGLXWindow, mContext) != True)
+ {
+ return egl::Error(EGL_BAD_DISPLAY);
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::swap()
+{
+ // We need to swap before resizing as some drivers clobber the back buffer
+ // when the window is resized.
+ mGLXDisplay->setSwapInterval(mGLXWindow, &mSwapControl);
+ mGLX.swapBuffers(mGLXWindow);
+
+ egl::Error error = checkForResize();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceGLX::releaseTexImage(EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+void WindowSurfaceGLX::setSwapInterval(EGLint interval)
+{
+ mSwapControl.targetSwapInterval = interval;
+}
+
+EGLint WindowSurfaceGLX::getWidth() const
+{
+ // The size of the window is always the same as the cached size of its parent.
+ return mParentWidth;
+}
+
+EGLint WindowSurfaceGLX::getHeight() const
+{
+ // The size of the window is always the same as the cached size of its parent.
+ return mParentHeight;
+}
+
+EGLint WindowSurfaceGLX::isPostSubBufferSupported() const
+{
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLint WindowSurfaceGLX::getSwapBehavior() const
+{
+ return EGL_BUFFER_PRESERVED;
+}
+
+egl::Error WindowSurfaceGLX::checkForResize()
+{
+ // TODO(cwallez) set up our own error handler to see if the call failed
+ unsigned int newParentWidth, newParentHeight;
+ if (!getWindowDimensions(mParent, &newParentWidth, &newParentHeight))
+ {
+ return egl::Error(EGL_BAD_CURRENT_SURFACE,
+ "Failed to retrieve the size of the parent window.");
+ }
+
+ if (mParentWidth != newParentWidth || mParentHeight != newParentHeight)
+ {
+ mParentWidth = newParentWidth;
+ mParentHeight = newParentHeight;
+
+ mGLX.waitGL();
+ XResizeWindow(mDisplay, mWindow, mParentWidth, mParentHeight);
+ mGLX.waitX();
+ XSync(mDisplay, False);
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+bool WindowSurfaceGLX::getWindowDimensions(Window window, unsigned int *width, unsigned int *height) const
+{
+ Window root;
+ int x, y;
+ unsigned int border, depth;
+ return XGetGeometry(mDisplay, window, &root, &x, &y, width, height, &border, &depth) != 0;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h b/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h
new file mode 100755
index 000000000..0cdda96e6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 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.
+//
+
+// WindowSurfaceGLX.h: GLX implementation of egl::Surface for windows
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_
+
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+#include "libANGLE/renderer/gl/glx/platform_glx.h"
+#include "libANGLE/renderer/gl/glx/SurfaceGLX.h"
+
+namespace rx
+{
+
+class DisplayGLX;
+class FunctionsGLX;
+
+class WindowSurfaceGLX : public SurfaceGLX
+{
+ public:
+ WindowSurfaceGLX(const egl::SurfaceState &state,
+ const FunctionsGLX &glx,
+ DisplayGLX *glxDisplay,
+ RendererGL *renderer,
+ Window window,
+ Display *display,
+ glx::Context context,
+ glx::FBConfig fbConfig);
+ ~WindowSurfaceGLX() override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ egl::Error checkForResize() override;
+
+ private:
+ bool getWindowDimensions(Window window, unsigned int *width, unsigned int *height) const;
+
+ Window mParent;
+ unsigned int mParentWidth, mParentHeight;
+ Window mWindow;
+ Display *mDisplay;
+
+ const FunctionsGLX &mGLX;
+ DisplayGLX *mGLXDisplay;
+
+ glx::Context mContext;
+ glx::FBConfig mFBConfig;
+ glx::Window mGLXWindow;
+
+ SwapControlData mSwapControl;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h b/gfx/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h
new file mode 100755
index 000000000..b0ba033c7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 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.
+//
+
+// functionsglx_typedefs.h: Typedefs of GLX functions.
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_
+#define LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_
+
+#include "libANGLE/renderer/gl/glx/platform_glx.h"
+
+namespace rx
+{
+
+// Only the functions of GLX 1.2 and earlier need to be typdefed; the other
+// functions are already typedefed in glx.h
+
+// GLX 1.0
+typedef XVisualInfo *(*PFNGLXCHOOSEVISUALPROC) (Display *dpy, int screen, int *attribList);
+typedef GLXContext (*PFNGLXCREATECONTEXTPROC) (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
+typedef void (*PFNGLXDESTROYCONTEXTPROC) (Display *dpy, GLXContext ctx);
+typedef Bool (*PFNGLXMAKECURRENTPROC) (Display *dpy, GLXDrawable drawable, GLXContext ctx);
+typedef void (*PFNGLXCOPYCONTEXTPROC) (Display *dpy, GLXContext src, GLXContext dst, unsigned long mask);
+typedef void (*PFNGLXSWAPBUFFERSPROC) (Display *dpy, GLXDrawable drawable);
+typedef GLXPixmap (*PFNGLXCREATEGLXPIXMAPPROC) (Display *dpy, XVisualInfo *visual, Pixmap pixmap);
+typedef void (*PFNGLXDESTROYGLXPIXMAPPROC) (Display *dpy, GLXPixmap pixmap);
+typedef Bool (*PFNGLXQUERYEXTENSIONPROC) (Display *dpy, int *errorb, int *event);
+typedef Bool (*PFNGLXQUERYVERSIONPROC) (Display *dpy, int *maj, int *min);
+typedef Bool (*PFNGLXISDIRECTPROC) (Display *dpy, GLXContext ctx);
+typedef int (*PFNGLXGETCONFIGPROC) (Display *dpy, XVisualInfo *visual, int attrib, int *value);
+typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) ();
+typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) ();
+typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) ();
+typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) ();
+typedef void (*PFNGLXWAITGLPROC) ();
+typedef void (*PFNGLXWAITXPROC) ();
+typedef void (*PFNGLXUSEXFONT) (Font font, int first, int count, int list);
+
+// GLX 1.1
+typedef const char *(*PFNGLXQUERYEXTENSIONSSTRINGPROC) (Display *dpy, int screen);
+typedef const char *(*PFNGLXQUERYSERVERSTRINGPROC) (Display *dpy, int screen, int name);
+typedef const char *(*PFNGLXGETCLIENTSTRINGPROC) (Display *dpy, int name);
+
+
+// GLX 1.2
+typedef Display *(*PFNGLXGETCURRENTDISPLAYPROC) ();
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/glx/platform_glx.h b/gfx/angle/src/libANGLE/renderer/gl/glx/platform_glx.h
new file mode 100755
index 000000000..3ffb609d5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/glx/platform_glx.h
@@ -0,0 +1,190 @@
+//
+// Copyright (c) 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_glx.h: Includes specific to GLX.
+
+#ifndef LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_
+#define LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_
+
+#if !defined(ANGLE_SKIP_GLX_DEFINES)
+// GLX 1.0
+#define GLX_USE_GL 1
+#define GLX_BUFFER_SIZE 2
+#define GLX_LEVEL 3
+#define GLX_RGBA 4
+#define GLX_DOUBLEBUFFER 5
+#define GLX_STEREO 6
+#define GLX_AUX_BUFFERS 7
+#define GLX_RED_SIZE 8
+#define GLX_GREEN_SIZE 9
+#define GLX_BLUE_SIZE 10
+#define GLX_ALPHA_SIZE 11
+#define GLX_DEPTH_SIZE 12
+#define GLX_STENCIL_SIZE 13
+#define GLX_ACCUM_RED_SIZE 14
+#define GLX_ACCUM_GREEN_SIZE 15
+#define GLX_ACCUM_BLUE_SIZE 16
+#define GLX_ACCUM_ALPHA_SIZE 17
+
+#define GLX_BAD_SCREEN 1
+#define GLX_BAD_ATTRIBUTE 2
+#define GLX_NO_EXTENSION 3
+#define GLX_BAD_VISUAL 4
+#define GLX_BAD_CONTEXT 5
+#define GLX_BAD_VALUE 6
+#define GLX_BAD_ENUM 7
+
+// GLX 1.1
+#define GLX_VENDOR 1
+#define GLX_VERSION 2
+#define GLX_EXTENSIONS 3
+
+// GLX 1.3
+#define GLX_CONFIG_CAVEAT 0x20
+#define GLX_DONT_CARE 0xFFFFFFFF
+#define GLX_X_VISUAL_TYPE 0x22
+#define GLX_TRANSPARENT_TYPE 0x23
+#define GLX_TRANSPARENT_INDEX_VALUE 0x24
+#define GLX_TRANSPARENT_RED_VALUE 0x25
+#define GLX_TRANSPARENT_GREEN_VALUE 0x26
+#define GLX_TRANSPARENT_BLUE_VALUE 0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE 0x28
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_PIXMAP_BIT 0x00000002
+#define GLX_PBUFFER_BIT 0x00000004
+#define GLX_AUX_BUFFERS_BIT 0x00000010
+#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
+#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
+#define GLX_DEPTH_BUFFER_BIT 0x00000020
+#define GLX_STENCIL_BUFFER_BIT 0x00000040
+#define GLX_ACCUM_BUFFER_BIT 0x00000080
+#define GLX_NONE 0x8000
+#define GLX_SLOW_CONFIG 0x8001
+#define GLX_TRUE_COLOR 0x8002
+#define GLX_DIRECT_COLOR 0x8003
+#define GLX_PSEUDO_COLOR 0x8004
+#define GLX_STATIC_COLOR 0x8005
+#define GLX_GRAY_SCALE 0x8006
+#define GLX_STATIC_GRAY 0x8007
+#define GLX_TRANSPARENT_RGB 0x8008
+#define GLX_TRANSPARENT_INDEX 0x8009
+#define GLX_VISUAL_ID 0x800B
+#define GLX_SCREEN 0x800C
+#define GLX_NON_CONFORMANT_CONFIG 0x800D
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_X_RENDERABLE 0x8012
+#define GLX_FBCONFIG_ID 0x8013
+#define GLX_RGBA_TYPE 0x8014
+#define GLX_COLOR_INDEX_TYPE 0x8015
+#define GLX_MAX_PBUFFER_WIDTH 0x8016
+#define GLX_MAX_PBUFFER_HEIGHT 0x8017
+#define GLX_MAX_PBUFFER_PIXELS 0x8018
+#define GLX_PRESERVED_CONTENTS 0x801B
+#define GLX_LARGEST_PBUFFER 0x801C
+#define GLX_WIDTH 0x801D
+#define GLX_HEIGHT 0x801E
+#define GLX_EVENT_MASK 0x801F
+#define GLX_DAMAGED 0x8020
+#define GLX_SAVED 0x8021
+#define GLX_WINDOW 0x8022
+#define GLX_PBUFFER 0x8023
+#define GLX_PBUFFER_HEIGHT 0x8040
+#define GLX_PBUFFER_WIDTH 0x8041
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_COLOR_INDEX_BIT 0x00000002
+#define GLX_PBUFFER_CLOBBER_MASK 0x08000000
+
+// GLX 1.4
+#define GLX_SAMPLE_BUFFERS 0x186a0
+#define GLX_SAMPLES 0x186a1
+
+// GLX_ARB_create_context
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+
+// GLX_ARB_create_context_profile
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+
+// GLX_ARB_create_context_robustness
+#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261
+
+// GLX_EXT_create_context_es2_profile
+#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+
+// GLX_EXT_texture_from_pixmap
+#define GLX_TEXTURE_1D_BIT_EXT 0x00000001
+#define GLX_TEXTURE_2D_BIT_EXT 0x00000002
+#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004
+#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0
+#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1
+#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2
+#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3
+#define GLX_Y_INVERTED_EXT 0x20D4
+#define GLX_TEXTURE_FORMAT_EXT 0x20D5
+#define GLX_TEXTURE_TARGET_EXT 0x20D6
+#define GLX_MIPMAP_TEXTURE_EXT 0x20D7
+#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8
+#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9
+#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA
+#define GLX_TEXTURE_1D_EXT 0x20DB
+#define GLX_TEXTURE_2D_EXT 0x20DC
+#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD
+#define GLX_FRONT_LEFT_EXT 0x20DE
+#define GLX_FRONT_RIGHT_EXT 0x20DF
+#define GLX_BACK_LEFT_EXT 0x20E0
+#define GLX_BACK_RIGHT_EXT 0x20E1
+#define GLX_FRONT_EXT 0x20DE
+#define GLX_BACK_EXT 0x20E0
+#define GLX_AUX0_EXT 0x20E2
+#define GLX_AUX1_EXT 0x20E3
+#define GLX_AUX2_EXT 0x20E4
+#define GLX_AUX3_EXT 0x20E5
+#define GLX_AUX4_EXT 0x20E6
+#define GLX_AUX5_EXT 0x20E7
+#define GLX_AUX6_EXT 0x20E8
+#define GLX_AUX7_EXT 0x20E9
+#define GLX_AUX8_EXT 0x20EA
+#define GLX_AUX9_EXT 0x20EB
+
+// GLX_EXT_swap_control
+#define GLX_SWAP_INTERVAL_EXT 0x20F1
+#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
+#endif // !defined(ANGLE_SKIP_GLX_DEFINES)
+
+// GLX typedefs depend on the X headers
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+#include <X11/Xutil.h>
+
+// GLX typedefs
+namespace glx
+{
+
+typedef void *Context;
+typedef void *FBConfig;
+typedef XID FBConfigID;
+typedef XID ContextID;
+typedef XID Window;
+typedef XID Pbuffer;
+typedef XID Pixmap;
+typedef XID Drawable;
+
+}
+
+typedef void* (*PFNGETPROCPROC) (const char *name);
+
+#endif // LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp b/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
new file mode 100755
index 000000000..504a787f8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
@@ -0,0 +1,1045 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// renderergl_utils.cpp: Conversion functions and other utility routines
+// specific to the OpenGL renderer.
+
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+
+#include <limits>
+
+#include "common/mathutil.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "libANGLE/renderer/gl/formatutilsgl.h"
+
+#include <algorithm>
+#include <sstream>
+
+using angle::CheckedNumeric;
+
+namespace rx
+{
+VendorID GetVendorID(const FunctionsGL *functions)
+{
+ std::string nativeVendorString(reinterpret_cast<const char *>(functions->getString(GL_VENDOR)));
+ if (nativeVendorString.find("Intel") != std::string::npos)
+ {
+ return VENDOR_ID_INTEL;
+ }
+ else if (nativeVendorString.find("NVIDIA") != std::string::npos)
+ {
+ return VENDOR_ID_NVIDIA;
+ }
+ else if (nativeVendorString.find("ATI") != std::string::npos ||
+ nativeVendorString.find("AMD") != std::string::npos)
+ {
+ return VENDOR_ID_AMD;
+ }
+ else if (nativeVendorString.find("Qualcomm") != std::string::npos)
+ {
+ return VENDOR_ID_QUALCOMM;
+ }
+ else
+ {
+ return VENDOR_ID_UNKNOWN;
+ }
+}
+
+namespace nativegl_gl
+{
+
+static bool MeetsRequirements(const FunctionsGL *functions, const nativegl::SupportRequirement &requirements)
+{
+ for (const std::string &extension : requirements.requiredExtensions)
+ {
+ if (!functions->hasExtension(extension))
+ {
+ return false;
+ }
+ }
+
+ if (functions->version >= requirements.version)
+ {
+ return true;
+ }
+ else if (!requirements.versionExtensions.empty())
+ {
+ for (const std::string &extension : requirements.versionExtensions)
+ {
+ if (!functions->hasExtension(extension))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, GLenum internalFormat)
+{
+ gl::TextureCaps textureCaps;
+
+ const nativegl::InternalFormat &formatInfo = nativegl::GetInternalFormatInfo(internalFormat, functions->standard);
+ textureCaps.texturable = MeetsRequirements(functions, formatInfo.texture);
+ textureCaps.filterable = textureCaps.texturable && MeetsRequirements(functions, formatInfo.filter);
+ textureCaps.renderable = MeetsRequirements(functions, formatInfo.framebufferAttachment);
+
+ // glGetInternalformativ is not available until version 4.2 but may be available through the 3.0
+ // extension GL_ARB_internalformat_query
+ if (textureCaps.renderable && functions->getInternalformativ)
+ {
+ GLint numSamples = 0;
+ functions->getInternalformativ(GL_RENDERBUFFER, internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &numSamples);
+
+ if (numSamples > 0)
+ {
+ std::vector<GLint> samples(numSamples);
+ functions->getInternalformativ(GL_RENDERBUFFER, internalFormat, GL_SAMPLES,
+ static_cast<GLsizei>(samples.size()), &samples[0]);
+ for (size_t sampleIndex = 0; sampleIndex < samples.size(); sampleIndex++)
+ {
+ textureCaps.sampleCounts.insert(samples[sampleIndex]);
+ }
+ }
+ }
+
+ return textureCaps;
+}
+
+static GLint QuerySingleGLInt(const FunctionsGL *functions, GLenum name)
+{
+ GLint result = 0;
+ functions->getIntegerv(name, &result);
+ return result;
+}
+
+static GLint QuerySingleIndexGLInt(const FunctionsGL *functions, GLenum name, GLuint index)
+{
+ GLint result;
+ functions->getIntegeri_v(name, index, &result);
+ return result;
+}
+
+static GLint QueryGLIntRange(const FunctionsGL *functions, GLenum name, size_t index)
+{
+ GLint result[2] = {};
+ functions->getIntegerv(name, result);
+ return result[index];
+}
+
+static GLint64 QuerySingleGLInt64(const FunctionsGL *functions, GLenum name)
+{
+ GLint64 result = 0;
+ functions->getInteger64v(name, &result);
+ return result;
+}
+
+static GLfloat QuerySingleGLFloat(const FunctionsGL *functions, GLenum name)
+{
+ GLfloat result = 0.0f;
+ functions->getFloatv(name, &result);
+ return result;
+}
+
+static GLfloat QueryGLFloatRange(const FunctionsGL *functions, GLenum name, size_t index)
+{
+ GLfloat result[2] = {};
+ functions->getFloatv(name, result);
+ return result[index];
+}
+
+static gl::TypePrecision QueryTypePrecision(const FunctionsGL *functions, GLenum shaderType, GLenum precisionType)
+{
+ gl::TypePrecision precision;
+ functions->getShaderPrecisionFormat(shaderType, precisionType, precision.range, &precision.precision);
+ return precision;
+}
+
+static GLint QueryQueryValue(const FunctionsGL *functions, GLenum target, GLenum name)
+{
+ GLint result;
+ functions->getQueryiv(target, name, &result);
+ return result;
+}
+
+static void LimitVersion(gl::Version *curVersion, const gl::Version &maxVersion)
+{
+ if (*curVersion >= maxVersion)
+ {
+ *curVersion = maxVersion;
+ }
+}
+
+void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap,
+ gl::Extensions *extensions, gl::Version *maxSupportedESVersion)
+{
+ // Texture format support checks
+ const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
+ for (GLenum internalFormat : allFormats)
+ {
+ gl::TextureCaps textureCaps = GenerateTextureFormatCaps(functions, internalFormat);
+ textureCapsMap->insert(internalFormat, textureCaps);
+
+ if (gl::GetInternalFormatInfo(internalFormat).compressed)
+ {
+ caps->compressedTextureFormats.push_back(internalFormat);
+ }
+ }
+
+ // Start by assuming ES3.1 support and work down
+ *maxSupportedESVersion = gl::Version(3, 1);
+
+ // Table 6.28, implementation dependent values
+ if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->hasGLExtension("GL_ARB_ES3_compatibility") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ caps->maxElementIndex = QuerySingleGLInt64(functions, GL_MAX_ELEMENT_INDEX);
+ }
+ else
+ {
+ // Doesn't affect ES3 support, can use a pre-defined limit
+ caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
+ }
+
+ if (functions->isAtLeastGL(gl::Version(1, 2)) ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_texture_3D"))
+ {
+ caps->max3DTextureSize = QuerySingleGLInt(functions, GL_MAX_3D_TEXTURE_SIZE);
+ }
+ else
+ {
+ // Can't support ES3 without 3D textures
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ caps->max2DTextureSize = QuerySingleGLInt(functions, GL_MAX_TEXTURE_SIZE); // GL 1.0 / ES 2.0
+ caps->maxCubeMapTextureSize = QuerySingleGLInt(functions, GL_MAX_CUBE_MAP_TEXTURE_SIZE); // GL 1.3 / ES 2.0
+
+ if (functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_texture_array") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ caps->maxArrayTextureLayers = QuerySingleGLInt(functions, GL_MAX_ARRAY_TEXTURE_LAYERS);
+ }
+ else
+ {
+ // Can't support ES3 without array textures
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(1, 5)) || functions->hasGLExtension("GL_EXT_texture_lod_bias") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ caps->maxLODBias = QuerySingleGLFloat(functions, GL_MAX_TEXTURE_LOD_BIAS);
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_framebuffer_object") ||
+ functions->isAtLeastGLES(gl::Version(2, 0)))
+ {
+ caps->maxRenderbufferSize = QuerySingleGLInt(functions, GL_MAX_RENDERBUFFER_SIZE);
+ caps->maxColorAttachments = QuerySingleGLInt(functions, GL_MAX_COLOR_ATTACHMENTS);
+ }
+ else
+ {
+ // Can't support ES2 without framebuffers and renderbuffers
+ LimitVersion(maxSupportedESVersion, gl::Version(0, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(2, 0)) || functions->hasGLExtension("ARB_draw_buffers") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_draw_buffers"))
+ {
+ caps->maxDrawBuffers = QuerySingleGLInt(functions, GL_MAX_DRAW_BUFFERS);
+ }
+ else
+ {
+ // Framebuffer is required to have at least one drawbuffer even if the extension is not
+ // supported
+ caps->maxDrawBuffers = 1;
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ caps->maxViewportWidth = QueryGLIntRange(functions, GL_MAX_VIEWPORT_DIMS, 0); // GL 1.0 / ES 2.0
+ caps->maxViewportHeight = QueryGLIntRange(functions, GL_MAX_VIEWPORT_DIMS, 1); // GL 1.0 / ES 2.0
+
+ if (functions->standard == STANDARD_GL_DESKTOP &&
+ (functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
+ {
+ // Desktop GL core profile deprecated the GL_ALIASED_POINT_SIZE_RANGE query. Use
+ // GL_POINT_SIZE_RANGE instead.
+ caps->minAliasedPointSize = QueryGLFloatRange(functions, GL_POINT_SIZE_RANGE, 0);
+ caps->maxAliasedPointSize = QueryGLFloatRange(functions, GL_POINT_SIZE_RANGE, 1);
+ }
+ else
+ {
+ caps->minAliasedPointSize = QueryGLFloatRange(functions, GL_ALIASED_POINT_SIZE_RANGE, 0);
+ caps->maxAliasedPointSize = QueryGLFloatRange(functions, GL_ALIASED_POINT_SIZE_RANGE, 1);
+ }
+
+ caps->minAliasedLineWidth = QueryGLFloatRange(functions, GL_ALIASED_LINE_WIDTH_RANGE, 0); // GL 1.2 / ES 2.0
+ caps->maxAliasedLineWidth = QueryGLFloatRange(functions, GL_ALIASED_LINE_WIDTH_RANGE, 1); // GL 1.2 / ES 2.0
+
+ // Table 6.29, implementation dependent values (cont.)
+ if (functions->isAtLeastGL(gl::Version(1, 2)) ||
+ functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ caps->maxElementsIndices = QuerySingleGLInt(functions, GL_MAX_ELEMENTS_INDICES);
+ caps->maxElementsVertices = QuerySingleGLInt(functions, GL_MAX_ELEMENTS_VERTICES);
+ }
+ else
+ {
+ // Doesn't impact supported version
+ }
+
+ if (functions->isAtLeastGL(gl::Version(4, 1)) ||
+ functions->hasGLExtension("GL_ARB_get_program_binary") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) ||
+ functions->hasGLExtension("GL_OES_get_program_binary"))
+ {
+ // Able to support the GL_PROGRAM_BINARY_ANGLE format as long as another program binary
+ // format is available.
+ GLint numBinaryFormats = QuerySingleGLInt(functions, GL_NUM_PROGRAM_BINARY_FORMATS_OES);
+ if (numBinaryFormats > 0)
+ {
+ caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
+ }
+ }
+ else
+ {
+ // Doesn't impact supported version
+ }
+
+ // glGetShaderPrecisionFormat is not available until desktop GL version 4.1 or GL_ARB_ES2_compatibility exists
+ if (functions->isAtLeastGL(gl::Version(4, 1)) || functions->hasGLExtension("GL_ARB_ES2_compatibility") ||
+ functions->isAtLeastGLES(gl::Version(2, 0)))
+ {
+ caps->vertexHighpFloat = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_HIGH_FLOAT);
+ caps->vertexMediumpFloat = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_MEDIUM_FLOAT);
+ caps->vertexLowpFloat = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_LOW_FLOAT);
+ caps->fragmentHighpFloat = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_HIGH_FLOAT);
+ caps->fragmentMediumpFloat = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT);
+ caps->fragmentLowpFloat = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_LOW_FLOAT);
+ caps->vertexHighpInt = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_HIGH_INT);
+ caps->vertexMediumpInt = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_MEDIUM_INT);
+ caps->vertexLowpInt = QueryTypePrecision(functions, GL_VERTEX_SHADER, GL_LOW_INT);
+ caps->fragmentHighpInt = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_HIGH_INT);
+ caps->fragmentMediumpInt = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_MEDIUM_INT);
+ caps->fragmentLowpInt = QueryTypePrecision(functions, GL_FRAGMENT_SHADER, GL_LOW_INT);
+ }
+ else
+ {
+ // Doesn't impact supported version, set some default values
+ caps->vertexHighpFloat.setIEEEFloat();
+ caps->vertexMediumpFloat.setIEEEFloat();
+ caps->vertexLowpFloat.setIEEEFloat();
+ caps->fragmentHighpFloat.setIEEEFloat();
+ caps->fragmentMediumpFloat.setIEEEFloat();
+ caps->fragmentLowpFloat.setIEEEFloat();
+ caps->vertexHighpInt.setTwosComplementInt(32);
+ caps->vertexMediumpInt.setTwosComplementInt(32);
+ caps->vertexLowpInt.setTwosComplementInt(32);
+ caps->fragmentHighpInt.setTwosComplementInt(32);
+ caps->fragmentMediumpInt.setTwosComplementInt(32);
+ caps->fragmentLowpInt.setTwosComplementInt(32);
+ }
+
+ if (functions->isAtLeastGL(gl::Version(3, 2)) || functions->hasGLExtension("GL_ARB_sync") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ caps->maxServerWaitTimeout = QuerySingleGLInt64(functions, GL_MAX_SERVER_WAIT_TIMEOUT);
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ // Table 6.31, implementation dependent vertex shader limits
+ if (functions->isAtLeastGL(gl::Version(2, 0)) ||
+ functions->isAtLeastGLES(gl::Version(2, 0)))
+ {
+ caps->maxVertexAttributes = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIBS);
+ caps->maxVertexUniformComponents = QuerySingleGLInt(functions, GL_MAX_VERTEX_UNIFORM_COMPONENTS);
+ caps->maxVertexTextureImageUnits = QuerySingleGLInt(functions, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
+ }
+ else
+ {
+ // Can't support ES2 version without these caps
+ LimitVersion(maxSupportedESVersion, gl::Version(0, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(4, 1)) || functions->hasGLExtension("GL_ARB_ES2_compatibility") ||
+ functions->isAtLeastGLES(gl::Version(2, 0)))
+ {
+ caps->maxVertexUniformVectors = QuerySingleGLInt(functions, GL_MAX_VERTEX_UNIFORM_VECTORS);
+ }
+ else
+ {
+ // Doesn't limit ES version, GL_MAX_VERTEX_UNIFORM_COMPONENTS / 4 is acceptable.
+ caps->maxVertexUniformVectors = caps->maxVertexUniformComponents / 4;
+ }
+
+ if (functions->isAtLeastGL(gl::Version(3, 1)) || functions->hasGLExtension("GL_ARB_uniform_buffer_object") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ caps->maxVertexUniformBlocks = QuerySingleGLInt(functions, GL_MAX_VERTEX_UNIFORM_BLOCKS);
+ }
+ else
+ {
+ // Can't support ES3 without uniform blocks
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(3, 2)) ||
+ functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ caps->maxVertexOutputComponents = QuerySingleGLInt(functions, GL_MAX_VERTEX_OUTPUT_COMPONENTS);
+ }
+ else
+ {
+ // There doesn't seem, to be a desktop extension to add this cap, maybe it could be given a safe limit
+ // instead of limiting the supported ES version.
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ // Table 6.32, implementation dependent fragment shader limits
+ if (functions->isAtLeastGL(gl::Version(2, 0)) ||
+ functions->isAtLeastGLES(gl::Version(2, 0)))
+ {
+ caps->maxFragmentUniformComponents = QuerySingleGLInt(functions, GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
+ caps->maxTextureImageUnits = QuerySingleGLInt(functions, GL_MAX_TEXTURE_IMAGE_UNITS);
+ }
+ else
+ {
+ // Can't support ES2 version without these caps
+ LimitVersion(maxSupportedESVersion, gl::Version(0, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(4, 1)) || functions->hasGLExtension("GL_ARB_ES2_compatibility") ||
+ functions->isAtLeastGLES(gl::Version(2, 0)))
+ {
+ caps->maxFragmentUniformVectors = QuerySingleGLInt(functions, GL_MAX_FRAGMENT_UNIFORM_VECTORS);
+ }
+ else
+ {
+ // Doesn't limit ES version, GL_MAX_FRAGMENT_UNIFORM_COMPONENTS / 4 is acceptable.
+ caps->maxFragmentUniformVectors = caps->maxFragmentUniformComponents / 4;
+ }
+
+ if (functions->isAtLeastGL(gl::Version(3, 1)) || functions->hasGLExtension("GL_ARB_uniform_buffer_object") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ caps->maxFragmentUniformBlocks = QuerySingleGLInt(functions, GL_MAX_FRAGMENT_UNIFORM_BLOCKS);
+ }
+ else
+ {
+ // Can't support ES3 without uniform blocks
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(3, 2)) ||
+ functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ caps->maxFragmentInputComponents = QuerySingleGLInt(functions, GL_MAX_FRAGMENT_INPUT_COMPONENTS);
+ }
+ else
+ {
+ // There doesn't seem, to be a desktop extension to add this cap, maybe it could be given a safe limit
+ // instead of limiting the supported ES version.
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(3, 0)) ||
+ functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ caps->minProgramTexelOffset = QuerySingleGLInt(functions, GL_MIN_PROGRAM_TEXEL_OFFSET);
+ caps->maxProgramTexelOffset = QuerySingleGLInt(functions, GL_MAX_PROGRAM_TEXEL_OFFSET);
+ }
+ else
+ {
+ // Can't support ES3 without texel offset, could possibly be emulated in the shader
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ // Table 6.33, implementation dependent aggregate shader limits
+ if (functions->isAtLeastGL(gl::Version(3, 1)) || functions->hasGLExtension("GL_ARB_uniform_buffer_object") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ caps->maxUniformBufferBindings = QuerySingleGLInt(functions, GL_MAX_UNIFORM_BUFFER_BINDINGS);
+ caps->maxUniformBlockSize = QuerySingleGLInt64(functions, GL_MAX_UNIFORM_BLOCK_SIZE);
+ caps->uniformBufferOffsetAlignment = QuerySingleGLInt(functions, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+ caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentInputComponents;
+ caps->maxCombinedVertexUniformComponents = QuerySingleGLInt64(functions, GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS);
+ caps->maxCombinedFragmentUniformComponents = QuerySingleGLInt64(functions, GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS);
+ }
+ else
+ {
+ // Can't support ES3 without uniform blocks
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(3, 0)) ||
+ functions->hasGLExtension("GL_ARB_ES2_compatibility") ||
+ functions->isAtLeastGLES(gl::Version(2, 0)))
+ {
+ caps->maxVaryingComponents = QuerySingleGLInt(functions, GL_MAX_VARYING_COMPONENTS);
+ }
+ else if (functions->isAtLeastGL(gl::Version(2, 0)))
+ {
+ caps->maxVaryingComponents = QuerySingleGLInt(functions, GL_MAX_VARYING_FLOATS);
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(0, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(4, 1)) || functions->hasGLExtension("GL_ARB_ES2_compatibility") ||
+ functions->isAtLeastGLES(gl::Version(2, 0)))
+ {
+ caps->maxVaryingVectors = QuerySingleGLInt(functions, GL_MAX_VARYING_VECTORS);
+ }
+ else
+ {
+ // Doesn't limit ES version, GL_MAX_VARYING_COMPONENTS / 4 is acceptable.
+ caps->maxVaryingVectors = caps->maxVaryingComponents / 4;
+ }
+
+ // Determine the max combined texture image units by adding the vertex and fragment limits. If
+ // the real cap is queried, it would contain the limits for shader types that are not available to ES.
+ caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
+
+ // Table 6.34, implementation dependent transform feedback limits
+ if (functions->isAtLeastGL(gl::Version(4, 0)) ||
+ functions->hasGLExtension("GL_ARB_transform_feedback2") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ caps->maxTransformFeedbackInterleavedComponents = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
+ caps->maxTransformFeedbackSeparateAttributes = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
+ caps->maxTransformFeedbackSeparateComponents = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS);
+ }
+ else
+ {
+ // Can't support ES3 without transform feedback
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ // Table 6.35, Framebuffer Dependent Values
+ if (functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_framebuffer_multisample") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_multisampled_render_to_texture"))
+ {
+ caps->maxSamples = QuerySingleGLInt(functions, GL_MAX_SAMPLES);
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ // Check if index constant sampler array indexing is supported
+ if (!functions->isAtLeastGL(gl::Version(4, 0)) &&
+ !functions->isAtLeastGLES(gl::Version(2, 0)) &&
+ !functions->hasExtension("GL_ARB_gpu_shader5"))
+ {
+ // This should also be required for ES2 but there are some driver support index constant
+ // sampler array indexing without meeting the requirements above. Don't limit their ES
+ // version as it would break WebGL for some users.
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ // Check if sampler objects are supported
+ if (!functions->isAtLeastGL(gl::Version(3, 3)) &&
+ !functions->hasGLExtension("GL_ARB_sampler_objects") &&
+ !functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ // Can't support ES3 without sampler objects
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ // Can't support ES3 without texture swizzling
+ if (!functions->isAtLeastGL(gl::Version(3, 3)) &&
+ !functions->hasGLExtension("GL_ARB_texture_swizzle") &&
+ !functions->hasGLExtension("GL_EXT_texture_swizzle") &&
+ !functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+
+ // Texture swizzling is required to work around the luminance texture format not being
+ // present in the core profile
+ if (functions->profile & GL_CONTEXT_CORE_PROFILE_BIT)
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(0, 0));
+ }
+ }
+
+ // Can't support ES3 without the GLSL packing builtins. We have a workaround for all
+ // desktop OpenGL versions starting from 3.3 with the bit packing extension.
+ if (!functions->isAtLeastGL(gl::Version(4, 2)) &&
+ !(functions->isAtLeastGL(gl::Version(3, 2)) &&
+ functions->hasGLExtension("GL_ARB_shader_bit_encoding")) &&
+ !functions->hasGLExtension("GL_ARB_shading_language_packing") &&
+ !functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ // ES3 needs to support explicit layout location qualifiers, while it might be possible to
+ // fake them in our side, we currently don't support that.
+ if (!functions->isAtLeastGL(gl::Version(3, 3)) &&
+ !functions->hasGLExtension("GL_ARB_explicit_attrib_location") &&
+ !functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+ functions->hasGLExtension("GL_ARB_texture_multisample"))
+ {
+ caps->maxFramebufferWidth = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_WIDTH);
+ caps->maxFramebufferHeight = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_HEIGHT);
+ caps->maxFramebufferSamples = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_SAMPLES);
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(3, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+ functions->hasGLExtension("GL_ARB_texture_multisample"))
+ {
+ caps->maxSampleMaskWords = QuerySingleGLInt(functions, GL_MAX_SAMPLE_MASK_WORDS);
+ caps->maxColorTextureSamples = QuerySingleGLInt(functions, GL_MAX_COLOR_TEXTURE_SAMPLES);
+ caps->maxDepthTextureSamples = QuerySingleGLInt(functions, GL_MAX_DEPTH_TEXTURE_SAMPLES);
+ caps->maxIntegerSamples = QuerySingleGLInt(functions, GL_MAX_INTEGER_SAMPLES);
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+ functions->hasGLExtension("GL_ARB_vertex_attrib_binding"))
+ {
+ caps->maxVertexAttribRelativeOffset =
+ QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET);
+ caps->maxVertexAttribBindings = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIB_BINDINGS);
+ caps->maxVertexAttribStride = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIB_STRIDE);
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+ functions->hasGLExtension("GL_ARB_shader_storage_buffer_object"))
+ {
+ caps->maxCombinedShaderOutputResources =
+ QuerySingleGLInt(functions, GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES);
+ caps->maxFragmentShaderStorageBlocks =
+ QuerySingleGLInt(functions, GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS);
+ caps->maxVertexShaderStorageBlocks =
+ QuerySingleGLInt(functions, GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS);
+ caps->maxShaderStorageBufferBindings =
+ QuerySingleGLInt(functions, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
+ caps->maxShaderStorageBlockSize =
+ QuerySingleGLInt64(functions, GL_MAX_SHADER_STORAGE_BLOCK_SIZE);
+ caps->maxCombinedShaderStorageBlocks =
+ QuerySingleGLInt(functions, GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS);
+ caps->shaderStorageBufferOffsetAlignment =
+ QuerySingleGLInt(functions, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT);
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+ functions->hasGLExtension("GL_ARB_compute_shader"))
+ {
+ for (GLuint index = 0u; index < 3u; ++index)
+ {
+ caps->maxComputeWorkGroupCount[index] =
+ QuerySingleIndexGLInt(functions, GL_MAX_COMPUTE_WORK_GROUP_COUNT, index);
+
+ caps->maxComputeWorkGroupSize[index] =
+ QuerySingleIndexGLInt(functions, GL_MAX_COMPUTE_WORK_GROUP_SIZE, index);
+ }
+ caps->maxComputeWorkGroupInvocations =
+ QuerySingleGLInt(functions, GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS);
+ caps->maxComputeUniformBlocks = QuerySingleGLInt(functions, GL_MAX_COMPUTE_UNIFORM_BLOCKS);
+ caps->maxComputeTextureImageUnits =
+ QuerySingleGLInt(functions, GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS);
+ caps->maxComputeSharedMemorySize =
+ QuerySingleGLInt(functions, GL_MAX_COMPUTE_SHARED_MEMORY_SIZE);
+ caps->maxComputeUniformComponents =
+ QuerySingleGLInt(functions, GL_MAX_COMPUTE_UNIFORM_COMPONENTS);
+ caps->maxComputeAtomicCounterBuffers =
+ QuerySingleGLInt(functions, GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS);
+ caps->maxComputeAtomicCounters =
+ QuerySingleGLInt(functions, GL_MAX_COMPUTE_ATOMIC_COUNTERS);
+ caps->maxComputeImageUniforms = QuerySingleGLInt(functions, GL_MAX_COMPUTE_IMAGE_UNIFORMS);
+ caps->maxCombinedComputeUniformComponents =
+ QuerySingleGLInt(functions, GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS);
+ caps->maxComputeShaderStorageBlocks =
+ QuerySingleGLInt(functions, GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS);
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+ functions->hasGLExtension("GL_ARB_explicit_uniform_location"))
+ {
+ caps->maxUniformLocations = QuerySingleGLInt(functions, GL_MAX_UNIFORM_LOCATIONS);
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(4, 0)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+ functions->hasGLExtension("GL_ARB_texture_gather"))
+ {
+ caps->minProgramTextureGatherOffset =
+ QuerySingleGLInt(functions, GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET);
+ caps->maxProgramTextureGatherOffset =
+ QuerySingleGLInt(functions, GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET);
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+ functions->hasGLExtension("GL_ARB_shader_image_load_store"))
+ {
+ caps->maxVertexImageUniforms = QuerySingleGLInt(functions, GL_MAX_VERTEX_IMAGE_UNIFORMS);
+ caps->maxFragmentImageUniforms =
+ QuerySingleGLInt(functions, GL_MAX_FRAGMENT_IMAGE_UNIFORMS);
+ caps->maxImageUnits = QuerySingleGLInt(functions, GL_MAX_IMAGE_UNITS);
+ caps->maxCombinedImageUniforms =
+ QuerySingleGLInt(functions, GL_MAX_COMBINED_IMAGE_UNIFORMS);
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+ }
+
+ if (functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
+ functions->hasGLExtension("GL_ARB_shader_atomic_counters"))
+ {
+ caps->maxVertexAtomicCounterBuffers =
+ QuerySingleGLInt(functions, GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS);
+ caps->maxVertexAtomicCounters = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATOMIC_COUNTERS);
+ caps->maxFragmentAtomicCounterBuffers =
+ QuerySingleGLInt(functions, GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS);
+ caps->maxFragmentAtomicCounters =
+ QuerySingleGLInt(functions, GL_MAX_FRAGMENT_ATOMIC_COUNTERS);
+ caps->maxAtomicCounterBufferBindings =
+ QuerySingleGLInt(functions, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);
+ caps->maxAtomicCounterBufferSize =
+ QuerySingleGLInt(functions, GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE);
+ caps->maxCombinedAtomicCounterBuffers =
+ QuerySingleGLInt(functions, GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS);
+ caps->maxCombinedAtomicCounters =
+ QuerySingleGLInt(functions, GL_MAX_COMBINED_ATOMIC_COUNTERS);
+ }
+ else
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
+ }
+
+ // TODO(geofflang): The gl-uniform-arrays WebGL conformance test struggles to complete on time
+ // if the max uniform vectors is too large. Artificially limit the maximum until the test is
+ // updated.
+ caps->maxVertexUniformVectors = std::min(1024u, caps->maxVertexUniformVectors);
+ caps->maxVertexUniformComponents =
+ std::min(caps->maxVertexUniformVectors * 4, caps->maxVertexUniformComponents);
+ caps->maxFragmentUniformVectors = std::min(1024u, caps->maxFragmentUniformVectors);
+ caps->maxFragmentUniformComponents =
+ std::min(caps->maxFragmentUniformVectors * 4, caps->maxFragmentUniformComponents);
+
+ // If it is not possible to support reading buffer data back, a shadow copy of the buffers must
+ // be held. This disallows writing to buffers indirectly through transform feedback, thus
+ // disallowing ES3.
+ if (!CanMapBufferForRead(functions))
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ // Extension support
+ extensions->setTextureExtensionSupport(*textureCapsMap);
+ extensions->elementIndexUint = functions->standard == STANDARD_GL_DESKTOP ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_element_index_uint");
+ extensions->getProgramBinary = caps->programBinaryFormats.size() > 0;
+ extensions->readFormatBGRA = functions->isAtLeastGL(gl::Version(1, 2)) || functions->hasGLExtension("GL_EXT_bgra") ||
+ functions->hasGLESExtension("GL_EXT_read_format_bgra");
+ extensions->mapBuffer = functions->isAtLeastGL(gl::Version(1, 5)) ||
+ functions->hasGLESExtension("GL_OES_mapbuffer");
+ extensions->mapBufferRange = functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_ARB_map_buffer_range") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_map_buffer_range");
+ extensions->textureNPOT = functions->standard == STANDARD_GL_DESKTOP ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_texture_npot");
+ extensions->drawBuffers = functions->isAtLeastGL(gl::Version(2, 0)) || functions->hasGLExtension("ARB_draw_buffers") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_draw_buffers");
+ extensions->textureStorage = true;
+ extensions->textureFilterAnisotropic = functions->hasGLExtension("GL_EXT_texture_filter_anisotropic") || functions->hasGLESExtension("GL_EXT_texture_filter_anisotropic");
+ extensions->occlusionQueryBoolean =
+ functions->isAtLeastGL(gl::Version(1, 5)) ||
+ functions->hasGLExtension("GL_ARB_occlusion_query2") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) ||
+ functions->hasGLESExtension("GL_EXT_occlusion_query_boolean");
+ extensions->maxTextureAnisotropy = extensions->textureFilterAnisotropic ? QuerySingleGLFloat(functions, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 0.0f;
+ extensions->fence = functions->hasGLExtension("GL_NV_fence") || functions->hasGLESExtension("GL_NV_fence");
+ extensions->blendMinMax = functions->isAtLeastGL(gl::Version(1, 5)) || functions->hasGLExtension("GL_EXT_blend_minmax") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_blend_minmax");
+ extensions->framebufferBlit = (functions->blitFramebuffer != nullptr);
+ extensions->framebufferMultisample = caps->maxSamples > 0;
+ extensions->standardDerivatives = functions->isAtLeastGL(gl::Version(2, 0)) || functions->hasGLExtension("GL_ARB_fragment_shader") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_standard_derivatives");
+ extensions->shaderTextureLOD = functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_ARB_shader_texture_lod") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_shader_texture_lod");
+ extensions->fragDepth = functions->standard == STANDARD_GL_DESKTOP ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_frag_depth");
+ extensions->fboRenderMipmap = functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_framebuffer_object") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_fbo_render_mipmap");
+ extensions->instancedArrays = functions->isAtLeastGL(gl::Version(3, 1)) ||
+ (functions->hasGLExtension("GL_ARB_instanced_arrays") &&
+ (functions->hasGLExtension("GL_ARB_draw_instanced") ||
+ functions->hasGLExtension("GL_EXT_draw_instanced"))) ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) ||
+ functions->hasGLESExtension("GL_EXT_instanced_arrays");
+ extensions->unpackSubimage = functions->standard == STANDARD_GL_DESKTOP ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) ||
+ functions->hasGLESExtension("GL_EXT_unpack_subimage");
+ extensions->packSubimage = functions->standard == STANDARD_GL_DESKTOP ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) ||
+ functions->hasGLESExtension("GL_NV_pack_subimage");
+ extensions->debugMarker =
+ functions->isAtLeastGL(gl::Version(4, 3)) || functions->hasGLExtension("GL_KHR_debug") ||
+ functions->isAtLeastGLES(gl::Version(3, 2)) || functions->hasGLESExtension("GL_KHR_debug");
+ if (functions->isAtLeastGL(gl::Version(3, 3)) ||
+ functions->hasGLExtension("GL_ARB_timer_query") ||
+ functions->hasGLESExtension("GL_EXT_disjoint_timer_query"))
+ {
+ extensions->disjointTimerQuery = true;
+ extensions->queryCounterBitsTimeElapsed =
+ QueryQueryValue(functions, GL_TIME_ELAPSED, GL_QUERY_COUNTER_BITS);
+ extensions->queryCounterBitsTimestamp =
+ QueryQueryValue(functions, GL_TIMESTAMP, GL_QUERY_COUNTER_BITS);
+ }
+
+ // the EXT_multisample_compatibility is written against ES3.1 but can apply
+ // to earlier versions so therefore we're only checking for the extension string
+ // and not the specific GLES version.
+ extensions->multisampleCompatibility = functions->isAtLeastGL(gl::Version(1, 3)) ||
+ functions->hasGLESExtension("GL_EXT_multisample_compatibility");
+
+ extensions->framebufferMixedSamples =
+ functions->hasGLExtension("GL_NV_framebuffer_mixed_samples") ||
+ functions->hasGLESExtension("GL_NV_framebuffer_mixed_samples");
+
+ extensions->robustness = functions->isAtLeastGL(gl::Version(4, 5)) ||
+ functions->hasGLExtension("GL_KHR_robustness") ||
+ functions->hasGLExtension("GL_ARB_robustness") ||
+ functions->isAtLeastGLES(gl::Version(3, 2)) ||
+ functions->hasGLESExtension("GL_KHR_robustness") ||
+ functions->hasGLESExtension("GL_EXT_robustness");
+
+ // NV_path_rendering
+ // We also need interface query which is available in
+ // >= 4.3 core or ARB_interface_query or >= GLES 3.1
+ const bool canEnableGLPathRendering =
+ functions->hasGLExtension("GL_NV_path_rendering") &&
+ (functions->hasGLExtension("GL_ARB_program_interface_query") ||
+ functions->isAtLeastGL(gl::Version(4, 3)));
+
+ const bool canEnableESPathRendering =
+ functions->hasGLESExtension("GL_NV_path_rendering") &&
+ functions->isAtLeastGLES(gl::Version(3, 1));
+
+ extensions->pathRendering = canEnableGLPathRendering || canEnableESPathRendering;
+
+ extensions->textureSRGBDecode = functions->hasGLExtension("GL_EXT_texture_sRGB_decode") ||
+ functions->hasGLESExtension("GL_EXT_texture_sRGB_decode");
+
+#if defined(ANGLE_PLATFORM_APPLE)
+ VendorID vendor = GetVendorID(functions);
+ if ((IsAMD(vendor) || IsIntel(vendor)) && *maxSupportedESVersion >= gl::Version(3, 0))
+ {
+ // Apple Intel/AMD drivers do not correctly use the TEXTURE_SRGB_DECODE property of sampler
+ // states. Disable this extension when we would advertise any ES version that has samplers.
+ extensions->textureSRGBDecode = false;
+ }
+#endif
+
+ extensions->sRGBWriteControl = functions->isAtLeastGL(gl::Version(3, 0)) ||
+ functions->hasGLExtension("GL_EXT_framebuffer_sRGB") ||
+ functions->hasGLExtension("GL_ARB_framebuffer_sRGB") ||
+ functions->hasGLESExtension("GL_EXT_sRGB_write_control");
+
+#if defined(ANGLE_PLATFORM_ANDROID)
+ // SRGB blending does not appear to work correctly on the Nexus 5. Writing to an SRGB
+ // framebuffer with GL_FRAMEBUFFER_SRGB enabled and then reading back returns the same value.
+ // Disabling GL_FRAMEBUFFER_SRGB will then convert in the wrong direction.
+ extensions->sRGBWriteControl = false;
+#endif
+}
+
+void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)
+{
+ VendorID vendor = GetVendorID(functions);
+
+ workarounds->dontRemoveInvariantForFragmentInput =
+ functions->standard == STANDARD_GL_DESKTOP && IsAMD(vendor);
+
+ // Don't use 1-bit alpha formats on desktop GL with AMD or Intel drivers.
+ workarounds->avoid1BitAlphaTextureFormats =
+ functions->standard == STANDARD_GL_DESKTOP && (IsAMD(vendor) || IsIntel(vendor));
+
+ workarounds->rgba4IsNotSupportedForColorRendering =
+ functions->standard == STANDARD_GL_DESKTOP && IsIntel(vendor);
+
+ workarounds->emulateAbsIntFunction = IsIntel(vendor);
+
+ workarounds->addAndTrueToLoopCondition = IsIntel(vendor);
+
+ workarounds->emulateIsnanFloat = IsIntel(vendor);
+
+ workarounds->doesSRGBClearsOnLinearFramebufferAttachments =
+ functions->standard == STANDARD_GL_DESKTOP && (IsIntel(vendor) || IsAMD(vendor));
+
+#if defined(ANGLE_PLATFORM_APPLE)
+ workarounds->doWhileGLSLCausesGPUHang = true;
+ workarounds->useUnusedBlocksWithStandardOrSharedLayout = true;
+#endif
+
+ workarounds->finishDoesNotCauseQueriesToBeAvailable =
+ functions->standard == STANDARD_GL_DESKTOP && IsNvidia(vendor);
+
+ // TODO(cwallez): Disable this workaround for MacOSX versions 10.9 or later.
+ workarounds->alwaysCallUseProgramAfterLink = true;
+
+ workarounds->unpackOverlappingRowsSeparatelyUnpackBuffer = IsNvidia(vendor);
+ workarounds->packOverlappingRowsSeparatelyPackBuffer = IsNvidia(vendor);
+
+ workarounds->initializeCurrentVertexAttributes = IsNvidia(vendor);
+
+#if defined(ANGLE_PLATFORM_APPLE)
+ workarounds->unpackLastRowSeparatelyForPaddingInclusion = true;
+ workarounds->packLastRowSeparatelyForPaddingInclusion = true;
+#else
+ workarounds->unpackLastRowSeparatelyForPaddingInclusion = IsNvidia(vendor);
+ workarounds->packLastRowSeparatelyForPaddingInclusion = IsNvidia(vendor);
+#endif
+
+ workarounds->removeInvariantAndCentroidForESSL3 = functions->isAtMostGL(gl::Version(4, 1));
+}
+
+}
+
+bool CanMapBufferForRead(const FunctionsGL *functions)
+{
+ return (functions->mapBufferRange != nullptr) ||
+ (functions->mapBuffer != nullptr && functions->standard == STANDARD_GL_DESKTOP);
+}
+
+uint8_t *MapBufferRangeWithFallback(const FunctionsGL *functions,
+ GLenum target,
+ size_t offset,
+ size_t length,
+ GLbitfield access)
+{
+ if (functions->mapBufferRange != nullptr)
+ {
+ return reinterpret_cast<uint8_t *>(
+ functions->mapBufferRange(target, offset, length, access));
+ }
+ else if (functions->mapBuffer != nullptr &&
+ (functions->standard == STANDARD_GL_DESKTOP || access == GL_MAP_WRITE_BIT))
+ {
+ // Only the read and write bits are supported
+ ASSERT((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) != 0);
+
+ GLenum accessEnum = 0;
+ if (access == (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))
+ {
+ accessEnum = GL_READ_WRITE;
+ }
+ else if (access == GL_MAP_READ_BIT)
+ {
+ accessEnum = GL_READ_ONLY;
+ }
+ else if (access == GL_MAP_WRITE_BIT)
+ {
+ accessEnum = GL_WRITE_ONLY;
+ }
+ else
+ {
+ UNREACHABLE();
+ return nullptr;
+ }
+
+ return reinterpret_cast<uint8_t *>(functions->mapBuffer(target, accessEnum)) + offset;
+ }
+ else
+ {
+ // No options available
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Extents &size,
+ const gl::PixelStoreStateBase &state,
+ GLenum format,
+ GLenum type,
+ bool is3D,
+ const void *pixels)
+{
+ if (state.pixelBuffer.get() == nullptr)
+ {
+ return false;
+ }
+
+ // We are using an pack or unpack buffer, compute what the driver thinks is going to be the
+ // last byte read or written. If it is past the end of the buffer, we will need to use the
+ // workaround otherwise the driver will generate INVALID_OPERATION and not do the operation.
+ CheckedNumeric<size_t> checkedEndByte;
+ CheckedNumeric<size_t> pixelBytes;
+ size_t rowPitch;
+
+ const gl::InternalFormat &glFormat =
+ gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
+ ANGLE_TRY_RESULT(glFormat.computePackUnpackEndByte(size, state, is3D), checkedEndByte);
+ ANGLE_TRY_RESULT(glFormat.computeRowPitch(size.width, state.alignment, state.rowLength),
+ rowPitch);
+ pixelBytes = glFormat.pixelBytes;
+
+ checkedEndByte += reinterpret_cast<intptr_t>(pixels);
+
+ // At this point checkedEndByte is the actual last byte read.
+ // The driver adds an extra row padding (if any), mimic it.
+ ANGLE_TRY_CHECKED_MATH(pixelBytes);
+ if (pixelBytes.ValueOrDie() * size.width < rowPitch)
+ {
+ checkedEndByte += rowPitch - pixelBytes * size.width;
+ }
+
+ ANGLE_TRY_CHECKED_MATH(checkedEndByte);
+
+ return checkedEndByte.ValueOrDie() > static_cast<size_t>(state.pixelBuffer->getSize());
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.h b/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.h
new file mode 100755
index 000000000..1e9338fb5
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.h
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2012-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.
+//
+
+// renderergl_utils.h: Conversion functions and other utility routines
+// specific to the OpenGL renderer.
+
+#ifndef LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_
+#define LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/driver_utils.h"
+#include "libANGLE/renderer/gl/functionsgl_typedefs.h"
+
+#include <string>
+#include <vector>
+
+namespace gl
+{
+struct Caps;
+class TextureCapsMap;
+struct Extensions;
+struct Version;
+}
+
+namespace rx
+{
+class FunctionsGL;
+struct WorkaroundsGL;
+
+VendorID GetVendorID(const FunctionsGL *functions);
+std::string GetDriverVersion(const FunctionsGL *functions);
+
+namespace nativegl_gl
+{
+
+void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap,
+ gl::Extensions *extensions, gl::Version *maxSupportedESVersion);
+
+void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds);
+}
+
+bool CanMapBufferForRead(const FunctionsGL *functions);
+uint8_t *MapBufferRangeWithFallback(const FunctionsGL *functions,
+ GLenum target,
+ size_t offset,
+ size_t length,
+ GLbitfield access);
+
+gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Extents &size,
+ const gl::PixelStoreStateBase &state,
+ GLenum format,
+ GLenum type,
+ bool is3D,
+ const void *pixels);
+}
+
+#endif // LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp
new file mode 100644
index 000000000..f19e8fdf3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp
@@ -0,0 +1,384 @@
+//
+// Copyright (c) 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.
+//
+
+// D3DTextureSurfaceWGL.cpp: WGL implementation of egl::Surface for D3D texture interop.
+
+#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h"
+
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+
+namespace rx
+{
+
+namespace
+{
+
+egl::Error GetD3DTextureInfo(EGLClientBuffer clientBuffer,
+ size_t *width,
+ size_t *height,
+ IUnknown **object,
+ IUnknown **device)
+{
+ IUnknown *buffer = static_cast<IUnknown *>(clientBuffer);
+
+ IDirect3DTexture9 *texture9 = nullptr;
+ ID3D11Texture2D *texture11 = nullptr;
+ if (SUCCEEDED(buffer->QueryInterface<ID3D11Texture2D>(&texture11)))
+ {
+ D3D11_TEXTURE2D_DESC textureDesc;
+ texture11->GetDesc(&textureDesc);
+
+ // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+ switch (textureDesc.Format)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ break;
+
+ default:
+ SafeRelease(texture11);
+ return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
+ textureDesc.Format);
+ }
+
+ ID3D11Device *d3d11Device = nullptr;
+ texture11->GetDevice(&d3d11Device);
+ if (d3d11Device == nullptr)
+ {
+ SafeRelease(texture11);
+ return egl::Error(EGL_BAD_PARAMETER,
+ "Could not query the D3D11 device from the client buffer.");
+ }
+
+ if (width)
+ {
+ *width = textureDesc.Width;
+ }
+ if (height)
+ {
+ *height = textureDesc.Height;
+ }
+
+ if (device)
+ {
+ *device = d3d11Device;
+ }
+ else
+ {
+ SafeRelease(d3d11Device);
+ }
+
+ if (object)
+ {
+ *object = texture11;
+ }
+ else
+ {
+ SafeRelease(texture11);
+ }
+
+ return egl::Error(EGL_SUCCESS);
+ }
+ else if (SUCCEEDED(buffer->QueryInterface<IDirect3DTexture9>(&texture9)))
+ {
+ D3DSURFACE_DESC surfaceDesc;
+ if (FAILED(texture9->GetLevelDesc(0, &surfaceDesc)))
+ {
+ SafeRelease(texture9);
+ return egl::Error(EGL_BAD_PARAMETER,
+ "Could not query description of the D3D9 surface.");
+ }
+
+ // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+ switch (surfaceDesc.Format)
+ {
+ case D3DFMT_R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_A16B16G16R16F:
+ case D3DFMT_A32B32G32R32F:
+ break;
+
+ default:
+ SafeRelease(texture9);
+ return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
+ surfaceDesc.Format);
+ }
+
+ if (width)
+ {
+ *width = surfaceDesc.Width;
+ }
+ if (height)
+ {
+ *height = surfaceDesc.Height;
+ }
+
+ IDirect3DDevice9 *d3d9Device = nullptr;
+ HRESULT result = texture9->GetDevice(&d3d9Device);
+ if (FAILED(result))
+ {
+ SafeRelease(texture9);
+ return egl::Error(EGL_BAD_PARAMETER,
+ "Could not query the D3D9 device from the client buffer.");
+ }
+
+ if (device)
+ {
+ *device = d3d9Device;
+ }
+ else
+ {
+ SafeRelease(d3d9Device);
+ }
+
+ if (object)
+ {
+ *object = texture9;
+ }
+ else
+ {
+ SafeRelease(texture9);
+ }
+
+ return egl::Error(EGL_SUCCESS);
+ }
+ else
+ {
+ return egl::Error(EGL_BAD_PARAMETER,
+ "Provided buffer is not a IDirect3DTexture9 or ID3D11Texture2D.");
+ }
+}
+
+} // anonymous namespace
+
+D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLClientBuffer clientBuffer,
+ DisplayWGL *display,
+ HGLRC wglContext,
+ HDC deviceContext,
+ const FunctionsGL *functionsGL,
+ const FunctionsWGL *functionsWGL)
+ : SurfaceGL(state, renderer),
+ mClientBuffer(clientBuffer),
+ mRenderer(renderer),
+ mDisplay(display),
+ mStateManager(renderer->getStateManager()),
+ mWorkarounds(renderer->getWorkarounds()),
+ mFunctionsGL(functionsGL),
+ mFunctionsWGL(functionsWGL),
+ mWGLContext(wglContext),
+ mDeviceContext(deviceContext),
+ mWidth(0),
+ mHeight(0),
+ mDeviceHandle(nullptr),
+ mObject(nullptr),
+ mBoundObjectTextureHandle(nullptr),
+ mBoundObjectRenderbufferHandle(nullptr),
+ mRenderbufferID(0),
+ mFramebufferID(0)
+{
+}
+
+D3DTextureSurfaceWGL::~D3DTextureSurfaceWGL()
+{
+ ASSERT(mBoundObjectTextureHandle == nullptr);
+
+ SafeRelease(mObject);
+
+ if (mDeviceHandle)
+ {
+ if (mBoundObjectRenderbufferHandle)
+ {
+ mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectRenderbufferHandle);
+ mBoundObjectRenderbufferHandle = nullptr;
+ }
+ mStateManager->deleteRenderbuffer(mRenderbufferID);
+
+ if (mBoundObjectTextureHandle)
+ {
+ mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectTextureHandle);
+ mBoundObjectTextureHandle = nullptr;
+ }
+
+ // GL framebuffer is deleted by the default framebuffer object
+ mFramebufferID = 0;
+
+ mDisplay->releaseD3DDevice(mDeviceHandle);
+ mDeviceHandle = nullptr;
+ }
+}
+
+egl::Error D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(EGLClientBuffer clientBuffer)
+{
+ return GetD3DTextureInfo(clientBuffer, nullptr, nullptr, nullptr, nullptr);
+}
+
+egl::Error D3DTextureSurfaceWGL::initialize()
+{
+ IUnknown *device = nullptr;
+ ANGLE_TRY(GetD3DTextureInfo(mClientBuffer, &mWidth, &mHeight, &mObject, &device));
+
+ ASSERT(device != nullptr);
+ egl::Error error = mDisplay->registerD3DDevice(device, &mDeviceHandle);
+ SafeRelease(device);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mFunctionsGL->genRenderbuffers(1, &mRenderbufferID);
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID);
+ mBoundObjectRenderbufferHandle = mFunctionsWGL->dxRegisterObjectNV(
+ mDeviceHandle, mObject, mRenderbufferID, GL_RENDERBUFFER, WGL_ACCESS_READ_WRITE_NV);
+ if (mBoundObjectRenderbufferHandle == nullptr)
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+
+ mFunctionsGL->genFramebuffers(1, &mFramebufferID);
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+ mRenderbufferID);
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::makeCurrent()
+{
+ if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext))
+ {
+ // TODO(geofflang): What error type here?
+ return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
+ }
+
+ if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mBoundObjectRenderbufferHandle))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
+ HRESULT_CODE(error));
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::unMakeCurrent()
+{
+ if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mBoundObjectRenderbufferHandle))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to unlock object, error: 0x%08x.",
+ HRESULT_CODE(error));
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::swap()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ ASSERT(mBoundObjectTextureHandle == nullptr);
+
+ const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
+ GLuint textureID = textureGL->getTextureID();
+
+ mBoundObjectTextureHandle = mFunctionsWGL->dxRegisterObjectNV(
+ mDeviceHandle, mObject, textureID, GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
+ if (mBoundObjectTextureHandle == nullptr)
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.",
+ HRESULT_CODE(error));
+ }
+
+ if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mBoundObjectTextureHandle))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
+ HRESULT_CODE(error));
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::releaseTexImage(EGLint buffer)
+{
+ ASSERT(mBoundObjectTextureHandle != nullptr);
+ if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mBoundObjectTextureHandle))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to unlock object, error: 0x%08x.",
+ HRESULT_CODE(error));
+ }
+
+ if (!mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectTextureHandle))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to unregister D3D object, error: 0x%08x.",
+ HRESULT_CODE(error));
+ }
+ mBoundObjectTextureHandle = nullptr;
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+void D3DTextureSurfaceWGL::setSwapInterval(EGLint interval)
+{
+ UNIMPLEMENTED();
+}
+
+EGLint D3DTextureSurfaceWGL::getWidth() const
+{
+ return static_cast<EGLint>(mWidth);
+}
+
+EGLint D3DTextureSurfaceWGL::getHeight() const
+{
+ return static_cast<EGLint>(mHeight);
+}
+
+EGLint D3DTextureSurfaceWGL::isPostSubBufferSupported() const
+{
+ return EGL_FALSE;
+}
+
+EGLint D3DTextureSurfaceWGL::getSwapBehavior() const
+{
+ return EGL_BUFFER_PRESERVED;
+}
+
+FramebufferImpl *D3DTextureSurfaceWGL::createDefaultFramebuffer(const gl::FramebufferState &data)
+{
+ return new FramebufferGL(mFramebufferID, data, mFunctionsGL, mWorkarounds,
+ mRenderer->getBlitter(), mStateManager);
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h
new file mode 100644
index 000000000..8fb1d4003
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h
@@ -0,0 +1,86 @@
+
+// Copyright (c) 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.
+//
+
+// D3DTextureSurfaceWGL.h: WGL implementation of egl::Surface for D3D texture interop.
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsGL;
+class FunctionsWGL;
+class DisplayWGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class D3DTextureSurfaceWGL : public SurfaceGL
+{
+ public:
+ D3DTextureSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLClientBuffer clientBuffer,
+ DisplayWGL *display,
+ HGLRC wglContext,
+ HDC deviceContext,
+ const FunctionsGL *functionsGL,
+ const FunctionsWGL *functionsWGL);
+ ~D3DTextureSurfaceWGL() override;
+
+ static egl::Error ValidateD3DTextureClientBuffer(EGLClientBuffer clientBuffer);
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+ egl::Error unMakeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
+
+ private:
+ EGLClientBuffer mClientBuffer;
+
+ RendererGL *mRenderer;
+
+ DisplayWGL *mDisplay;
+ StateManagerGL *mStateManager;
+ const WorkaroundsGL &mWorkarounds;
+ const FunctionsGL *mFunctionsGL;
+ const FunctionsWGL *mFunctionsWGL;
+
+ HGLRC mWGLContext;
+ HDC mDeviceContext;
+
+ size_t mWidth;
+ size_t mHeight;
+
+ HANDLE mDeviceHandle;
+ IUnknown *mObject;
+ HANDLE mBoundObjectTextureHandle;
+ HANDLE mBoundObjectRenderbufferHandle;
+
+ GLuint mRenderbufferID;
+ GLuint mFramebufferID;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp
new file mode 100755
index 000000000..7c5214e82
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp
@@ -0,0 +1,553 @@
+//
+// Copyright (c) 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.
+//
+
+// DXGISwapChainWindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows using a DXGI
+// swapchain.
+
+#include "libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+
+#include <EGL/eglext.h>
+
+namespace rx
+{
+
+DXGISwapChainWindowSurfaceWGL::DXGISwapChainWindowSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLNativeWindowType window,
+ ID3D11Device *device,
+ HANDLE deviceHandle,
+ HGLRC wglContext,
+ HDC deviceContext,
+ const FunctionsGL *functionsGL,
+ const FunctionsWGL *functionsWGL,
+ EGLint orientation)
+ : SurfaceGL(state, renderer),
+ mWindow(window),
+ mStateManager(renderer->getStateManager()),
+ mWorkarounds(renderer->getWorkarounds()),
+ mRenderer(renderer),
+ mFunctionsGL(functionsGL),
+ mFunctionsWGL(functionsWGL),
+ mDevice(device),
+ mDeviceHandle(deviceHandle),
+ mWGLDevice(deviceContext),
+ mWGLContext(wglContext),
+ mSwapChainFormat(DXGI_FORMAT_UNKNOWN),
+ mSwapChainFlags(0),
+ mDepthBufferFormat(GL_NONE),
+ mFirstSwap(true),
+ mSwapChain(nullptr),
+ mSwapChain1(nullptr),
+ mColorRenderbufferID(0),
+ mRenderbufferBufferHandle(nullptr),
+ mDepthRenderbufferID(0),
+ mFramebufferID(0),
+ mTextureID(0),
+ mTextureHandle(nullptr),
+ mWidth(0),
+ mHeight(0),
+ mSwapInterval(1),
+ mOrientation(orientation)
+{
+}
+
+DXGISwapChainWindowSurfaceWGL::~DXGISwapChainWindowSurfaceWGL()
+{
+ if (mRenderbufferBufferHandle != nullptr)
+ {
+ mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mRenderbufferBufferHandle);
+ mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mRenderbufferBufferHandle);
+ }
+
+ if (mColorRenderbufferID != 0)
+ {
+ mStateManager->deleteRenderbuffer(mColorRenderbufferID);
+ mColorRenderbufferID = 0;
+ }
+
+ if (mDepthRenderbufferID != 0)
+ {
+ mStateManager->deleteRenderbuffer(mDepthRenderbufferID);
+ mDepthRenderbufferID = 0;
+ }
+
+ SafeRelease(mSwapChain);
+ SafeRelease(mSwapChain1);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::initialize()
+{
+ if (mOrientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE)
+ {
+ // TODO(geofflang): Support the orientation extensions fully. Currently only inverting Y is
+ // supported. To support all orientations, an intermediate framebuffer will be needed with
+ // a blit before swap.
+ return egl::Error(EGL_BAD_ATTRIBUTE,
+ "DXGISwapChainWindowSurfaceWGL requires an orientation of "
+ "EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE.");
+ }
+
+ RECT rect;
+ if (!GetClientRect(mWindow, &rect))
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the window size.");
+ }
+ mWidth = rect.right - rect.left;
+ mHeight = rect.bottom - rect.top;
+
+ mSwapChainFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
+ mSwapChainFlags = 0;
+ mDepthBufferFormat = GL_DEPTH24_STENCIL8;
+
+ mFunctionsGL->genFramebuffers(1, &mFramebufferID);
+ mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID);
+ mFunctionsGL->genRenderbuffers(1, &mDepthRenderbufferID);
+
+ return createSwapChain();
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::makeCurrent()
+{
+ if (!mFunctionsWGL->makeCurrent(mWGLDevice, mWGLContext))
+ {
+ // TODO: What error type here?
+ return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::swap()
+{
+ mFunctionsGL->flush();
+
+ egl::Error error = setObjectsLocked(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ HRESULT result = mSwapChain->Present(mSwapInterval, 0);
+ mFirstSwap = false;
+
+ error = setObjectsLocked(true);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to present swap chain, result: 0x%X", result);
+ }
+
+ return checkForResize();
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::postSubBuffer(EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
+{
+ ASSERT(mSwapChain1 != nullptr);
+
+ mFunctionsGL->flush();
+
+ egl::Error error = setObjectsLocked(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ HRESULT result = S_OK;
+ if (mFirstSwap)
+ {
+ result = mSwapChain1->Present(mSwapInterval, 0);
+ mFirstSwap = false;
+ }
+ 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(mSwapInterval, 0, &params);
+ }
+
+ error = setObjectsLocked(true);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to present swap chain, result: 0x%X", result);
+ }
+
+ return checkForResize();
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNREACHABLE();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ ASSERT(mTextureHandle == nullptr);
+
+ const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
+ GLuint textureID = textureGL->getTextureID();
+
+ ID3D11Texture2D *colorBuffer = nullptr;
+ HRESULT result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
+ reinterpret_cast<void **>(&colorBuffer));
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to query texture from swap chain, result: 0x%X",
+ result);
+ }
+
+ mTextureHandle = mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, textureID,
+ GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
+ SafeRelease(colorBuffer);
+ if (mTextureHandle == nullptr)
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+
+ if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mTextureHandle))
+ {
+ mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle);
+ mTextureHandle = nullptr;
+
+ return egl::Error(EGL_BAD_ALLOC, "Failed to lock D3D object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+
+ mTextureID = textureID;
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::releaseTexImage(EGLint buffer)
+{
+ ASSERT(mTextureHandle != nullptr);
+
+ if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mTextureHandle))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to unlock D3D object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+
+ if (!mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to unregister D3D object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+
+ mTextureID = 0;
+ mTextureHandle = nullptr;
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+void DXGISwapChainWindowSurfaceWGL::setSwapInterval(EGLint interval)
+{
+ mSwapInterval = interval;
+}
+
+EGLint DXGISwapChainWindowSurfaceWGL::getWidth() const
+{
+ return static_cast<EGLint>(mWidth);
+}
+
+EGLint DXGISwapChainWindowSurfaceWGL::getHeight() const
+{
+ return static_cast<EGLint>(mHeight);
+}
+
+EGLint DXGISwapChainWindowSurfaceWGL::isPostSubBufferSupported() const
+{
+ return mSwapChain1 != nullptr;
+}
+
+EGLint DXGISwapChainWindowSurfaceWGL::getSwapBehavior() const
+{
+ return EGL_BUFFER_DESTROYED;
+}
+
+FramebufferImpl *DXGISwapChainWindowSurfaceWGL::createDefaultFramebuffer(
+ const gl::FramebufferState &data)
+{
+ return new FramebufferGL(mFramebufferID, data, mFunctionsGL, mWorkarounds,
+ mRenderer->getBlitter(), mStateManager);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::setObjectsLocked(bool locked)
+{
+ if (mRenderbufferBufferHandle == nullptr)
+ {
+ ASSERT(mTextureHandle == nullptr);
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ HANDLE resources[] = {
+ mRenderbufferBufferHandle, mTextureHandle,
+ };
+ GLint count = (mTextureHandle != nullptr) ? 2 : 1;
+
+ if (locked)
+ {
+ if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, count, resources))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+ }
+ else
+ {
+ if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, count, resources))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::checkForResize()
+{
+ RECT rect;
+ if (!GetClientRect(mWindow, &rect))
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the window size.");
+ }
+
+ size_t newWidth = rect.right - rect.left;
+ size_t newHeight = rect.bottom - rect.top;
+ if (newWidth != mWidth || newHeight != mHeight)
+ {
+ mWidth = newWidth;
+ mHeight = newHeight;
+
+ // TODO(geofflang): Handle resize by resizing the swap chain instead of re-creating it.
+ egl::Error error = createSwapChain();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+static IDXGIFactory *GetDXGIFactoryFromDevice(ID3D11Device *device)
+{
+ IDXGIDevice *dxgiDevice = nullptr;
+ HRESULT result =
+ device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void **>(&dxgiDevice));
+ if (FAILED(result))
+ {
+ return nullptr;
+ }
+
+ IDXGIAdapter *dxgiAdapter = nullptr;
+ result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void **>(&dxgiAdapter));
+ SafeRelease(dxgiDevice);
+ if (FAILED(result))
+ {
+ return nullptr;
+ }
+
+ IDXGIFactory *dxgiFactory = nullptr;
+ result =
+ dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void **>(&dxgiFactory));
+ SafeRelease(dxgiAdapter);
+ if (FAILED(result))
+ {
+ return nullptr;
+ }
+
+ return dxgiFactory;
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::createSwapChain()
+{
+ egl::Error error = setObjectsLocked(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (mRenderbufferBufferHandle)
+ {
+ mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mRenderbufferBufferHandle);
+ mRenderbufferBufferHandle = nullptr;
+ }
+
+ // If this surface is bound to a texture, unregister it.
+ bool hadBoundSurface = (mTextureHandle != nullptr);
+ if (hadBoundSurface)
+ {
+ mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle);
+ mTextureHandle = nullptr;
+ }
+
+ IDXGIFactory *dxgiFactory = GetDXGIFactoryFromDevice(mDevice);
+ if (dxgiFactory == nullptr)
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the DXGIFactory.");
+ }
+
+ IDXGIFactory2 *dxgiFactory2 = nullptr;
+ HRESULT result = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2),
+ reinterpret_cast<void **>(&dxgiFactory2));
+ if (SUCCEEDED(result))
+ {
+ ASSERT(dxgiFactory2 != nullptr);
+
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
+ swapChainDesc.BufferCount = 1;
+ swapChainDesc.Format = mSwapChainFormat;
+ swapChainDesc.Width = static_cast<UINT>(mWidth);
+ swapChainDesc.Height = static_cast<UINT>(mHeight);
+ swapChainDesc.Format = mSwapChainFormat;
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = 1;
+ 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 = mSwapChainFlags;
+
+ result = dxgiFactory2->CreateSwapChainForHwnd(mDevice, mWindow, &swapChainDesc, nullptr,
+ nullptr, &mSwapChain1);
+ SafeRelease(dxgiFactory2);
+ SafeRelease(dxgiFactory);
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to create swap chain for window, result: 0x%X",
+ result);
+ }
+
+ mSwapChain = mSwapChain1;
+ mSwapChain->AddRef();
+ }
+ else
+ {
+ DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
+ swapChainDesc.BufferCount = 1;
+ swapChainDesc.BufferDesc.Format = mSwapChainFormat;
+ swapChainDesc.BufferDesc.Width = static_cast<UINT>(mWidth);
+ swapChainDesc.BufferDesc.Height = static_cast<UINT>(mHeight);
+ 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 = mSwapChainFlags;
+ swapChainDesc.OutputWindow = mWindow;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.Windowed = TRUE;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+
+ result = dxgiFactory->CreateSwapChain(mDevice, &swapChainDesc, &mSwapChain);
+ SafeRelease(dxgiFactory);
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to create swap chain for window, result: 0x%X",
+ result);
+ }
+ }
+
+ ID3D11Texture2D *colorBuffer = nullptr;
+ result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
+ reinterpret_cast<void **>(&colorBuffer));
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to query texture from swap chain, result: 0x%X",
+ result);
+ }
+
+ mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID);
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbufferID);
+ mRenderbufferBufferHandle =
+ mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mColorRenderbufferID,
+ GL_RENDERBUFFER, WGL_ACCESS_READ_WRITE_NV);
+ SafeRelease(colorBuffer);
+ if (mRenderbufferBufferHandle == nullptr)
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%X.",
+ HRESULT_CODE(GetLastError()));
+ }
+
+ // Rebind the surface to the texture if needed.
+ if (hadBoundSurface)
+ {
+ mTextureHandle = mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mTextureID,
+ GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
+ if (mTextureHandle == nullptr)
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%X.",
+ HRESULT_CODE(GetLastError()));
+ }
+ }
+
+ error = setObjectsLocked(true);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(mFramebufferID != 0);
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+ mColorRenderbufferID);
+
+ if (mDepthBufferFormat != GL_NONE)
+ {
+ ASSERT(mDepthRenderbufferID != 0);
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbufferID);
+ mFunctionsGL->renderbufferStorage(GL_RENDERBUFFER, mDepthBufferFormat,
+ static_cast<GLsizei>(mWidth),
+ static_cast<GLsizei>(mHeight));
+
+ const gl::InternalFormat &depthStencilFormatInfo =
+ gl::GetInternalFormatInfo(mDepthBufferFormat);
+ if (depthStencilFormatInfo.depthBits > 0)
+ {
+ mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, mDepthRenderbufferID);
+ }
+ if (depthStencilFormatInfo.stencilBits > 0)
+ {
+ mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, mDepthRenderbufferID);
+ }
+ }
+
+ mFirstSwap = true;
+
+ return egl::Error(EGL_SUCCESS);
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h
new file mode 100755
index 000000000..f516239c9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h
@@ -0,0 +1,106 @@
+//
+// Copyright (c) 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.
+//
+
+// DXGISwapChainWindowSurfaceWGL.h: WGL implementation of egl::Surface for windows using a DXGI
+// swapchain.
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_DXGISWAPCHAINSURFACEWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_DXGISWAPCHAINSURFACEWGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsGL;
+class FunctionsWGL;
+class DisplayWGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class DXGISwapChainWindowSurfaceWGL : public SurfaceGL
+{
+ public:
+ DXGISwapChainWindowSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLNativeWindowType window,
+ ID3D11Device *device,
+ HANDLE deviceHandle,
+ HGLRC wglContext,
+ HDC deviceContext,
+ const FunctionsGL *functionsGL,
+ const FunctionsWGL *functionsWGL,
+ EGLint orientation);
+ ~DXGISwapChainWindowSurfaceWGL() override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
+
+ private:
+ egl::Error setObjectsLocked(bool locked);
+ egl::Error checkForResize();
+
+ egl::Error createSwapChain();
+
+ EGLNativeWindowType mWindow;
+
+ StateManagerGL *mStateManager;
+ const WorkaroundsGL &mWorkarounds;
+ RendererGL *mRenderer;
+ const FunctionsGL *mFunctionsGL;
+ const FunctionsWGL *mFunctionsWGL;
+
+ ID3D11Device *mDevice;
+ HANDLE mDeviceHandle;
+
+ HDC mWGLDevice;
+ HGLRC mWGLContext;
+
+ DXGI_FORMAT mSwapChainFormat;
+ UINT mSwapChainFlags;
+ GLenum mDepthBufferFormat;
+
+ bool mFirstSwap;
+ IDXGISwapChain *mSwapChain;
+ IDXGISwapChain1 *mSwapChain1;
+
+ GLuint mColorRenderbufferID;
+ HANDLE mRenderbufferBufferHandle;
+
+ GLuint mDepthRenderbufferID;
+
+ GLuint mFramebufferID;
+
+ GLuint mTextureID;
+ HANDLE mTextureHandle;
+
+ size_t mWidth;
+ size_t mHeight;
+
+ EGLint mSwapInterval;
+
+ EGLint mOrientation;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_WGL_DXGISWAPCHAINSURFACEWGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
new file mode 100755
index 000000000..188321115
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
@@ -0,0 +1,741 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayWGL.h: WGL implementation of egl::Display
+
+#include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h"
+#include "libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+#include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h"
+#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"
+#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
+
+#include "platform/Platform.h"
+
+#include <EGL/eglext.h>
+#include <string>
+#include <sstream>
+
+namespace rx
+{
+
+class FunctionsGLWindows : public FunctionsGL
+{
+ public:
+ FunctionsGLWindows(HMODULE openGLModule, PFNWGLGETPROCADDRESSPROC getProcAddressWGL)
+ : mOpenGLModule(openGLModule),
+ mGetProcAddressWGL(getProcAddressWGL)
+ {
+ ASSERT(mOpenGLModule);
+ ASSERT(mGetProcAddressWGL);
+ }
+
+ ~FunctionsGLWindows() override {}
+
+ private:
+ void *loadProcAddress(const std::string &function) override
+ {
+ void *proc = reinterpret_cast<void*>(mGetProcAddressWGL(function.c_str()));
+ if (!proc)
+ {
+ proc = reinterpret_cast<void*>(GetProcAddress(mOpenGLModule, function.c_str()));
+ }
+ return proc;
+ }
+
+ HMODULE mOpenGLModule;
+ PFNWGLGETPROCADDRESSPROC mGetProcAddressWGL;
+};
+
+DisplayWGL::DisplayWGL()
+ : DisplayGL(),
+ mOpenGLModule(nullptr),
+ mFunctionsWGL(nullptr),
+ mFunctionsGL(nullptr),
+ mHasRobustness(false),
+ mWindowClass(0),
+ mWindow(nullptr),
+ mDeviceContext(nullptr),
+ mPixelFormat(0),
+ mWGLContext(nullptr),
+ mUseDXGISwapChains(false),
+ mDxgiModule(nullptr),
+ mD3d11Module(nullptr),
+ mD3D11DeviceHandle(nullptr),
+ mD3D11Device(nullptr),
+ mDisplay(nullptr)
+{
+}
+
+DisplayWGL::~DisplayWGL()
+{
+}
+
+egl::Error DisplayWGL::initialize(egl::Display *display)
+{
+ mDisplay = display;
+
+ mOpenGLModule = LoadLibraryA("opengl32.dll");
+ if (!mOpenGLModule)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to load OpenGL library.");
+ }
+
+ mFunctionsWGL = new FunctionsWGL();
+ mFunctionsWGL->initialize(mOpenGLModule, nullptr);
+
+ // WGL can't grab extensions until it creates a context because it needs to load the driver's DLLs first.
+ // Create a dummy context to load the driver and determine which GL versions are available.
+
+ // Work around compile error from not defining "UNICODE" while Chromium does
+ const LPSTR idcArrow = MAKEINTRESOURCEA(32512);
+
+ std::string className = FormatString("ANGLE DisplayWGL 0x%0.8p Intermediate Window Class", mDisplay);
+
+ WNDCLASSA intermediateClassDesc = { 0 };
+ intermediateClassDesc.style = CS_OWNDC;
+ intermediateClassDesc.lpfnWndProc = DefWindowProc;
+ intermediateClassDesc.cbClsExtra = 0;
+ intermediateClassDesc.cbWndExtra = 0;
+ intermediateClassDesc.hInstance = GetModuleHandle(nullptr);
+ intermediateClassDesc.hIcon = nullptr;
+ intermediateClassDesc.hCursor = LoadCursorA(nullptr, idcArrow);
+ intermediateClassDesc.hbrBackground = 0;
+ intermediateClassDesc.lpszMenuName = nullptr;
+ intermediateClassDesc.lpszClassName = className.c_str();
+ mWindowClass = RegisterClassA(&intermediateClassDesc);
+ if (!mWindowClass)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to register intermediate OpenGL window class.");
+ }
+
+ HWND dummyWindow = CreateWindowExA(0,
+ reinterpret_cast<const char *>(mWindowClass),
+ "ANGLE Dummy Window",
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr);
+ if (!dummyWindow)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to create dummy OpenGL window.");
+ }
+
+ HDC dummyDeviceContext = GetDC(dummyWindow);
+ if (!dummyDeviceContext)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to get the device context of the dummy OpenGL window.");
+ }
+
+ const PIXELFORMATDESCRIPTOR pixelFormatDescriptor = wgl::GetDefaultPixelFormatDescriptor();
+
+ int dummyPixelFormat = ChoosePixelFormat(dummyDeviceContext, &pixelFormatDescriptor);
+ if (dummyPixelFormat == 0)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not find a compatible pixel format for the dummy OpenGL window.");
+ }
+
+ if (!SetPixelFormat(dummyDeviceContext, dummyPixelFormat, &pixelFormatDescriptor))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the intermediate OpenGL window.");
+ }
+
+ HGLRC dummyWGLContext = mFunctionsWGL->createContext(dummyDeviceContext);
+ if (!dummyDeviceContext)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to create a WGL context for the dummy OpenGL window.");
+ }
+
+ if (!mFunctionsWGL->makeCurrent(dummyDeviceContext, dummyWGLContext))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the dummy WGL context current.");
+ }
+
+ // Grab the GL version from this context and use it as the maximum version available.
+ typedef const GLubyte* (GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+ PFNGLGETSTRINGPROC getString = reinterpret_cast<PFNGLGETSTRINGPROC>(GetProcAddress(mOpenGLModule, "glGetString"));
+ if (!getString)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to get glGetString pointer.");
+ }
+
+ // Reinitialize the wgl functions to grab the extensions
+ mFunctionsWGL->initialize(mOpenGLModule, dummyDeviceContext);
+
+ bool hasWGLCreateContextRobustness =
+ mFunctionsWGL->hasExtension("WGL_ARB_create_context_robustness");
+
+ // Destroy the dummy window and context
+ mFunctionsWGL->makeCurrent(dummyDeviceContext, nullptr);
+ mFunctionsWGL->deleteContext(dummyWGLContext);
+ ReleaseDC(dummyWindow, dummyDeviceContext);
+ DestroyWindow(dummyWindow);
+
+ const egl::AttributeMap &displayAttributes = display->getAttributeMap();
+ EGLint requestedDisplayType = static_cast<EGLint>(displayAttributes.get(
+ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
+ if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE &&
+ !mFunctionsWGL->hasExtension("WGL_EXT_create_context_es2_profile") &&
+ !mFunctionsWGL->hasExtension("WGL_EXT_create_context_es_profile"))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED,
+ "Cannot create an OpenGL ES platform on Windows without "
+ "the WGL_EXT_create_context_es(2)_profile extension.");
+ }
+
+ // Create the real intermediate context and windows
+ mWindow = CreateWindowExA(0,
+ reinterpret_cast<const char *>(mWindowClass),
+ "ANGLE Intermediate Window",
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr);
+ if (!mWindow)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to create intermediate OpenGL window.");
+ }
+
+ mDeviceContext = GetDC(mWindow);
+ if (!mDeviceContext)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to get the device context of the intermediate OpenGL window.");
+ }
+
+ if (mFunctionsWGL->choosePixelFormatARB)
+ {
+ std::vector<int> attribs = wgl::GetDefaultPixelFormatAttributes(false);
+
+ UINT matchingFormats = 0;
+ mFunctionsWGL->choosePixelFormatARB(mDeviceContext, &attribs[0], nullptr, 1u, &mPixelFormat,
+ &matchingFormats);
+ }
+
+ if (mPixelFormat == 0)
+ {
+ mPixelFormat = ChoosePixelFormat(mDeviceContext, &pixelFormatDescriptor);
+ }
+
+ if (mPixelFormat == 0)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not find a compatible pixel format for the intermediate OpenGL window.");
+ }
+
+ if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the intermediate OpenGL window.");
+ }
+
+ if (mFunctionsWGL->createContextAttribsARB)
+ {
+ int flags = 0;
+ // TODO: allow debug contexts
+ // TODO: handle robustness
+
+ int mask = 0;
+
+ if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+ {
+ mask |= WGL_CONTEXT_ES_PROFILE_BIT_EXT;
+ }
+ else
+ {
+ // Request core profile
+ mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
+ }
+
+ std::vector<int> contextCreationAttributes;
+
+ if (hasWGLCreateContextRobustness)
+ {
+ contextCreationAttributes.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
+ contextCreationAttributes.push_back(WGL_LOSE_CONTEXT_ON_RESET_ARB);
+ }
+
+ // Don't request a specific version unless the user wants one. WGL will return the highest version
+ // that the driver supports if no version is requested.
+ EGLint requestedMajorVersion = static_cast<EGLint>(
+ displayAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE));
+ EGLint requestedMinorVersion = static_cast<EGLint>(
+ displayAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE));
+ if (requestedMajorVersion != EGL_DONT_CARE && requestedMinorVersion != EGL_DONT_CARE)
+ {
+ contextCreationAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
+ contextCreationAttributes.push_back(requestedMajorVersion);
+
+ contextCreationAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
+ contextCreationAttributes.push_back(requestedMinorVersion);
+ }
+ else
+ {
+ // the ES profile will give us ES version 1.1 unless a higher version is requested.
+ // Requesting version 2.0 will give us the highest compatible version available (2.0,
+ // 3.0, 3.1, etc).
+ if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+ {
+ contextCreationAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
+ contextCreationAttributes.push_back(2);
+
+ contextCreationAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
+ contextCreationAttributes.push_back(0);
+ }
+ }
+
+ // Set the flag attributes
+ if (flags != 0)
+ {
+ contextCreationAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
+ contextCreationAttributes.push_back(flags);
+ }
+
+ // Set the mask attribute
+ if (mask != 0)
+ {
+ contextCreationAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
+ contextCreationAttributes.push_back(mask);
+ }
+
+ // Signal the end of the attributes
+ contextCreationAttributes.push_back(0);
+ contextCreationAttributes.push_back(0);
+
+ mWGLContext = mFunctionsWGL->createContextAttribsARB(mDeviceContext, NULL, &contextCreationAttributes[0]);
+ }
+
+ // If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext
+ if (!mWGLContext)
+ {
+ // Don't have control over GL versions
+ mWGLContext = mFunctionsWGL->createContext(mDeviceContext);
+ }
+
+ if (!mWGLContext)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to create a WGL context for the intermediate OpenGL window.");
+ }
+
+ if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the intermediate WGL context current.");
+ }
+
+ mFunctionsGL = new FunctionsGLWindows(mOpenGLModule, mFunctionsWGL->getProcAddress);
+ mFunctionsGL->initialize();
+
+ mHasRobustness = mFunctionsGL->getGraphicsResetStatus != nullptr;
+ if (hasWGLCreateContextRobustness != mHasRobustness)
+ {
+ ANGLEPlatformCurrent()->logWarning(
+ "WGL_ARB_create_context_robustness exists but unable to OpenGL context with "
+ "robustness.");
+ }
+
+ // Intel OpenGL ES drivers are not currently supported due to bugs in the driver and ANGLE
+ VendorID vendor = GetVendorID(mFunctionsGL);
+ if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE && IsIntel(vendor))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Intel OpenGL ES drivers are not supported.");
+ }
+
+ // Create DXGI swap chains for windows that come from other processes. Windows is unable to
+ // SetPixelFormat on windows from other processes when a sandbox is enabled.
+ HDC nativeDisplay = display->getNativeDisplayId();
+ HWND nativeWindow = WindowFromDC(nativeDisplay);
+ if (nativeWindow != nullptr)
+ {
+ DWORD currentProcessId = GetCurrentProcessId();
+ DWORD windowProcessId;
+ GetWindowThreadProcessId(nativeWindow, &windowProcessId);
+
+ // AMD drivers advertise the WGL_NV_DX_interop and WGL_NV_DX_interop2 extensions but fail
+ mUseDXGISwapChains = !IsAMD(vendor) && (currentProcessId != windowProcessId);
+ }
+ else
+ {
+ mUseDXGISwapChains = false;
+ }
+
+ if (mUseDXGISwapChains)
+ {
+ egl::Error error = initializeD3DDevice();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return DisplayGL::initialize(display);
+}
+
+void DisplayWGL::terminate()
+{
+ DisplayGL::terminate();
+
+ releaseD3DDevice(mD3D11DeviceHandle);
+
+ mFunctionsWGL->makeCurrent(mDeviceContext, NULL);
+ mFunctionsWGL->deleteContext(mWGLContext);
+ mWGLContext = NULL;
+
+ ReleaseDC(mWindow, mDeviceContext);
+ mDeviceContext = NULL;
+
+ DestroyWindow(mWindow);
+ mWindow = NULL;
+
+ UnregisterClassA(reinterpret_cast<const char*>(mWindowClass), NULL);
+ mWindowClass = NULL;
+
+ SafeDelete(mFunctionsWGL);
+ SafeDelete(mFunctionsGL);
+
+ FreeLibrary(mOpenGLModule);
+ mOpenGLModule = nullptr;
+
+ SafeRelease(mD3D11Device);
+
+ if (mDxgiModule)
+ {
+ FreeLibrary(mDxgiModule);
+ mDxgiModule = nullptr;
+ }
+
+ if (mD3d11Module)
+ {
+ FreeLibrary(mD3d11Module);
+ mD3d11Module = nullptr;
+ }
+
+ ASSERT(mRegisteredD3DDevices.empty());
+}
+
+SurfaceImpl *DisplayWGL::createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ EGLint orientation = static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
+ if (mUseDXGISwapChains)
+ {
+ return new DXGISwapChainWindowSurfaceWGL(state, getRenderer(), window, mD3D11Device,
+ mD3D11DeviceHandle, mWGLContext, mDeviceContext,
+ mFunctionsGL, mFunctionsWGL, orientation);
+ }
+ else
+ {
+ return new WindowSurfaceWGL(state, getRenderer(), window, mPixelFormat, mWGLContext,
+ mFunctionsWGL, orientation);
+ }
+}
+
+SurfaceImpl *DisplayWGL::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs)
+{
+ EGLint width = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0));
+ EGLint height = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0));
+ bool largest = (attribs.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
+ EGLenum textureFormat = static_cast<EGLenum>(attribs.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE));
+ EGLenum textureTarget = static_cast<EGLenum>(attribs.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
+
+ return new PbufferSurfaceWGL(state, getRenderer(), width, height, textureFormat, textureTarget,
+ largest, mPixelFormat, mDeviceContext, mWGLContext, mFunctionsWGL);
+}
+
+SurfaceImpl *DisplayWGL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(buftype == EGL_D3D_TEXTURE_ANGLE);
+ return new D3DTextureSurfaceWGL(state, getRenderer(), clientBuffer, this, mWGLContext,
+ mDeviceContext, mFunctionsGL, mFunctionsWGL);
+}
+
+SurfaceImpl *DisplayWGL::createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+egl::Error DisplayWGL::getDevice(DeviceImpl **device)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+egl::ConfigSet DisplayWGL::generateConfigs()
+{
+ egl::ConfigSet configs;
+
+ int minSwapInterval = 1;
+ int maxSwapInterval = 1;
+ if (mFunctionsWGL->swapIntervalEXT)
+ {
+ // No defined maximum swap interval in WGL_EXT_swap_control, use a reasonable number
+ minSwapInterval = 0;
+ maxSwapInterval = 8;
+ }
+
+ const gl::Version &maxVersion = getMaxSupportedESVersion();
+ ASSERT(maxVersion >= gl::Version(2, 0));
+ bool supportsES3 = maxVersion >= gl::Version(3, 0);
+
+ PIXELFORMATDESCRIPTOR pixelFormatDescriptor;
+ DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor), &pixelFormatDescriptor);
+
+ auto getAttrib = [this](int attrib)
+ {
+ return wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, attrib, mFunctionsWGL);
+ };
+
+ const EGLint optimalSurfaceOrientation =
+ mUseDXGISwapChains ? EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE : 0;
+
+ egl::Config config;
+ config.renderTargetFormat = GL_RGBA8; // TODO: use the bit counts to determine the format
+ config.depthStencilFormat = GL_DEPTH24_STENCIL8; // TODO: use the bit counts to determine the format
+ config.bufferSize = pixelFormatDescriptor.cColorBits;
+ config.redSize = pixelFormatDescriptor.cRedBits;
+ config.greenSize = pixelFormatDescriptor.cGreenBits;
+ config.blueSize = pixelFormatDescriptor.cBlueBits;
+ config.luminanceSize = 0;
+ config.alphaSize = pixelFormatDescriptor.cAlphaBits;
+ config.alphaMaskSize = 0;
+ config.bindToTextureRGB = (getAttrib(WGL_BIND_TO_TEXTURE_RGB_ARB) == TRUE);
+ config.bindToTextureRGBA = (getAttrib(WGL_BIND_TO_TEXTURE_RGBA_ARB) == TRUE);
+ config.colorBufferType = EGL_RGB_BUFFER;
+ config.configCaveat = EGL_NONE;
+ config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+ config.depthSize = pixelFormatDescriptor.cDepthBits;
+ config.level = 0;
+ config.matchNativePixmap = EGL_NONE;
+ config.maxPBufferWidth = getAttrib(WGL_MAX_PBUFFER_WIDTH_ARB);
+ config.maxPBufferHeight = getAttrib(WGL_MAX_PBUFFER_HEIGHT_ARB);
+ config.maxPBufferPixels = getAttrib(WGL_MAX_PBUFFER_PIXELS_ARB);
+ config.maxSwapInterval = maxSwapInterval;
+ config.minSwapInterval = minSwapInterval;
+ config.nativeRenderable = EGL_TRUE; // Direct rendering
+ config.nativeVisualID = 0;
+ config.nativeVisualType = EGL_NONE;
+ config.renderableType = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+ config.sampleBuffers = 0; // FIXME: enumerate multi-sampling
+ config.samples = 0;
+ config.stencilSize = pixelFormatDescriptor.cStencilBits;
+ config.surfaceType =
+ ((pixelFormatDescriptor.dwFlags & PFD_DRAW_TO_WINDOW) ? EGL_WINDOW_BIT : 0) |
+ ((getAttrib(WGL_DRAW_TO_PBUFFER_ARB) == TRUE) ? EGL_PBUFFER_BIT : 0) |
+ ((getAttrib(WGL_SWAP_METHOD_ARB) == WGL_SWAP_COPY_ARB) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT
+ : 0);
+ config.optimalOrientation = optimalSurfaceOrientation;
+
+ config.transparentType = EGL_NONE;
+ config.transparentRedValue = 0;
+ config.transparentGreenValue = 0;
+ config.transparentBlueValue = 0;
+
+ configs.add(config);
+
+ return configs;
+}
+
+bool DisplayWGL::testDeviceLost()
+{
+ if (mHasRobustness)
+ {
+ return getRenderer()->getResetStatus() != GL_NO_ERROR;
+ }
+
+ return false;
+}
+
+egl::Error DisplayWGL::restoreLostDevice()
+{
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+bool DisplayWGL::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return (IsWindow(window) == TRUE);
+}
+
+egl::Error DisplayWGL::validateClientBuffer(const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ switch (buftype)
+ {
+ case EGL_D3D_TEXTURE_ANGLE:
+ return D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(clientBuffer);
+
+ default:
+ return DisplayGL::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
+ }
+}
+
+std::string DisplayWGL::getVendorString() const
+{
+ //UNIMPLEMENTED();
+ return "";
+}
+
+const FunctionsGL *DisplayWGL::getFunctionsGL() const
+{
+ return mFunctionsGL;
+}
+
+egl::Error DisplayWGL::initializeD3DDevice()
+{
+ if (mD3D11Device != nullptr)
+ {
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
+ if (!mDxgiModule)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to load DXGI library.");
+ }
+
+ mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+ if (!mD3d11Module)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to load d3d11 library.");
+ }
+
+ PFN_D3D11_CREATE_DEVICE d3d11CreateDevice = nullptr;
+ d3d11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
+ GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
+ if (d3d11CreateDevice == nullptr)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not retrieve D3D11CreateDevice address.");
+ }
+
+ HRESULT result = d3d11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0,
+ D3D11_SDK_VERSION, &mD3D11Device, nullptr, nullptr);
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create D3D11 device, error: 0x%X",
+ result);
+ }
+
+ egl::Error error = registerD3DDevice(mD3D11Device, &mD3D11DeviceHandle);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayWGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ // Only enable the surface orientation and post sub buffer for DXGI swap chain surfaces, they
+ // prefer to swap with inverted Y.
+ outExtensions->postSubBuffer = mUseDXGISwapChains;
+ outExtensions->surfaceOrientation = mUseDXGISwapChains;
+
+ outExtensions->createContextRobustness = mHasRobustness;
+
+ outExtensions->d3dTextureClientBuffer = mFunctionsWGL->hasExtension("WGL_NV_DX_interop2");
+}
+
+void DisplayWGL::generateCaps(egl::Caps *outCaps) const
+{
+ outCaps->textureNPOT = true;
+}
+
+egl::Error DisplayWGL::waitClient() const
+{
+ // Unimplemented as this is not needed for WGL
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayWGL::waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const
+{
+ // Unimplemented as this is not needed for WGL
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayWGL::getDriverVersion(std::string *version) const
+{
+ *version = "";
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayWGL::registerD3DDevice(IUnknown *device, HANDLE *outHandle)
+{
+ ASSERT(device != nullptr);
+ ASSERT(outHandle != nullptr);
+
+ auto iter = mRegisteredD3DDevices.find(device);
+ if (iter != mRegisteredD3DDevices.end())
+ {
+ iter->second.refCount++;
+ *outHandle = iter->second.handle;
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ HANDLE handle = mFunctionsWGL->dxOpenDeviceNV(device);
+ if (!handle)
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "Failed to open D3D device.");
+ }
+
+ device->AddRef();
+
+ D3DObjectHandle newDeviceInfo;
+ newDeviceInfo.handle = handle;
+ newDeviceInfo.refCount = 1;
+ mRegisteredD3DDevices[device] = newDeviceInfo;
+
+ *outHandle = handle;
+ return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayWGL::releaseD3DDevice(HANDLE deviceHandle)
+{
+ for (auto iter = mRegisteredD3DDevices.begin(); iter != mRegisteredD3DDevices.end(); iter++)
+ {
+ if (iter->second.handle == deviceHandle)
+ {
+ iter->second.refCount--;
+ if (iter->second.refCount == 0)
+ {
+ mFunctionsWGL->dxCloseDeviceNV(iter->second.handle);
+ iter->first->Release();
+ mRegisteredD3DDevices.erase(iter);
+ break;
+ }
+ }
+ }
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h
new file mode 100755
index 000000000..509ea9b39
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h
@@ -0,0 +1,112 @@
+//
+// Copyright (c) 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.
+//
+
+// DisplayWGL.h: WGL implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_DISPLAYWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_DISPLAYWGL_H_
+
+#include "libANGLE/renderer/gl/DisplayGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsWGL;
+
+class DisplayWGL : public DisplayGL
+{
+ public:
+ DisplayWGL();
+ ~DisplayWGL() override;
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ // Surface creation
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() 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 getDevice(DeviceImpl **device) override;
+
+ std::string getVendorString() const override;
+
+ egl::Error waitClient() const override;
+ egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const override;
+
+ egl::Error getDriverVersion(std::string *version) const override;
+
+ egl::Error registerD3DDevice(IUnknown *device, HANDLE *outHandle);
+ void releaseD3DDevice(HANDLE handle);
+
+ private:
+ const FunctionsGL *getFunctionsGL() const override;
+
+ egl::Error initializeD3DDevice();
+
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+ void generateCaps(egl::Caps *outCaps) const override;
+
+ HMODULE mOpenGLModule;
+
+ FunctionsWGL *mFunctionsWGL;
+ FunctionsGL *mFunctionsGL;
+
+ bool mHasRobustness;
+
+ ATOM mWindowClass;
+ HWND mWindow;
+ HDC mDeviceContext;
+ int mPixelFormat;
+ HGLRC mWGLContext;
+
+ bool mUseDXGISwapChains;
+ HMODULE mDxgiModule;
+ HMODULE mD3d11Module;
+ HANDLE mD3D11DeviceHandle;
+ ID3D11Device *mD3D11Device;
+
+ struct D3DObjectHandle
+ {
+ HANDLE handle;
+ size_t refCount;
+ };
+ std::map<IUnknown *, D3DObjectHandle> mRegisteredD3DDevices;
+
+ egl::Display *mDisplay;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_DISPLAYWGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp
new file mode 100755
index 000000000..2cfe6e9eb
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp
@@ -0,0 +1,181 @@
+//
+// Copyright (c) 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.
+//
+
+// FunctionsWGL.h: Implements the FuntionsWGL class.
+
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+
+#include <algorithm>
+
+#include "common/string_utils.h"
+
+namespace rx
+{
+
+template <typename T>
+static void GetWGLProcAddress(HMODULE glModule, PFNWGLGETPROCADDRESSPROC getProcAddressWGL,
+ const std::string &procName, T *outProcAddress)
+{
+ T proc = nullptr;
+ if (getProcAddressWGL)
+ {
+ proc = reinterpret_cast<T>(getProcAddressWGL(procName.c_str()));
+ }
+
+ if (!proc)
+ {
+ proc = reinterpret_cast<T>(GetProcAddress(glModule, procName.c_str()));
+ }
+
+ *outProcAddress = proc;
+}
+
+template <typename T>
+static void GetWGLExtensionProcAddress(HMODULE glModule,
+ PFNWGLGETPROCADDRESSPROC getProcAddressWGL,
+ const std::vector<std::string> &extensions,
+ const std::string &extensionName,
+ const std::string &procName,
+ T *outProcAddress)
+{
+ T proc = nullptr;
+ if (std::find(extensions.begin(), extensions.end(), extensionName) != extensions.end())
+ {
+ GetWGLProcAddress(glModule, getProcAddressWGL, procName, &proc);
+ }
+
+ *outProcAddress = proc;
+}
+
+FunctionsWGL::FunctionsWGL()
+ : copyContext(nullptr),
+ createContext(nullptr),
+ createLayerContext(nullptr),
+ deleteContext(nullptr),
+ getCurrentContext(nullptr),
+ getCurrentDC(nullptr),
+ getProcAddress(nullptr),
+ makeCurrent(nullptr),
+ shareLists(nullptr),
+ useFontBitmapsA(nullptr),
+ useFontBitmapsW(nullptr),
+ swapBuffers(nullptr),
+ useFontOutlinesA(nullptr),
+ useFontOutlinesW(nullptr),
+ describeLayerPlane(nullptr),
+ setLayerPaletteEntries(nullptr),
+ getLayerPaletteEntries(nullptr),
+ realizeLayerPalette(nullptr),
+ swapLayerBuffers(nullptr),
+ swapMultipleBuffers(nullptr),
+ getExtensionStringEXT(nullptr),
+ getExtensionStringARB(nullptr),
+ createContextAttribsARB(nullptr),
+ getPixelFormatAttribivARB(nullptr),
+ getPixelFormatAttribfvARB(nullptr),
+ choosePixelFormatARB(nullptr),
+ swapIntervalEXT(nullptr),
+ createPbufferARB(nullptr),
+ getPbufferDCARB(nullptr),
+ releasePbufferDCARB(nullptr),
+ destroyPbufferARB(nullptr),
+ queryPbufferARB(nullptr),
+ bindTexImageARB(nullptr),
+ releaseTexImageARB(nullptr),
+ setPbufferAttribARB(nullptr),
+ dxSetResourceShareHandleNV(nullptr),
+ dxOpenDeviceNV(nullptr),
+ dxCloseDeviceNV(nullptr),
+ dxRegisterObjectNV(nullptr),
+ dxUnregisterObjectNV(nullptr),
+ dxObjectAccessNV(nullptr),
+ dxLockObjectsNV(nullptr),
+ dxUnlockObjectsNV(nullptr)
+{
+}
+
+void FunctionsWGL::initialize(HMODULE glModule, HDC context)
+{
+ // First grab the wglGetProcAddress function from the gl module
+ GetWGLProcAddress(glModule, nullptr, "wglGetProcAddress", &getProcAddress);
+
+ // Load the core wgl functions
+ GetWGLProcAddress(glModule, getProcAddress, "wglCopyContext", &copyContext);
+ GetWGLProcAddress(glModule, getProcAddress, "wglCreateContext", &createContext);
+ GetWGLProcAddress(glModule, getProcAddress, "wglCreateLayerContext", &createLayerContext);
+ GetWGLProcAddress(glModule, getProcAddress, "wglDeleteContext", &deleteContext);
+ GetWGLProcAddress(glModule, getProcAddress, "wglGetCurrentContext", &getCurrentContext);
+ GetWGLProcAddress(glModule, getProcAddress, "wglGetCurrentDC", &getCurrentDC);
+ GetWGLProcAddress(glModule, getProcAddress, "wglMakeCurrent", &makeCurrent);
+ GetWGLProcAddress(glModule, getProcAddress, "wglShareLists", &shareLists);
+ GetWGLProcAddress(glModule, getProcAddress, "wglUseFontBitmapsA", &useFontBitmapsA);
+ GetWGLProcAddress(glModule, getProcAddress, "wglUseFontBitmapsW", &useFontBitmapsW);
+ swapBuffers = SwapBuffers; // SwapBuffers is statically linked from GDI
+ GetWGLProcAddress(glModule, getProcAddress, "wglUseFontOutlinesA", &useFontOutlinesA);
+ GetWGLProcAddress(glModule, getProcAddress, "wglUseFontOutlinesW", &useFontOutlinesW);
+ GetWGLProcAddress(glModule, getProcAddress, "wglDescribeLayerPlane", &describeLayerPlane);
+ GetWGLProcAddress(glModule, getProcAddress, "wglSetLayerPaletteEntries", &setLayerPaletteEntries);
+ GetWGLProcAddress(glModule, getProcAddress, "wglGetLayerPaletteEntries", &getLayerPaletteEntries);
+ GetWGLProcAddress(glModule, getProcAddress, "wglRealizeLayerPalette", &realizeLayerPalette);
+ GetWGLProcAddress(glModule, getProcAddress, "wglSwapLayerBuffers", &swapLayerBuffers);
+ GetWGLProcAddress(glModule, getProcAddress, "wglSwapMultipleBuffers", &swapMultipleBuffers);
+
+ // Load extension string getter functions
+ GetWGLProcAddress(glModule, getProcAddress, "wglGetExtensionsStringEXT", &getExtensionStringEXT);
+ GetWGLProcAddress(glModule, getProcAddress, "wglGetExtensionsStringARB", &getExtensionStringARB);
+
+ std::string extensionString = "";
+ if (getExtensionStringEXT)
+ {
+ extensionString = getExtensionStringEXT();
+ }
+ else if (getExtensionStringARB && context)
+ {
+ extensionString = getExtensionStringARB(context);
+ }
+ angle::SplitStringAlongWhitespace(extensionString, &extensions);
+
+ // Load the wgl extension functions by checking if the context supports the extension first
+
+ // WGL_ARB_create_context
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_create_context", "wglCreateContextAttribsARB", &createContextAttribsARB);
+
+ // WGL_ARB_pixel_format
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pixel_format", "wglGetPixelFormatAttribivARB", &getPixelFormatAttribivARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pixel_format", "wglGetPixelFormatAttribfvARB", &getPixelFormatAttribfvARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pixel_format", "wglChoosePixelFormatARB", &choosePixelFormatARB);
+
+ // WGL_EXT_swap_control
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_EXT_swap_control", "wglSwapIntervalEXT", &swapIntervalEXT);
+
+ // WGL_ARB_pbuffer
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglCreatePbufferARB", &createPbufferARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglGetPbufferDCARB", &getPbufferDCARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglReleasePbufferDCARB", &releasePbufferDCARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglDestroyPbufferARB", &destroyPbufferARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglQueryPbufferARB", &queryPbufferARB);
+
+ // WGL_ARB_render_texture
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglBindTexImageARB", &bindTexImageARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglReleaseTexImageARB", &releaseTexImageARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglSetPbufferAttribARB", &setPbufferAttribARB);
+
+ // WGL_NV_DX_interop
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXSetResourceShareHandleNV", &dxSetResourceShareHandleNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXOpenDeviceNV", &dxOpenDeviceNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXCloseDeviceNV", &dxCloseDeviceNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXRegisterObjectNV", &dxRegisterObjectNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXUnregisterObjectNV", &dxUnregisterObjectNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXObjectAccessNV", &dxObjectAccessNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXLockObjectsNV", &dxLockObjectsNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXUnlockObjectsNV", &dxUnlockObjectsNV);
+}
+
+bool FunctionsWGL::hasExtension(const std::string &ext) const
+{
+ return std::find(extensions.begin(), extensions.end(), ext) != extensions.end();
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h
new file mode 100755
index 000000000..30cf9ebc0
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 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.
+//
+
+// FunctionsWGL.h: Defines the FuntionsWGL class to contain loaded WGL functions
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL
+#define LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/gl/wgl/functionswgl_typedefs.h"
+
+namespace rx
+{
+
+class FunctionsWGL : angle::NonCopyable
+{
+ public:
+ FunctionsWGL();
+
+ // Loads all available wgl functions, may be called multiple times
+ void initialize(HMODULE glModule, HDC context);
+
+ // Extension information
+ std::vector<std::string> extensions;
+ bool hasExtension(const std::string &ext) const;
+
+ // Base WGL functions
+ PFNWGLCOPYCONTEXTPROC copyContext;
+ PFNWGLCREATECONTEXTPROC createContext;
+ PFNWGLCREATELAYERCONTEXTPROC createLayerContext;
+ PFNWGLDELETECONTEXTPROC deleteContext;
+ PFNWGLGETCURRENTCONTEXTPROC getCurrentContext;
+ PFNWGLGETCURRENTDCPROC getCurrentDC;
+ PFNWGLGETPROCADDRESSPROC getProcAddress;
+ PFNWGLMAKECURRENTPROC makeCurrent;
+ PFNWGLSHARELISTSPROC shareLists;
+ PFNWGLUSEFONTBITMAPSAPROC useFontBitmapsA;
+ PFNWGLUSEFONTBITMAPSWPROC useFontBitmapsW;
+ PFNSWAPBUFFERSPROC swapBuffers;
+ PFNWGLUSEFONTOUTLINESAPROC useFontOutlinesA;
+ PFNWGLUSEFONTOUTLINESWPROC useFontOutlinesW;
+ PFNWGLDESCRIBELAYERPLANEPROC describeLayerPlane;
+ PFNWGLSETLAYERPALETTEENTRIESPROC setLayerPaletteEntries;
+ PFNWGLGETLAYERPALETTEENTRIESPROC getLayerPaletteEntries;
+ PFNWGLREALIZELAYERPALETTEPROC realizeLayerPalette;
+ PFNWGLSWAPLAYERBUFFERSPROC swapLayerBuffers;
+ PFNWGLSWAPMULTIPLEBUFFERSPROC swapMultipleBuffers;
+
+ // WGL_EXT_extensions_string
+ PFNWGLGETEXTENSIONSSTRINGEXTPROC getExtensionStringEXT;
+
+ // WGL_ARB_extensions_string
+ PFNWGLGETEXTENSIONSSTRINGARBPROC getExtensionStringARB;
+
+ // WGL_ARB_create_context
+ PFNWGLCREATECONTEXTATTRIBSARBPROC createContextAttribsARB;
+
+ // WGL_ARB_pixel_format
+ PFNWGLGETPIXELFORMATATTRIBIVARBPROC getPixelFormatAttribivARB;
+ PFNWGLGETPIXELFORMATATTRIBFVARBPROC getPixelFormatAttribfvARB;
+ PFNWGLCHOOSEPIXELFORMATARBPROC choosePixelFormatARB;
+
+ // WGL_EXT_swap_control
+ PFNWGLSWAPINTERVALEXTPROC swapIntervalEXT;
+
+ // WGL_ARB_pbuffer
+ PFNWGLCREATEPBUFFERARBPROC createPbufferARB;
+ PFNWGLGETPBUFFERDCARBPROC getPbufferDCARB;
+ PFNWGLRELEASEPBUFFERDCARBPROC releasePbufferDCARB;
+ PFNWGLDESTROYPBUFFERARBPROC destroyPbufferARB;
+ PFNWGLQUERYPBUFFERARBPROC queryPbufferARB;
+
+ // WGL_ARB_render_texture
+ PFNWGLBINDTEXIMAGEARBPROC bindTexImageARB;
+ PFNWGLRELEASETEXIMAGEARBPROC releaseTexImageARB;
+ PFNWGLSETPBUFFERATTRIBARBPROC setPbufferAttribARB;
+
+ // WGL_NV_DX_interop
+ PFNWGLDXSETRESOURCESHAREHANDLENVPROC dxSetResourceShareHandleNV;
+ PFNWGLDXOPENDEVICENVPROC dxOpenDeviceNV;
+ PFNWGLDXCLOSEDEVICENVPROC dxCloseDeviceNV;
+ PFNWGLDXREGISTEROBJECTNVPROC dxRegisterObjectNV;
+ PFNWGLDXUNREGISTEROBJECTNVPROC dxUnregisterObjectNV;
+ PFNWGLDXOBJECTACCESSNVPROC dxObjectAccessNV;
+ PFNWGLDXLOCKOBJECTSNVPROC dxLockObjectsNV;
+ PFNWGLDXUNLOCKOBJECTSNVPROC dxUnlockObjectsNV;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp
new file mode 100755
index 000000000..f2c503616
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp
@@ -0,0 +1,196 @@
+//
+// Copyright (c) 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.
+//
+
+// SurfaceWGL.cpp: WGL implementation of egl::Surface
+
+#include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
+
+namespace rx
+{
+
+PbufferSurfaceWGL::PbufferSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLint width,
+ EGLint height,
+ EGLenum textureFormat,
+ EGLenum textureTarget,
+ bool largest,
+ int pixelFormat,
+ HDC deviceContext,
+ HGLRC wglContext,
+ const FunctionsWGL *functions)
+ : SurfaceGL(state, renderer),
+ mWidth(width),
+ mHeight(height),
+ mLargest(largest),
+ mTextureFormat(textureFormat),
+ mTextureTarget(textureTarget),
+ mPixelFormat(pixelFormat),
+ mShareWGLContext(wglContext),
+ mParentDeviceContext(deviceContext),
+ mPbuffer(nullptr),
+ mPbufferDeviceContext(nullptr),
+ mFunctionsWGL(functions)
+{
+}
+
+PbufferSurfaceWGL::~PbufferSurfaceWGL()
+{
+ mFunctionsWGL->releasePbufferDCARB(mPbuffer, mPbufferDeviceContext);
+ mPbufferDeviceContext = nullptr;
+
+ mFunctionsWGL->destroyPbufferARB(mPbuffer);
+ mPbuffer = nullptr;
+}
+
+static int GetWGLTextureType(EGLenum eglTextureType)
+{
+ switch (eglTextureType)
+ {
+ case EGL_NO_TEXTURE: return WGL_NO_TEXTURE_ARB;
+ case EGL_TEXTURE_RGB: return WGL_TEXTURE_RGB_ARB;
+ case EGL_TEXTURE_RGBA: return WGL_TEXTURE_RGBA_ARB;
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+static int GetWGLTextureTarget(EGLenum eglTextureTarget)
+{
+ switch (eglTextureTarget)
+ {
+ case EGL_NO_TEXTURE: return WGL_NO_TEXTURE_ARB;
+ case EGL_TEXTURE_2D: return WGL_TEXTURE_2D_ARB;
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+egl::Error PbufferSurfaceWGL::initialize()
+{
+ const int pbufferCreationAttributes[] =
+ {
+ WGL_PBUFFER_LARGEST_ARB, mLargest ? 1 : 0,
+ WGL_TEXTURE_FORMAT_ARB, GetWGLTextureType(mTextureFormat),
+ WGL_TEXTURE_TARGET_ARB, GetWGLTextureTarget(mTextureTarget),
+ 0, 0,
+ };
+
+ mPbuffer = mFunctionsWGL->createPbufferARB(mParentDeviceContext, mPixelFormat, mWidth, mHeight,
+ pbufferCreationAttributes);
+ if (mPbuffer == nullptr)
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to create a native WGL pbuffer, error: 0x%08x.", HRESULT_CODE(error));
+ }
+
+ // The returned pbuffer may not be as large as requested, update the size members.
+ if (mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_WIDTH_ARB, &mWidth) != TRUE ||
+ mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_HEIGHT_ARB, &mHeight) != TRUE)
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to query the WGL pbuffer's dimensions, error: 0x%08x.", HRESULT_CODE(error));
+ }
+
+ mPbufferDeviceContext = mFunctionsWGL->getPbufferDCARB(mPbuffer);
+ if (mPbufferDeviceContext == nullptr)
+ {
+ mFunctionsWGL->destroyPbufferARB(mPbuffer);
+ mPbuffer = nullptr;
+
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to get the WGL pbuffer handle, error: 0x%08x.", HRESULT_CODE(error));
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::makeCurrent()
+{
+ if (!mFunctionsWGL->makeCurrent(mPbufferDeviceContext, mShareWGLContext))
+ {
+ // TODO: What error type here?
+ return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::swap()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+static int GetWGLBufferBindTarget(EGLint buffer)
+{
+ switch (buffer)
+ {
+ case EGL_BACK_BUFFER: return WGL_BACK_LEFT_ARB;
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+egl::Error PbufferSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ if (!mFunctionsWGL->bindTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_SURFACE, "Failed to bind native wgl pbuffer, error: 0x%08x.", HRESULT_CODE(error));
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::releaseTexImage(EGLint buffer)
+{
+ if (!mFunctionsWGL->releaseTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_SURFACE, "Failed to unbind native wgl pbuffer, error: 0x%08x.", HRESULT_CODE(error));
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+void PbufferSurfaceWGL::setSwapInterval(EGLint interval)
+{
+}
+
+EGLint PbufferSurfaceWGL::getWidth() const
+{
+ return mWidth;
+}
+
+EGLint PbufferSurfaceWGL::getHeight() const
+{
+ return mHeight;
+}
+
+EGLint PbufferSurfaceWGL::isPostSubBufferSupported() const
+{
+ return EGL_FALSE;
+}
+
+EGLint PbufferSurfaceWGL::getSwapBehavior() const
+{
+ return EGL_BUFFER_PRESERVED;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h
new file mode 100755
index 000000000..56235293a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 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.
+//
+
+// PBufferSurfaceWGL.h: WGL implementation of egl::Surface for PBuffers
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_PBUFFERSURFACEWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_PBUFFERSURFACEWGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsWGL;
+
+class PbufferSurfaceWGL : public SurfaceGL
+{
+ public:
+ PbufferSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLint width,
+ EGLint height,
+ EGLenum textureFormat,
+ EGLenum textureTarget,
+ bool largest,
+ int pixelFormat,
+ HDC deviceContext,
+ HGLRC wglContext,
+ const FunctionsWGL *functions);
+ ~PbufferSurfaceWGL() override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ private:
+ EGLint mWidth;
+ EGLint mHeight;
+ bool mLargest;
+ EGLenum mTextureFormat;
+ EGLenum mTextureTarget;
+
+ int mPixelFormat;
+
+ HGLRC mShareWGLContext;
+
+ HDC mParentDeviceContext;
+
+ HPBUFFERARB mPbuffer;
+ HDC mPbufferDeviceContext;
+
+ const FunctionsWGL *mFunctionsWGL;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_PBUFFERSURFACEWGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp
new file mode 100755
index 000000000..f22943acb
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp
@@ -0,0 +1,178 @@
+//
+// Copyright (c) 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.
+//
+
+// WindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows
+
+#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
+
+namespace rx
+{
+
+WindowSurfaceWGL::WindowSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLNativeWindowType window,
+ int pixelFormat,
+ HGLRC wglContext,
+ const FunctionsWGL *functions,
+ EGLint orientation)
+ : SurfaceGL(state, renderer),
+ mPixelFormat(pixelFormat),
+ mWGLContext(wglContext),
+ mWindow(window),
+ mDeviceContext(nullptr),
+ mFunctionsWGL(functions),
+ mSwapBehavior(0)
+{
+ // EGL_ANGLE_surface_orientation is not supported for regular WGL window surfaces
+ ASSERT(orientation == 0);
+}
+
+WindowSurfaceWGL::~WindowSurfaceWGL()
+{
+ ReleaseDC(mWindow, mDeviceContext);
+ mDeviceContext = nullptr;
+}
+
+egl::Error WindowSurfaceWGL::initialize()
+{
+ mDeviceContext = GetDC(mWindow);
+ if (!mDeviceContext)
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the device context from the native window, "
+ "error: 0x%X.", GetLastError());
+ }
+
+ // Require that the pixel format for this window has not been set yet or is equal to the Display's pixel format.
+ int windowPixelFormat = GetPixelFormat(mDeviceContext);
+ if (windowPixelFormat == 0)
+ {
+ PIXELFORMATDESCRIPTOR pixelFormatDescriptor = { 0 };
+ if (!DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor), &pixelFormatDescriptor))
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to DescribePixelFormat, error: 0x%X.", GetLastError());
+ }
+
+ if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the device context, "
+ "error: 0x%X.", GetLastError());
+ }
+ }
+ else if (windowPixelFormat != mPixelFormat)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Pixel format of the NativeWindow and NativeDisplayType must match.");
+ }
+
+ // Check for the swap behavior of this pixel format
+ switch (
+ wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, WGL_SWAP_METHOD_ARB, mFunctionsWGL))
+ {
+ case WGL_SWAP_COPY_ARB:
+ mSwapBehavior = EGL_BUFFER_PRESERVED;
+ break;
+
+ case WGL_SWAP_EXCHANGE_ARB:
+ case WGL_SWAP_UNDEFINED_ARB:
+ default:
+ mSwapBehavior = EGL_BUFFER_DESTROYED;
+ break;
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::makeCurrent()
+{
+ if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext))
+ {
+ // TODO: What error type here?
+ return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::swap()
+{
+ if (!mFunctionsWGL->swapBuffers(mDeviceContext))
+ {
+ // TODO: What error type here?
+ return egl::Error(EGL_CONTEXT_LOST, "Failed to swap buffers on the child window.");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::releaseTexImage(EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+void WindowSurfaceWGL::setSwapInterval(EGLint interval)
+{
+ if (mFunctionsWGL->swapIntervalEXT)
+ {
+ mFunctionsWGL->swapIntervalEXT(interval);
+ }
+}
+
+EGLint WindowSurfaceWGL::getWidth() const
+{
+ RECT rect;
+ if (!GetClientRect(mWindow, &rect))
+ {
+ return 0;
+ }
+ return rect.right - rect.left;
+}
+
+EGLint WindowSurfaceWGL::getHeight() const
+{
+ RECT rect;
+ if (!GetClientRect(mWindow, &rect))
+ {
+ return 0;
+ }
+ return rect.bottom - rect.top;
+}
+
+EGLint WindowSurfaceWGL::isPostSubBufferSupported() const
+{
+ // PostSubBuffer extension not exposed on WGL.
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLint WindowSurfaceWGL::getSwapBehavior() const
+{
+ return mSwapBehavior;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h
new file mode 100755
index 000000000..eb95e4dc2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 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.
+//
+
+// WindowSurfaceWGL.h: WGL implementation of egl::Surface for windows
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_WINDOWSURFACEWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_WINDOWSURFACEWGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsWGL;
+
+class WindowSurfaceWGL : public SurfaceGL
+{
+ public:
+ WindowSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLNativeWindowType window,
+ int pixelFormat,
+ HGLRC wglContext,
+ const FunctionsWGL *functions,
+ EGLint orientation);
+ ~WindowSurfaceWGL() override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ private:
+ int mPixelFormat;
+
+ HGLRC mWGLContext;
+
+ HWND mWindow;
+ HDC mDeviceContext;
+
+ const FunctionsWGL *mFunctionsWGL;
+
+ EGLint mSwapBehavior;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_WINDOWSURFACEWGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h
new file mode 100755
index 000000000..c4b79ee02
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 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.
+//
+
+// functionswgl_typedefs.h: Typedefs of WGL functions.
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_FUNCTIONSWGLTYPEDEFS_H_
+#define LIBANGLE_RENDERER_GL_WGL_FUNCTIONSWGLTYPEDEFS_H_
+
+#include "common/platform.h"
+
+#include <angle_gl.h>
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+typedef BOOL(WINAPI *PFNWGLCOPYCONTEXTPROC)(HGLRC, HGLRC, UINT);
+typedef HGLRC(WINAPI *PFNWGLCREATECONTEXTPROC)(HDC);
+typedef HGLRC(WINAPI *PFNWGLCREATELAYERCONTEXTPROC)(HDC, int);
+typedef BOOL(WINAPI *PFNWGLDELETECONTEXTPROC)(HGLRC);
+typedef HGLRC(WINAPI *PFNWGLGETCURRENTCONTEXTPROC)(VOID);
+typedef HDC(WINAPI *PFNWGLGETCURRENTDCPROC)(VOID);
+typedef PROC(WINAPI *PFNWGLGETPROCADDRESSPROC)(LPCSTR);
+typedef BOOL(WINAPI *PFNWGLMAKECURRENTPROC)(HDC, HGLRC);
+typedef BOOL(WINAPI *PFNWGLSHARELISTSPROC)(HGLRC, HGLRC);
+typedef BOOL(WINAPI *PFNWGLUSEFONTBITMAPSAPROC)(HDC, DWORD, DWORD, DWORD);
+typedef BOOL(WINAPI *PFNWGLUSEFONTBITMAPSWPROC)(HDC, DWORD, DWORD, DWORD);
+typedef BOOL(WINAPI *PFNSWAPBUFFERSPROC)(HDC);
+typedef BOOL(WINAPI *PFNWGLUSEFONTOUTLINESAPROC)(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT);
+typedef BOOL(WINAPI *PFNWGLUSEFONTOUTLINESWPROC)(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT);
+typedef BOOL(WINAPI *PFNWGLDESCRIBELAYERPLANEPROC)(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR);
+typedef int(WINAPI *PFNWGLSETLAYERPALETTEENTRIESPROC)(HDC, int, int, int, CONST COLORREF *);
+typedef int(WINAPI *PFNWGLGETLAYERPALETTEENTRIESPROC)(HDC, int, int, int, COLORREF *);
+typedef BOOL(WINAPI *PFNWGLREALIZELAYERPALETTEPROC)(HDC, int, BOOL);
+typedef BOOL(WINAPI *PFNWGLSWAPLAYERBUFFERSPROC)(HDC, UINT);
+typedef DWORD(WINAPI *PFNWGLSWAPMULTIPLEBUFFERSPROC)(UINT, CONST WGLSWAP *);
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_FUNCTIONSWGLTYPEDEFS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp
new file mode 100755
index 000000000..641c3fbc4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp
@@ -0,0 +1,85 @@
+//
+// Copyright (c) 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.
+//
+
+// wgl_utils.cpp: Utility routines specific to the WGL->EGL implementation.
+
+#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
+
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+
+namespace rx
+{
+
+namespace wgl
+{
+
+PIXELFORMATDESCRIPTOR GetDefaultPixelFormatDescriptor()
+{
+ PIXELFORMATDESCRIPTOR pixelFormatDescriptor = { 0 };
+ pixelFormatDescriptor.nSize = sizeof(pixelFormatDescriptor);
+ pixelFormatDescriptor.nVersion = 1;
+ pixelFormatDescriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_GENERIC_ACCELERATED | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+ pixelFormatDescriptor.iPixelType = PFD_TYPE_RGBA;
+ pixelFormatDescriptor.cColorBits = 24;
+ pixelFormatDescriptor.cAlphaBits = 8;
+ pixelFormatDescriptor.cDepthBits = 24;
+ pixelFormatDescriptor.cStencilBits = 8;
+ pixelFormatDescriptor.iLayerType = PFD_MAIN_PLANE;
+
+ return pixelFormatDescriptor;
+}
+
+std::vector<int> GetDefaultPixelFormatAttributes(bool preservedSwap)
+{
+ std::vector<int> attribs;
+ attribs.push_back(WGL_DRAW_TO_WINDOW_ARB);
+ attribs.push_back(TRUE);
+
+ attribs.push_back(WGL_ACCELERATION_ARB);
+ attribs.push_back(WGL_FULL_ACCELERATION_ARB);
+
+ attribs.push_back(WGL_SUPPORT_OPENGL_ARB);
+ attribs.push_back(TRUE);
+
+ attribs.push_back(WGL_DOUBLE_BUFFER_ARB);
+ attribs.push_back(TRUE);
+
+ attribs.push_back(WGL_PIXEL_TYPE_ARB);
+ attribs.push_back(WGL_TYPE_RGBA_ARB);
+
+ attribs.push_back(WGL_COLOR_BITS_ARB);
+ attribs.push_back(24);
+
+ attribs.push_back(WGL_ALPHA_BITS_ARB);
+ attribs.push_back(8);
+
+ attribs.push_back(WGL_DEPTH_BITS_ARB);
+ attribs.push_back(24);
+
+ attribs.push_back(WGL_STENCIL_BITS_ARB);
+ attribs.push_back(8);
+
+ attribs.push_back(WGL_SWAP_METHOD_ARB);
+ attribs.push_back(preservedSwap ? WGL_SWAP_COPY_ARB : WGL_SWAP_UNDEFINED_ARB);
+
+ attribs.push_back(0);
+
+ return attribs;
+}
+
+int QueryWGLFormatAttrib(HDC dc, int format, int attribName, const FunctionsWGL *functions)
+{
+ int result = 0;
+ if (functions->getPixelFormatAttribivARB == nullptr ||
+ !functions->getPixelFormatAttribivARB(dc, format, 0, 1, &attribName, &result))
+ {
+ return 0;
+ }
+ return result;
+}
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h
new file mode 100755
index 000000000..d4914b5d3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 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.
+//
+
+// wgl_utils.h: Utility routines specific to the WGL->EGL implementation.
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_WGLUTILS_H_
+#define LIBANGLE_RENDERER_GL_WGL_WGLUTILS_H_
+
+#include <vector>
+
+#include "common/platform.h"
+
+namespace rx
+{
+
+class FunctionsWGL;
+
+namespace wgl
+{
+
+PIXELFORMATDESCRIPTOR GetDefaultPixelFormatDescriptor();
+std::vector<int> GetDefaultPixelFormatAttributes(bool preservedSwap);
+
+int QueryWGLFormatAttrib(HDC dc, int format, int attribName, const FunctionsWGL *functions);
+}
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_WGLUTILS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/load_functions_data.json b/gfx/angle/src/libANGLE/renderer/load_functions_data.json
new file mode 100755
index 000000000..8145704d6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/load_functions_data.json
@@ -0,0 +1,562 @@
+{
+ "GL_RG8_SNORM": {
+ "R8G8_SNORM": {
+ "GL_BYTE": "LoadToNative<GLbyte, 2>"
+ }
+ },
+ "GL_SRGB8": {
+ "R8G8B8A8_UNORM_SRGB": {
+ "GL_UNSIGNED_BYTE": "LoadToNative3To4<GLubyte, 0xFF>"
+ }
+ },
+ "GL_RGBA8I": {
+ "R8G8B8A8_SINT": {
+ "GL_BYTE": "LoadToNative<GLbyte, 4>"
+ }
+ },
+ "GL_R8_SNORM": {
+ "R8_SNORM": {
+ "GL_BYTE": "LoadToNative<GLbyte, 1>"
+ }
+ },
+ "GL_RGBA8_SNORM": {
+ "R8G8B8A8_SNORM": {
+ "GL_BYTE": "LoadToNative<GLbyte, 4>"
+ }
+ },
+ "GL_R16I": {
+ "R16_SINT": {
+ "GL_SHORT": "LoadToNative<GLshort, 1>"
+ }
+ },
+ "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": {
+ "R8G8B8A8_UNORM_SRGB": {
+ "GL_UNSIGNED_BYTE": "LoadETC2SRGBA8ToSRGBA8"
+ }
+ },
+ "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadETC2RGB8A1ToRGBA8"
+ }
+ },
+ "GL_RGB32UI": {
+ "R32G32B32A32_UINT": {
+ "GL_UNSIGNED_INT": "LoadToNative3To4<GLuint, 0x00000001>"
+ }
+ },
+ "GL_ALPHA32F_EXT": {
+ "NONE": {
+ "GL_FLOAT": "LoadA32FToRGBA32F"
+ }
+ },
+ "GL_R16UI": {
+ "R16_UINT": {
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 1>"
+ }
+ },
+ "GL_RGB9_E5": {
+ "R9G9B9E5_SHAREDEXP": {
+ "GL_HALF_FLOAT": "LoadRGB16FToRGB9E5",
+ "GL_UNSIGNED_INT_5_9_9_9_REV": "LoadToNative<GLuint, 1>",
+ "GL_FLOAT": "LoadRGB32FToRGB9E5",
+ "GL_HALF_FLOAT_OES": "LoadRGB16FToRGB9E5"
+ }
+ },
+ "GL_COMPRESSED_R11_EAC": {
+ "R8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadEACR11ToR8"
+ }
+ },
+ "GL_RGBA32UI": {
+ "R32G32B32A32_UINT": {
+ "GL_UNSIGNED_INT": "LoadToNative<GLuint, 4>"
+ }
+ },
+ "GL_RG8UI": {
+ "R8G8_UINT": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 2>"
+ }
+ },
+ "GL_LUMINANCE32F_EXT": {
+ "NONE": {
+ "GL_FLOAT": "LoadL32FToRGBA32F"
+ }
+ },
+ "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": {
+ "R8G8B8A8_UNORM_SRGB": {
+ "GL_UNSIGNED_BYTE": "LoadETC2SRGB8A1ToRGBA8"
+ }
+ },
+ "GL_R16F": {
+ "R16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadToNative<GLhalf, 1>",
+ "GL_FLOAT": "Load32FTo16F<1>",
+ "GL_HALF_FLOAT_OES": "LoadToNative<GLhalf, 1>"
+ }
+ },
+ "GL_RGBA8UI": {
+ "R8G8B8A8_UINT": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+ }
+ },
+ "GL_BGRA4_ANGLEX": {
+ "NONE": {
+ "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT": "LoadRGBA4ToRGBA8",
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+ }
+ },
+ "GL_RGBA16F": {
+ "R16G16B16A16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadToNative<GLhalf, 4>",
+ "GL_FLOAT": "Load32FTo16F<4>",
+ "GL_HALF_FLOAT_OES": "LoadToNative<GLhalf, 4>"
+ }
+ },
+ "GL_LUMINANCE8_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadL8ToRGBA8"
+ }
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 16>"
+ }
+ },
+ "GL_RGB": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction",
+ "GL_UNSIGNED_SHORT_5_6_5": "UnreachableLoadFunction"
+ }
+ },
+ "GL_RGB5_A1": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_INT_2_10_10_10_REV": "LoadRGB10A2ToRGBA8",
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>",
+ "GL_UNSIGNED_SHORT_5_5_5_1": "LoadRGB5A1ToRGBA8"
+ },
+ "B5G5R5A1_UNORM": {
+ "GL_UNSIGNED_INT_2_10_10_10_REV": "LoadRGB10A2ToBGR5A1",
+ "GL_UNSIGNED_BYTE": "LoadRGBA8ToBGR5A1",
+ "GL_UNSIGNED_SHORT_5_5_5_1": "LoadRGB5A1ToA1RGB5"
+ }
+ },
+ "GL_RGB16UI": {
+ "R16G16B16A16_UINT": {
+ "GL_UNSIGNED_SHORT": "LoadToNative3To4<GLushort, 0x0001>"
+ }
+ },
+ "GL_BGRA_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction"
+ }
+ },
+ "GL_COMPRESSED_RGB8_ETC2": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadETC2RGB8ToRGBA8"
+ }
+ },
+ "GL_RGBA32F": {
+ "R32G32B32A32_FLOAT": {
+ "GL_FLOAT": "LoadToNative<GLfloat, 4>"
+ }
+ },
+ "GL_RGBA32I": {
+ "R32G32B32A32_SINT": {
+ "GL_INT": "LoadToNative<GLint, 4>"
+ }
+ },
+ "GL_LUMINANCE8_ALPHA8_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadLA8ToRGBA8"
+ }
+ },
+ "GL_RG8": {
+ "R8G8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 2>"
+ }
+ },
+ "GL_RGB10_A2": {
+ "R10G10B10A2_UNORM": {
+ "GL_UNSIGNED_INT_2_10_10_10_REV": "LoadToNative<GLuint, 1>"
+ }
+ },
+ "GL_COMPRESSED_SIGNED_RG11_EAC": {
+ "R8G8_SNORM": {
+ "GL_UNSIGNED_BYTE": "LoadEACRG11SToRG8"
+ }
+ },
+ "GL_DEPTH_COMPONENT16": {
+ "D16_UNORM": {
+ "GL_UNSIGNED_INT": "LoadR32ToR16",
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 1>"
+ }
+ },
+ "GL_RGB32I": {
+ "R32G32B32A32_SINT": {
+ "GL_INT": "LoadToNative3To4<GLint, 0x00000001>"
+ }
+ },
+ "GL_R8": {
+ "R8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 1>"
+ }
+ },
+ "GL_RGB32F": {
+ "R32G32B32A32_FLOAT": {
+ "GL_FLOAT": "LoadToNative3To4<GLfloat, gl::Float32One>"
+ }
+ },
+ "GL_R11F_G11F_B10F": {
+ "R11G11B10_FLOAT": {
+ "GL_UNSIGNED_INT_10F_11F_11F_REV": "LoadToNative<GLuint, 1>",
+ "GL_HALF_FLOAT": "LoadRGB16FToRG11B10F",
+ "GL_FLOAT": "LoadRGB32FToRG11B10F",
+ "GL_HALF_FLOAT_OES": "LoadRGB16FToRG11B10F"
+ }
+ },
+ "GL_RGB8": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative3To4<GLubyte, 0xFF>"
+ }
+ },
+ "GL_LUMINANCE_ALPHA": {
+ "R16G16B16A16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadLA16FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadLA16FToRGBA16F"
+ },
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction"
+ },
+ "R32G32B32A32_FLOAT": {
+ "GL_FLOAT": "LoadLA32FToRGBA32F"
+ }
+ },
+ "GL_RGBA16I": {
+ "R16G16B16A16_SINT": {
+ "GL_SHORT": "LoadToNative<GLshort, 4>"
+ }
+ },
+ "GL_R8I": {
+ "R8_SINT": {
+ "GL_BYTE": "LoadToNative<GLbyte, 1>"
+ }
+ },
+ "GL_RGB8_SNORM": {
+ "R8G8B8A8_SNORM": {
+ "GL_BYTE": "LoadToNative3To4<GLbyte, 0x7F>"
+ }
+ },
+ "GL_RG32F": {
+ "R32G32_FLOAT": {
+ "GL_FLOAT": "LoadToNative<GLfloat, 2>"
+ }
+ },
+ "GL_DEPTH_COMPONENT32F": {
+ "D32_FLOAT": {
+ "GL_FLOAT": "LoadD32FToD32F"
+ }
+ },
+ "GL_RG32I": {
+ "R32G32_SINT": {
+ "GL_INT": "LoadToNative<GLint, 2>"
+ }
+ },
+ "GL_ALPHA8_EXT": {
+ "A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 1>"
+ },
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadA8ToRGBA8"
+ }
+ },
+ "GL_RG32UI": {
+ "R32G32_UINT": {
+ "GL_UNSIGNED_INT": "LoadToNative<GLuint, 2>"
+ }
+ },
+ "GL_RGBA16UI": {
+ "R16G16B16A16_UINT": {
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 4>"
+ }
+ },
+ "GL_COMPRESSED_RGBA8_ETC2_EAC": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadETC2RGBA8ToRGBA8"
+ }
+ },
+ "GL_RGB8I": {
+ "R8G8B8A8_SINT": {
+ "GL_BYTE": "LoadToNative3To4<GLbyte, 0x01>"
+ }
+ },
+ "GL_COMPRESSED_SRGB8_ETC2": {
+ "R8G8B8A8_UNORM_SRGB": {
+ "GL_UNSIGNED_BYTE": "LoadETC2SRGB8ToRGBA8"
+ }
+ },
+ "GL_DEPTH32F_STENCIL8": {
+ "D32_FLOAT_S8X24_UINT": {
+ "GL_FLOAT_32_UNSIGNED_INT_24_8_REV": "LoadD32FS8X24ToD32FS8X24"
+ }
+ },
+ "GL_RG8I": {
+ "R8G8_SINT": {
+ "GL_BYTE": "LoadToNative<GLbyte, 2>"
+ }
+ },
+ "GL_R32UI": {
+ "R32_UINT": {
+ "GL_UNSIGNED_INT": "LoadToNative<GLuint, 1>"
+ }
+ },
+ "GL_BGR5_A1_ANGLEX": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>",
+ "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT": "LoadRGB5A1ToRGBA8"
+ }
+ },
+ "GL_BGR565_ANGLEX": {
+ "B5G6R5_UNORM": {
+ "GL_UNSIGNED_SHORT_5_6_5": "LoadRGB565ToBGR565",
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLushort, 1>"
+ }
+ },
+ "GL_COMPRESSED_RG11_EAC": {
+ "R8G8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadEACRG11ToRG8"
+ }
+ },
+ "GL_SRGB8_ALPHA8": {
+ "R8G8B8A8_UNORM_SRGB": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+ }
+ },
+ "GL_LUMINANCE_ALPHA16F_EXT": {
+ "NONE": {
+ "GL_HALF_FLOAT": "LoadLA16FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadLA16FToRGBA16F"
+ }
+ },
+ "GL_RGBA": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction",
+ "GL_UNSIGNED_SHORT_4_4_4_4": "UnreachableLoadFunction",
+ "GL_UNSIGNED_SHORT_5_5_5_1": "UnreachableLoadFunction"
+ }
+ },
+ "GL_DEPTH24_STENCIL8": {
+ "D24_UNORM_S8_UINT": {
+ "GL_UNSIGNED_INT_24_8": "LoadR32ToR24G8"
+ }
+ },
+ "GL_RGB16I": {
+ "R16G16B16A16_SINT": {
+ "GL_SHORT": "LoadToNative3To4<GLshort, 0x0001>"
+ }
+ },
+ "GL_R8UI": {
+ "R8_UINT": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 1>"
+ }
+ },
+ "GL_ALPHA": {
+ "R16G16B16A16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadA16FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadA16FToRGBA16F"
+ },
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction"
+ },
+ "R32G32B32A32_FLOAT": {
+ "GL_FLOAT": "LoadA32FToRGBA32F"
+ }
+ },
+ "GL_RGB16F": {
+ "R16G16B16A16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadToNative3To4<GLhalf, gl::Float16One>",
+ "GL_FLOAT": "LoadRGB32FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadToNative3To4<GLhalf, gl::Float16One>"
+ }
+ },
+ "GL_COMPRESSED_SIGNED_R11_EAC": {
+ "R8_SNORM": {
+ "GL_UNSIGNED_BYTE": "LoadEACR11SToR8"
+ }
+ },
+ "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 8>"
+ }
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 8>"
+ }
+ },
+ "GL_STENCIL_INDEX8": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnimplementedLoadFunction"
+ }
+ },
+ "GL_LUMINANCE_ALPHA32F_EXT": {
+ "NONE": {
+ "GL_FLOAT": "LoadLA32FToRGBA32F"
+ }
+ },
+ "GL_RGB8UI": {
+ "R8G8B8A8_UINT": {
+ "GL_UNSIGNED_BYTE": "LoadToNative3To4<GLubyte, 0x01>"
+ }
+ },
+ "GL_DEPTH_COMPONENT24": {
+ "D24_UNORM_S8_UINT": {
+ "GL_UNSIGNED_INT": "LoadR32ToR24G8"
+ }
+ },
+ "GL_R32I": {
+ "R32_SINT": {
+ "GL_INT": "LoadToNative<GLint, 1>"
+ }
+ },
+ "GL_DEPTH_COMPONENT32_OES": {
+ "NONE": {
+ "GL_UNSIGNED_INT": "LoadR32ToR24G8"
+ }
+ },
+ "GL_R32F": {
+ "R32_FLOAT": {
+ "GL_FLOAT": "LoadToNative<GLfloat, 1>"
+ }
+ },
+ "GL_RG16F": {
+ "R16G16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadToNative<GLhalf, 2>",
+ "GL_FLOAT": "Load32FTo16F<2>",
+ "GL_HALF_FLOAT_OES": "LoadToNative<GLhalf, 2>"
+ }
+ },
+ "GL_RGB565": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative3To4<GLubyte, 0xFF>",
+ "GL_UNSIGNED_SHORT_5_6_5": "LoadR5G6B5ToRGBA8"
+ },
+ "B5G6R5_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadRGB8ToBGR565",
+ "GL_UNSIGNED_SHORT_5_6_5": "LoadToNative<GLushort, 1>"
+ }
+ },
+ "GL_LUMINANCE16F_EXT": {
+ "NONE": {
+ "GL_HALF_FLOAT": "LoadL16FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadL16FToRGBA16F"
+ }
+ },
+ "GL_RG16UI": {
+ "R16G16_UINT": {
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 2>"
+ }
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 16>"
+ }
+ },
+ "GL_RG16I": {
+ "R16G16_SINT": {
+ "GL_SHORT": "LoadToNative<GLshort, 2>"
+ }
+ },
+ "GL_BGRA8_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+ }
+ },
+ "GL_ALPHA16F_EXT": {
+ "NONE": {
+ "GL_HALF_FLOAT": "LoadA16FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadA16FToRGBA16F"
+ }
+ },
+ "GL_RGBA4": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>",
+ "GL_UNSIGNED_SHORT_4_4_4_4": "LoadRGBA4ToRGBA8"
+ },
+ "B4G4R4A4_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadRGBA8ToBGRA4",
+ "GL_UNSIGNED_SHORT_4_4_4_4": "LoadRGBA4ToARGB4"
+ }
+ },
+ "GL_RGBA8": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+ }
+ },
+ "GL_LUMINANCE": {
+ "R16G16B16A16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadL16FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadL16FToRGBA16F"
+ },
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction"
+ },
+ "R32G32B32A32_FLOAT": {
+ "GL_FLOAT": "LoadL32FToRGBA32F"
+ }
+ },
+ "GL_RGB10_A2UI": {
+ "R10G10B10A2_UINT": {
+ "GL_UNSIGNED_INT_2_10_10_10_REV": "LoadToNative<GLuint, 1>"
+ }
+ },
+ "GL_ETC1_RGB8_OES": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadETC1RGB8ToRGBA8"
+ }
+ },
+ "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": {
+ "BC1_RGB_UNORM_BLOCK": {
+ "GL_UNSIGNED_BYTE": "LoadETC1RGB8ToBC1"
+ }
+ },
+ "GL_R16_EXT": {
+ "R16_UNORM": {
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 1>"
+ }
+ },
+ "GL_RG16_EXT": {
+ "R16G16_UNORM": {
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 2>"
+ }
+ },
+ "GL_RGB16_EXT": {
+ "R16G16B16A16_UNORM": {
+ "GL_UNSIGNED_SHORT": "LoadToNative3To4<GLushort, 0xFFFF>"
+ }
+ },
+ "GL_RGBA16_EXT": {
+ "R16G16B16A16_UNORM": {
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 4>"
+ }
+ },
+ "GL_R16_SNORM_EXT": {
+ "R16_SNORM": {
+ "GL_SHORT": "LoadToNative<GLushort, 1>"
+ }
+ },
+ "GL_RG16_SNORM_EXT": {
+ "R16G16_SNORM": {
+ "GL_SHORT": "LoadToNative<GLushort, 2>"
+ }
+ },
+ "GL_RGB16_SNORM_EXT": {
+ "R16G16B16A16_SNORM": {
+ "GL_SHORT": "LoadToNative3To4<GLushort, 0x7FFF>"
+ }
+ },
+ "GL_RGBA16_SNORM_EXT": {
+ "R16G16B16A16_SNORM": {
+ "GL_SHORT": "LoadToNative<GLushort, 4>"
+ }
+ }
+}
diff --git a/gfx/angle/src/libANGLE/renderer/load_functions_table.h b/gfx/angle/src/libANGLE/renderer/load_functions_table.h
new file mode 100755
index 000000000..f3da31c10
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/load_functions_table.h
@@ -0,0 +1,22 @@
+//
+// 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, Format::ID angleFormat);
+
+} // namespace angle
+
+#endif // LIBANGLE_RENDERER_LOADFUNCTIONSTABLE_H_
diff --git a/gfx/angle/src/libANGLE/renderer/load_functions_table_autogen.cpp b/gfx/angle/src/libANGLE/renderer/load_functions_table_autogen.cpp
new file mode 100755
index 000000000..c93f87385
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/load_functions_table_autogen.cpp
@@ -0,0 +1,2311 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_load_functions_table.py using data from load_functions_data.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.
+//
+// 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 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_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_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 BGR565_ANGLEX_to_B5G6R5_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ 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(LoadToNative<GLubyte, 4>, false);
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ return LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true);
+ 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 BGRA_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_R11_EAC_to_R8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACR11ToR8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RG11_EAC_to_R8G8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACRG11ToRG8, 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_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_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_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 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, 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, 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, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_R11_EAC_to_R8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACR11SToR8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_RG11_EAC_to_R8G8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACRG11SToRG8, 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_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2SRGB8ToRGBA8, 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 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 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_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_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_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_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC1RGB8ToRGBA8, 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_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_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadL32FToRGBA32F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE8_ALPHA8_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadLA8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE8_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadL8ToRGBA8, true);
+ 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_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_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadLA32FToRGBA32F, 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 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 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 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 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 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 RGB16I_to_R16G16B16A16_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLshort, 0x0001>, true);
+ 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 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_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 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 RGB32I_to_R32G32B32A32_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_INT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLint, 0x00000001>, true);
+ 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 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_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_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_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 RGB8I_to_R8G8B8A8_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLbyte, 0x01>, true);
+ 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 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 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 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_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 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_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_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnimplementedLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+} // namespace
+
+LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, Format::ID angleFormat)
+{
+ // clang-format off
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_FLOAT:
+ return ALPHA_to_R16G16B16A16_FLOAT;
+ case Format::ID::R32G32B32A32_FLOAT:
+ return ALPHA_to_R32G32B32A32_FLOAT;
+ default:
+ return ALPHA_to_default;
+ }
+ }
+ case GL_ALPHA16F_EXT:
+ return ALPHA16F_EXT_to_default;
+ case GL_ALPHA32F_EXT:
+ return ALPHA32F_EXT_to_default;
+ case GL_ALPHA8_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::A8_UNORM:
+ return ALPHA8_EXT_to_A8_UNORM;
+ case Format::ID::R8G8B8A8_UNORM:
+ return ALPHA8_EXT_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_BGR565_ANGLEX:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::B5G6R5_UNORM:
+ return BGR565_ANGLEX_to_B5G6R5_UNORM;
+ default:
+ 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_BGRA_EXT:
+ return BGRA_EXT_to_default;
+ case GL_COMPRESSED_R11_EAC:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8_UNORM:
+ return COMPRESSED_R11_EAC_to_R8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RG11_EAC:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8_UNORM:
+ return COMPRESSED_RG11_EAC_to_R8G8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGB8_ETC2:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGB8_ETC2_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA8_ETC2_EAC_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ 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_S3TC_DXT1_EXT:
+ return COMPRESSED_RGB_S3TC_DXT1_EXT_to_default;
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8_SNORM:
+ return COMPRESSED_SIGNED_R11_EAC_to_R8_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8_SNORM:
+ return COMPRESSED_SIGNED_RG11_EAC_to_R8G8_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ETC2_EAC_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ETC2:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ETC2_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH24_STENCIL8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::D24_UNORM_S8_UINT:
+ return DEPTH24_STENCIL8_to_D24_UNORM_S8_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH32F_STENCIL8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::D32_FLOAT_S8X24_UINT:
+ return DEPTH32F_STENCIL8_to_D32_FLOAT_S8X24_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT16:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::D16_UNORM:
+ return DEPTH_COMPONENT16_to_D16_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT24:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::D24_UNORM_S8_UINT:
+ return DEPTH_COMPONENT24_to_D24_UNORM_S8_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT32F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::D32_FLOAT:
+ return DEPTH_COMPONENT32F_to_D32_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT32_OES:
+ return DEPTH_COMPONENT32_OES_to_default;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::BC1_RGB_UNORM_BLOCK:
+ return ETC1_RGB8_LOSSY_DECODE_ANGLE_to_BC1_RGB_UNORM_BLOCK;
+ default:
+ break;
+ }
+ }
+ case GL_ETC1_RGB8_OES:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM:
+ return ETC1_RGB8_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_LUMINANCE:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_FLOAT:
+ return LUMINANCE_to_R16G16B16A16_FLOAT;
+ case Format::ID::R32G32B32A32_FLOAT:
+ return LUMINANCE_to_R32G32B32A32_FLOAT;
+ default:
+ return LUMINANCE_to_default;
+ }
+ }
+ case GL_LUMINANCE16F_EXT:
+ return LUMINANCE16F_EXT_to_default;
+ case GL_LUMINANCE32F_EXT:
+ return LUMINANCE32F_EXT_to_default;
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ return LUMINANCE8_ALPHA8_EXT_to_default;
+ case GL_LUMINANCE8_EXT:
+ return LUMINANCE8_EXT_to_default;
+ case GL_LUMINANCE_ALPHA:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_FLOAT:
+ return LUMINANCE_ALPHA_to_R16G16B16A16_FLOAT;
+ case Format::ID::R32G32B32A32_FLOAT:
+ return LUMINANCE_ALPHA_to_R32G32B32A32_FLOAT;
+ default:
+ return LUMINANCE_ALPHA_to_default;
+ }
+ }
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ return LUMINANCE_ALPHA16F_EXT_to_default;
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ return LUMINANCE_ALPHA32F_EXT_to_default;
+ case GL_R11F_G11F_B10F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R11G11B10_FLOAT:
+ return R11F_G11F_B10F_to_R11G11B10_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_R16F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16_FLOAT:
+ return R16F_to_R16_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_R16I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16_SINT:
+ return R16I_to_R16_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_R16UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16_UINT:
+ return R16UI_to_R16_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_R16_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16_UNORM:
+ return R16_EXT_to_R16_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_R16_SNORM_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16_SNORM:
+ return R16_SNORM_EXT_to_R16_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_R32F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32_FLOAT:
+ return R32F_to_R32_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_R32I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32_SINT:
+ return R32I_to_R32_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_R32UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32_UINT:
+ return R32UI_to_R32_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_R8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8_UNORM:
+ return R8_to_R8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_R8I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8_SINT:
+ return R8I_to_R8_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_R8UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8_UINT:
+ return R8UI_to_R8_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_R8_SNORM:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8_SNORM:
+ return R8_SNORM_to_R8_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RG16F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16_FLOAT:
+ return RG16F_to_R16G16_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_RG16I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16_SINT:
+ return RG16I_to_R16G16_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RG16UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16_UINT:
+ return RG16UI_to_R16G16_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RG16_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16_UNORM:
+ return RG16_EXT_to_R16G16_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RG16_SNORM_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16_SNORM:
+ return RG16_SNORM_EXT_to_R16G16_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RG32F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32_FLOAT:
+ return RG32F_to_R32G32_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_RG32I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32_SINT:
+ return RG32I_to_R32G32_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RG32UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32_UINT:
+ return RG32UI_to_R32G32_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RG8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8_UNORM:
+ return RG8_to_R8G8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RG8I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8_SINT:
+ return RG8I_to_R8G8_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RG8UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8_UINT:
+ return RG8UI_to_R8G8_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RG8_SNORM:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8_SNORM:
+ return RG8_SNORM_to_R8G8_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB:
+ return RGB_to_default;
+ case GL_RGB10_A2:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R10G10B10A2_UNORM:
+ return RGB10_A2_to_R10G10B10A2_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB10_A2UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R10G10B10A2_UINT:
+ return RGB10_A2UI_to_R10G10B10A2_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB16F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_FLOAT:
+ return RGB16F_to_R16G16B16A16_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB16I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_SINT:
+ return RGB16I_to_R16G16B16A16_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB16UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_UINT:
+ return RGB16UI_to_R16G16B16A16_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB16_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_UNORM:
+ return RGB16_EXT_to_R16G16B16A16_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB16_SNORM_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_SNORM:
+ return RGB16_SNORM_EXT_to_R16G16B16A16_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB32F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32B32A32_FLOAT:
+ return RGB32F_to_R32G32B32A32_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB32I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32B32A32_SINT:
+ return RGB32I_to_R32G32B32A32_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB32UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32B32A32_UINT:
+ return RGB32UI_to_R32G32B32A32_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB565:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::B5G6R5_UNORM:
+ return RGB565_to_B5G6R5_UNORM;
+ case Format::ID::R8G8B8A8_UNORM:
+ return RGB565_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB5_A1:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::B5G5R5A1_UNORM:
+ return RGB5_A1_to_B5G5R5A1_UNORM;
+ case Format::ID::R8G8B8A8_UNORM:
+ return RGB5_A1_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM:
+ return RGB8_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB8I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_SINT:
+ return RGB8I_to_R8G8B8A8_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB8UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UINT:
+ return RGB8UI_to_R8G8B8A8_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB8_SNORM:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_SNORM:
+ return RGB8_SNORM_to_R8G8B8A8_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB9_E5:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R9G9B9E5_SHAREDEXP:
+ return RGB9_E5_to_R9G9B9E5_SHAREDEXP;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA:
+ return RGBA_to_default;
+ case GL_RGBA16F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_FLOAT:
+ return RGBA16F_to_R16G16B16A16_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA16I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_SINT:
+ return RGBA16I_to_R16G16B16A16_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA16UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_UINT:
+ return RGBA16UI_to_R16G16B16A16_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA16_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_UNORM:
+ return RGBA16_EXT_to_R16G16B16A16_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA16_SNORM_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_SNORM:
+ return RGBA16_SNORM_EXT_to_R16G16B16A16_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA32F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32B32A32_FLOAT:
+ return RGBA32F_to_R32G32B32A32_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA32I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32B32A32_SINT:
+ return RGBA32I_to_R32G32B32A32_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA32UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32B32A32_UINT:
+ return RGBA32UI_to_R32G32B32A32_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA4:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::B4G4R4A4_UNORM:
+ return RGBA4_to_B4G4R4A4_UNORM;
+ case Format::ID::R8G8B8A8_UNORM:
+ return RGBA4_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM:
+ return RGBA8_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA8I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_SINT:
+ return RGBA8I_to_R8G8B8A8_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA8UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UINT:
+ return RGBA8UI_to_R8G8B8A8_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA8_SNORM:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_SNORM:
+ return RGBA8_SNORM_to_R8G8B8A8_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_SRGB8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM_SRGB:
+ return SRGB8_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ }
+ case GL_SRGB8_ALPHA8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM_SRGB:
+ return SRGB8_ALPHA8_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ }
+ case GL_STENCIL_INDEX8:
+ return STENCIL_INDEX8_to_default;
+
+ default:
+ {
+ static LoadFunctionMap emptyLoadFunctionsMap;
+ return emptyLoadFunctionsMap;
+ }
+ }
+ // clang-format on
+
+} // GetLoadFunctionsMap
+
+} // namespace angle
diff --git a/gfx/angle/src/libANGLE/renderer/null/BufferNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/BufferNULL.cpp
new file mode 100644
index 000000000..95463c3f4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/BufferNULL.cpp
@@ -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.
+//
+// BufferNULL.cpp:
+// Implements the class methods for BufferNULL.
+//
+
+#include "libANGLE/renderer/null/BufferNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+BufferNULL::BufferNULL(const gl::BufferState &state) : BufferImpl(state)
+{
+}
+
+BufferNULL::~BufferNULL()
+{
+}
+
+gl::Error BufferNULL::setData(GLenum target, const void *data, size_t size, GLenum usage)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferNULL::setSubData(GLenum target, const void *data, size_t size, size_t offset)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferNULL::copySubData(BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferNULL::map(GLenum access, GLvoid **mapPtr)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferNULL::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferNULL::unmap(GLboolean *result)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferNULL::getIndexRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ gl::IndexRange *outRange)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/BufferNULL.h b/gfx/angle/src/libANGLE/renderer/null/BufferNULL.h
new file mode 100644
index 000000000..1578dacbb
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/BufferNULL.h
@@ -0,0 +1,43 @@
+//
+// 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.
+//
+// BufferNULL.h:
+// Defines the class interface for BufferNULL, implementing BufferImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_BUFFERNULL_H_
+#define LIBANGLE_RENDERER_NULL_BUFFERNULL_H_
+
+#include "libANGLE/renderer/BufferImpl.h"
+
+namespace rx
+{
+
+class BufferNULL : public BufferImpl
+{
+ public:
+ BufferNULL(const gl::BufferState &state);
+ ~BufferNULL() override;
+
+ gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) override;
+ gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) override;
+ gl::Error copySubData(BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size) override;
+ gl::Error map(GLenum access, GLvoid **mapPtr) override;
+ gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override;
+ gl::Error unmap(GLboolean *result) override;
+
+ gl::Error getIndexRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ gl::IndexRange *outRange) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_BUFFERNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/CompilerNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/CompilerNULL.cpp
new file mode 100644
index 000000000..547f4c4e1
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/CompilerNULL.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.
+//
+// CompilerNULL.cpp:
+// Implements the class methods for CompilerNULL.
+//
+
+#include "libANGLE/renderer/null/CompilerNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+CompilerNULL::CompilerNULL() : CompilerImpl()
+{
+}
+
+CompilerNULL::~CompilerNULL()
+{
+}
+
+gl::Error CompilerNULL::release()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+ShShaderOutput CompilerNULL::getTranslatorOutputType() const
+{
+ UNIMPLEMENTED();
+ return ShShaderOutput();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/CompilerNULL.h b/gfx/angle/src/libANGLE/renderer/null/CompilerNULL.h
new file mode 100644
index 000000000..5cd85e8bf
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/CompilerNULL.h
@@ -0,0 +1,32 @@
+//
+// 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.
+//
+// CompilerNULL.h:
+// Defines the class interface for CompilerNULL, implementing CompilerImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_COMPILERNULL_H_
+#define LIBANGLE_RENDERER_NULL_COMPILERNULL_H_
+
+#include "libANGLE/renderer/CompilerImpl.h"
+
+namespace rx
+{
+
+class CompilerNULL : public CompilerImpl
+{
+ public:
+ CompilerNULL();
+ ~CompilerNULL() override;
+
+ gl::Error release() override;
+
+ // TODO(jmadill): Expose translator built-in resources init method.
+ ShShaderOutput getTranslatorOutputType() const override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_COMPILERNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/ContextNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/ContextNULL.cpp
new file mode 100644
index 000000000..95d4c046a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/ContextNULL.cpp
@@ -0,0 +1,175 @@
+//
+// 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.
+//
+// ContextNULL.cpp:
+// Implements the class methods for ContextNULL.
+//
+
+#include "libANGLE/renderer/null/ContextNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ContextNULL::ContextNULL(const gl::ContextState &state) : ContextImpl(state)
+{
+}
+
+ContextNULL::~ContextNULL()
+{
+}
+
+gl::Error ContextNULL::initialize()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextNULL::flush()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextNULL::finish()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextNULL::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextNULL::drawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextNULL::drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextNULL::drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextNULL::drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+CompilerImpl *ContextNULL::createCompiler()
+{
+ UNIMPLEMENTED();
+ return static_cast<CompilerImpl *>(0);
+}
+
+ShaderImpl *ContextNULL::createShader(const gl::ShaderState &data)
+{
+ UNIMPLEMENTED();
+ return static_cast<ShaderImpl *>(0);
+}
+
+ProgramImpl *ContextNULL::createProgram(const gl::ProgramState &data)
+{
+ UNIMPLEMENTED();
+ return static_cast<ProgramImpl *>(0);
+}
+
+FramebufferImpl *ContextNULL::createFramebuffer(const gl::FramebufferState &data)
+{
+ UNIMPLEMENTED();
+ return static_cast<FramebufferImpl *>(0);
+}
+
+TextureImpl *ContextNULL::createTexture(const gl::TextureState &state)
+{
+ UNIMPLEMENTED();
+ return static_cast<TextureImpl *>(0);
+}
+
+RenderbufferImpl *ContextNULL::createRenderbuffer()
+{
+ UNIMPLEMENTED();
+ return static_cast<RenderbufferImpl *>(0);
+}
+
+BufferImpl *ContextNULL::createBuffer(const gl::BufferState &state)
+{
+ UNIMPLEMENTED();
+ return static_cast<BufferImpl *>(0);
+}
+
+VertexArrayImpl *ContextNULL::createVertexArray(const gl::VertexArrayState &data)
+{
+ UNIMPLEMENTED();
+ return static_cast<VertexArrayImpl *>(0);
+}
+
+QueryImpl *ContextNULL::createQuery(GLenum type)
+{
+ UNIMPLEMENTED();
+ return static_cast<QueryImpl *>(0);
+}
+
+FenceNVImpl *ContextNULL::createFenceNV()
+{
+ UNIMPLEMENTED();
+ return static_cast<FenceNVImpl *>(0);
+}
+
+FenceSyncImpl *ContextNULL::createFenceSync()
+{
+ UNIMPLEMENTED();
+ return static_cast<FenceSyncImpl *>(0);
+}
+
+TransformFeedbackImpl *ContextNULL::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+ UNIMPLEMENTED();
+ return static_cast<TransformFeedbackImpl *>(0);
+}
+
+SamplerImpl *ContextNULL::createSampler()
+{
+ UNIMPLEMENTED();
+ return static_cast<SamplerImpl *>(0);
+}
+
+std::vector<PathImpl *> ContextNULL::createPaths(GLsizei range)
+{
+ UNIMPLEMENTED();
+ return std::vector<PathImpl *>();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/ContextNULL.h b/gfx/angle/src/libANGLE/renderer/null/ContextNULL.h
new file mode 100644
index 000000000..9a7987b67
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/ContextNULL.h
@@ -0,0 +1,95 @@
+//
+// 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.
+//
+// ContextNULL.h:
+// Defines the class interface for ContextNULL, implementing ContextImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_CONTEXTNULL_H_
+#define LIBANGLE_RENDERER_NULL_CONTEXTNULL_H_
+
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace rx
+{
+
+class ContextNULL : public ContextImpl
+{
+ public:
+ ContextNULL(const gl::ContextState &state);
+ ~ContextNULL() override;
+
+ gl::Error initialize() override;
+
+ // Flush and finish.
+ gl::Error flush() override;
+ gl::Error finish() override;
+
+ // Drawing methods.
+ gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override;
+ gl::Error drawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) override;
+
+ gl::Error drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange) override;
+ gl::Error drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange) override;
+ gl::Error drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange) override;
+
+ // CHROMIUM_path_rendering path drawing methods.
+
+ // 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() 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(GLenum type) override;
+ FenceNVImpl *createFenceNV() override;
+ FenceSyncImpl *createFenceSync() override;
+
+ // Transform Feedback creation
+ TransformFeedbackImpl *createTransformFeedback(
+ const gl::TransformFeedbackState &state) override;
+
+ // Sampler object creation
+ SamplerImpl *createSampler() override;
+
+ std::vector<PathImpl *> createPaths(GLsizei range) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_CONTEXTNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/DeviceNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/DeviceNULL.cpp
new file mode 100644
index 000000000..4893f9466
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/DeviceNULL.cpp
@@ -0,0 +1,48 @@
+//
+// 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.
+//
+// DeviceNULL.cpp:
+// Implements the class methods for DeviceNULL.
+//
+
+#include "libANGLE/renderer/null/DeviceNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+DeviceNULL::DeviceNULL() : DeviceImpl()
+{
+}
+
+DeviceNULL::~DeviceNULL()
+{
+}
+
+egl::Error DeviceNULL::getDevice(void **outValue)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+EGLint DeviceNULL::getType()
+{
+ UNIMPLEMENTED();
+ return EGLint();
+}
+
+void DeviceNULL::generateExtensions(egl::DeviceExtensions *outExtensions) const
+{
+ UNIMPLEMENTED();
+}
+
+bool DeviceNULL::deviceExternallySourced()
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/DeviceNULL.h b/gfx/angle/src/libANGLE/renderer/null/DeviceNULL.h
new file mode 100644
index 000000000..ed921039e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/DeviceNULL.h
@@ -0,0 +1,32 @@
+//
+// 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.
+//
+// DeviceNULL.h:
+// Defines the class interface for DeviceNULL, implementing DeviceImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_DEVICENULL_H_
+#define LIBANGLE_RENDERER_NULL_DEVICENULL_H_
+
+#include "libANGLE/renderer/DeviceImpl.h"
+
+namespace rx
+{
+
+class DeviceNULL : public DeviceImpl
+{
+ public:
+ DeviceNULL();
+ ~DeviceNULL() override;
+
+ egl::Error getDevice(void **outValue) override;
+ EGLint getType() override;
+ void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
+ bool deviceExternallySourced() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_DEVICENULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/DisplayNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/DisplayNULL.cpp
new file mode 100644
index 000000000..fc04e0465
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/DisplayNULL.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.
+//
+// DisplayNULL.cpp:
+// Implements the class methods for DisplayNULL.
+//
+
+#include "libANGLE/renderer/null/DisplayNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+DisplayNULL::DisplayNULL() : DisplayImpl()
+{
+}
+
+DisplayNULL::~DisplayNULL()
+{
+}
+
+egl::Error DisplayNULL::initialize(egl::Display *display)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+void DisplayNULL::terminate()
+{
+ UNIMPLEMENTED();
+}
+
+egl::Error DisplayNULL::makeCurrent(egl::Surface *drawSurface,
+ egl::Surface *readSurface,
+ gl::Context *context)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::ConfigSet DisplayNULL::generateConfigs()
+{
+ UNIMPLEMENTED();
+ return egl::ConfigSet();
+}
+
+bool DisplayNULL::testDeviceLost()
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+egl::Error DisplayNULL::restoreLostDevice()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+bool DisplayNULL::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+std::string DisplayNULL::getVendorString() const
+{
+ UNIMPLEMENTED();
+ return std::string();
+}
+
+egl::Error DisplayNULL::getDevice(DeviceImpl **device)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error DisplayNULL::waitClient() const
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error DisplayNULL::waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+gl::Version DisplayNULL::getMaxSupportedESVersion() const
+{
+ UNIMPLEMENTED();
+ return gl::Version();
+}
+
+SurfaceImpl *DisplayNULL::createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return static_cast<SurfaceImpl *>(0);
+}
+
+SurfaceImpl *DisplayNULL::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return static_cast<SurfaceImpl *>(0);
+}
+
+SurfaceImpl *DisplayNULL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return static_cast<SurfaceImpl *>(0);
+}
+
+SurfaceImpl *DisplayNULL::createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return static_cast<SurfaceImpl *>(0);
+}
+
+ImageImpl *DisplayNULL::createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return static_cast<ImageImpl *>(0);
+}
+
+ContextImpl *DisplayNULL::createContext(const gl::ContextState &state)
+{
+ UNIMPLEMENTED();
+ return static_cast<ContextImpl *>(0);
+}
+
+StreamProducerImpl *DisplayNULL::createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return static_cast<StreamProducerImpl *>(0);
+}
+
+void DisplayNULL::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ UNIMPLEMENTED();
+}
+
+void DisplayNULL::generateCaps(egl::Caps *outCaps) const
+{
+ UNIMPLEMENTED();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/DisplayNULL.h b/gfx/angle/src/libANGLE/renderer/null/DisplayNULL.h
new file mode 100644
index 000000000..5a453810a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/DisplayNULL.h
@@ -0,0 +1,82 @@
+//
+// 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.
+//
+// DisplayNULL.h:
+// Defines the class interface for DisplayNULL, implementing DisplayImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_DISPLAYNULL_H_
+#define LIBANGLE_RENDERER_NULL_DISPLAYNULL_H_
+
+#include "libANGLE/renderer/DisplayImpl.h"
+
+namespace rx
+{
+
+class DisplayNULL : public DisplayImpl
+{
+ public:
+ DisplayNULL();
+ ~DisplayNULL() override;
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ egl::Error makeCurrent(egl::Surface *drawSurface,
+ egl::Surface *readSurface,
+ gl::Context *context) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() override;
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+ std::string getVendorString() const override;
+
+ egl::Error getDevice(DeviceImpl **device) override;
+
+ egl::Error waitClient() const override;
+ egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const override;
+ gl::Version getMaxSupportedESVersion() const override;
+
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ ImageImpl *createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs) override;
+
+ ContextImpl *createContext(const gl::ContextState &state) override;
+
+ StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) override;
+
+ private:
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+ void generateCaps(egl::Caps *outCaps) const override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_DISPLAYNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/FenceNVNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/FenceNVNULL.cpp
new file mode 100644
index 000000000..9d7f26043
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/FenceNVNULL.cpp
@@ -0,0 +1,43 @@
+//
+// 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.
+//
+// FenceNVNULL.cpp:
+// Implements the class methods for FenceNVNULL.
+//
+
+#include "libANGLE/renderer/null/FenceNVNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+FenceNVNULL::FenceNVNULL() : FenceNVImpl()
+{
+}
+
+FenceNVNULL::~FenceNVNULL()
+{
+}
+
+gl::Error FenceNVNULL::set(GLenum condition)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceNVNULL::test(GLboolean *outFinished)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceNVNULL::finish()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/FenceNVNULL.h b/gfx/angle/src/libANGLE/renderer/null/FenceNVNULL.h
new file mode 100644
index 000000000..10cf5c2cb
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/FenceNVNULL.h
@@ -0,0 +1,31 @@
+//
+// 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.
+//
+// FenceNVNULL.h:
+// Defines the class interface for FenceNVNULL, implementing FenceNVImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_FENCENVNULL_H_
+#define LIBANGLE_RENDERER_NULL_FENCENVNULL_H_
+
+#include "libANGLE/renderer/FenceNVImpl.h"
+
+namespace rx
+{
+
+class FenceNVNULL : public FenceNVImpl
+{
+ public:
+ FenceNVNULL();
+ ~FenceNVNULL() override;
+
+ gl::Error set(GLenum condition) override;
+ gl::Error test(GLboolean *outFinished) override;
+ gl::Error finish() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_FENCENVNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/FenceSyncNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/FenceSyncNULL.cpp
new file mode 100644
index 000000000..37bfdfedb
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/FenceSyncNULL.cpp
@@ -0,0 +1,49 @@
+//
+// 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.
+//
+// FenceSyncNULL.cpp:
+// Implements the class methods for FenceSyncNULL.
+//
+
+#include "libANGLE/renderer/null/FenceSyncNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+FenceSyncNULL::FenceSyncNULL() : FenceSyncImpl()
+{
+}
+
+FenceSyncNULL::~FenceSyncNULL()
+{
+}
+
+gl::Error FenceSyncNULL::set(GLenum condition, GLbitfield flags)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceSyncNULL::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceSyncNULL::serverWait(GLbitfield flags, GLuint64 timeout)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceSyncNULL::getStatus(GLint *outResult)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/FenceSyncNULL.h b/gfx/angle/src/libANGLE/renderer/null/FenceSyncNULL.h
new file mode 100644
index 000000000..28a12f703
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/FenceSyncNULL.h
@@ -0,0 +1,32 @@
+//
+// 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.
+//
+// FenceSyncNULL.h:
+// Defines the class interface for FenceSyncNULL, implementing FenceSyncImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_FENCESYNCNULL_H_
+#define LIBANGLE_RENDERER_NULL_FENCESYNCNULL_H_
+
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+namespace rx
+{
+
+class FenceSyncNULL : public FenceSyncImpl
+{
+ public:
+ FenceSyncNULL();
+ ~FenceSyncNULL() override;
+
+ gl::Error set(GLenum condition, GLbitfield flags) override;
+ gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override;
+ gl::Error serverWait(GLbitfield flags, GLuint64 timeout) override;
+ gl::Error getStatus(GLint *outResult) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_FENCESYNCNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/FramebufferNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/FramebufferNULL.cpp
new file mode 100644
index 000000000..14ebe1eba
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/FramebufferNULL.cpp
@@ -0,0 +1,131 @@
+//
+// 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.
+//
+// FramebufferNULL.cpp:
+// Implements the class methods for FramebufferNULL.
+//
+
+#include "libANGLE/renderer/null/FramebufferNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+FramebufferNULL::FramebufferNULL(const gl::FramebufferState &state) : FramebufferImpl(state)
+{
+}
+
+FramebufferNULL::~FramebufferNULL()
+{
+}
+
+gl::Error FramebufferNULL::discard(size_t count, const GLenum *attachments)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferNULL::invalidate(size_t count, const GLenum *attachments)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferNULL::invalidateSub(size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferNULL::clear(ContextImpl *context, GLbitfield mask)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferNULL::clearBufferfv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferNULL::clearBufferuiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferNULL::clearBufferiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferNULL::clearBufferfi(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+GLenum FramebufferNULL::getImplementationColorReadFormat() const
+{
+ UNIMPLEMENTED();
+ return GLenum();
+}
+
+GLenum FramebufferNULL::getImplementationColorReadType() const
+{
+ UNIMPLEMENTED();
+ return GLenum();
+}
+
+gl::Error FramebufferNULL::readPixels(ContextImpl *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels) const
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferNULL::blit(ContextImpl *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+bool FramebufferNULL::checkStatus() const
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+void FramebufferNULL::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
+{
+ UNIMPLEMENTED();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/FramebufferNULL.h b/gfx/angle/src/libANGLE/renderer/null/FramebufferNULL.h
new file mode 100644
index 000000000..c53132c18
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/FramebufferNULL.h
@@ -0,0 +1,70 @@
+//
+// 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.
+//
+// FramebufferNULL.h:
+// Defines the class interface for FramebufferNULL, implementing FramebufferImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_FRAMEBUFFERNULL_H_
+#define LIBANGLE_RENDERER_NULL_FRAMEBUFFERNULL_H_
+
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace rx
+{
+
+class FramebufferNULL : public FramebufferImpl
+{
+ public:
+ FramebufferNULL(const gl::FramebufferState &state);
+ ~FramebufferNULL() override;
+
+ gl::Error discard(size_t count, const GLenum *attachments) override;
+ gl::Error invalidate(size_t count, const GLenum *attachments) override;
+ gl::Error invalidateSub(size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area) override;
+
+ gl::Error clear(ContextImpl *context, GLbitfield mask) override;
+ gl::Error clearBufferfv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values) override;
+ gl::Error clearBufferuiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values) override;
+ gl::Error clearBufferiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values) override;
+ gl::Error clearBufferfi(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil) override;
+
+ GLenum getImplementationColorReadFormat() const override;
+ GLenum getImplementationColorReadType() const override;
+ gl::Error readPixels(ContextImpl *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels) const override;
+
+ gl::Error blit(ContextImpl *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter) override;
+
+ bool checkStatus() const override;
+
+ void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_FRAMEBUFFERNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/ImageNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/ImageNULL.cpp
new file mode 100644
index 000000000..23f3ca099
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/ImageNULL.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.
+//
+// ImageNULL.cpp:
+// Implements the class methods for ImageNULL.
+//
+
+#include "libANGLE/renderer/null/ImageNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ImageNULL::ImageNULL() : ImageImpl()
+{
+}
+
+ImageNULL::~ImageNULL()
+{
+}
+
+egl::Error ImageNULL::initialize()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+gl::Error ImageNULL::orphan(egl::ImageSibling *sibling)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/ImageNULL.h b/gfx/angle/src/libANGLE/renderer/null/ImageNULL.h
new file mode 100644
index 000000000..b88b346dd
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/ImageNULL.h
@@ -0,0 +1,30 @@
+//
+// 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.
+//
+// ImageNULL.h:
+// Defines the class interface for ImageNULL, implementing ImageImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_IMAGENULL_H_
+#define LIBANGLE_RENDERER_NULL_IMAGENULL_H_
+
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace rx
+{
+
+class ImageNULL : public ImageImpl
+{
+ public:
+ ImageNULL();
+ ~ImageNULL() override;
+ egl::Error initialize() override;
+
+ gl::Error orphan(egl::ImageSibling *sibling) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_IMAGENULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/PathNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/PathNULL.cpp
new file mode 100644
index 000000000..bb52ea2c2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/PathNULL.cpp
@@ -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.
+//
+// PathNULL.cpp:
+// Implements the class methods for PathNULL.
+//
+
+#include "libANGLE/renderer/null/PathNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+PathNULL::PathNULL() : PathImpl()
+{
+}
+
+PathNULL::~PathNULL()
+{
+}
+
+gl::Error PathNULL::setCommands(GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+void PathNULL::setPathParameter(GLenum pname, GLfloat value)
+{
+ UNIMPLEMENTED();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/PathNULL.h b/gfx/angle/src/libANGLE/renderer/null/PathNULL.h
new file mode 100644
index 000000000..4c80c1c91
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/PathNULL.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.
+//
+// PathNULL.h:
+// Defines the class interface for PathNULL, implementing PathImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_PATHNULL_H_
+#define LIBANGLE_RENDERER_NULL_PATHNULL_H_
+
+#include "libANGLE/renderer/PathImpl.h"
+
+namespace rx
+{
+
+class PathNULL : public PathImpl
+{
+ public:
+ PathNULL();
+ ~PathNULL() override;
+
+ gl::Error setCommands(GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords) override;
+
+ void setPathParameter(GLenum pname, GLfloat value) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_PATHNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/ProgramNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/ProgramNULL.cpp
new file mode 100644
index 000000000..fb44b6ee4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/ProgramNULL.cpp
@@ -0,0 +1,212 @@
+//
+// 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.
+//
+// ProgramNULL.cpp:
+// Implements the class methods for ProgramNULL.
+//
+
+#include "libANGLE/renderer/null/ProgramNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ProgramNULL::ProgramNULL(const gl::ProgramState &state) : ProgramImpl(state)
+{
+}
+
+ProgramNULL::~ProgramNULL()
+{
+}
+
+LinkResult ProgramNULL::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ProgramNULL::save(gl::BinaryOutputStream *stream)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+void ProgramNULL::setBinaryRetrievableHint(bool retrievable)
+{
+ UNIMPLEMENTED();
+}
+
+LinkResult ProgramNULL::link(const gl::ContextState &data, gl::InfoLog &infoLog)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+GLboolean ProgramNULL::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
+{
+ UNIMPLEMENTED();
+ return GLboolean();
+}
+
+void ProgramNULL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramNULL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+{
+ UNIMPLEMENTED();
+}
+
+bool ProgramNULL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+bool ProgramNULL::getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+void ProgramNULL::setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ UNIMPLEMENTED();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/ProgramNULL.h b/gfx/angle/src/libANGLE/renderer/null/ProgramNULL.h
new file mode 100644
index 000000000..576a52c18
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/ProgramNULL.h
@@ -0,0 +1,101 @@
+//
+// 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.
+//
+// ProgramNULL.h:
+// Defines the class interface for ProgramNULL, implementing ProgramImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_PROGRAMNULL_H_
+#define LIBANGLE_RENDERER_NULL_PROGRAMNULL_H_
+
+#include "libANGLE/renderer/ProgramImpl.h"
+
+namespace rx
+{
+
+class ProgramNULL : public ProgramImpl
+{
+ public:
+ ProgramNULL(const gl::ProgramState &state);
+ ~ProgramNULL() override;
+
+ LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
+ gl::Error save(gl::BinaryOutputStream *stream) override;
+ void setBinaryRetrievableHint(bool retrievable) override;
+
+ LinkResult link(const gl::ContextState &data, gl::InfoLog &infoLog) override;
+ GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
+
+ 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;
+
+ // TODO: synchronize in syncState when dirty bits exist.
+ void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
+
+ // May only be called after a successful link operation.
+ // Return false for inactive blocks.
+ bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
+
+ // May only be called after a successful link operation.
+ // Returns false for inactive members.
+ bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const override;
+ // CHROMIUM_path_rendering
+ // Set parameters to control fragment shader input variable interpolation
+ void setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_PROGRAMNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/QueryNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/QueryNULL.cpp
new file mode 100644
index 000000000..6276a0ff1
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/QueryNULL.cpp
@@ -0,0 +1,73 @@
+//
+// 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.
+//
+// QueryNULL.cpp:
+// Implements the class methods for QueryNULL.
+//
+
+#include "libANGLE/renderer/null/QueryNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+QueryNULL::QueryNULL(GLenum type) : QueryImpl(type)
+{
+}
+
+QueryNULL::~QueryNULL()
+{
+}
+
+gl::Error QueryNULL::begin()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryNULL::end()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryNULL::queryCounter()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryNULL::getResult(GLint *params)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryNULL::getResult(GLuint *params)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryNULL::getResult(GLint64 *params)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryNULL::getResult(GLuint64 *params)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryNULL::isResultAvailable(bool *available)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/QueryNULL.h b/gfx/angle/src/libANGLE/renderer/null/QueryNULL.h
new file mode 100644
index 000000000..40082a9b8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/QueryNULL.h
@@ -0,0 +1,36 @@
+//
+// 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.
+//
+// QueryNULL.h:
+// Defines the class interface for QueryNULL, implementing QueryImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_QUERYNULL_H_
+#define LIBANGLE_RENDERER_NULL_QUERYNULL_H_
+
+#include "libANGLE/renderer/QueryImpl.h"
+
+namespace rx
+{
+
+class QueryNULL : public QueryImpl
+{
+ public:
+ QueryNULL(GLenum type);
+ ~QueryNULL() override;
+
+ gl::Error begin() override;
+ gl::Error end() override;
+ gl::Error queryCounter() override;
+ gl::Error getResult(GLint *params) override;
+ gl::Error getResult(GLuint *params) override;
+ gl::Error getResult(GLint64 *params) override;
+ gl::Error getResult(GLuint64 *params) override;
+ gl::Error isResultAvailable(bool *available) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_QUERYNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/RenderbufferNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/RenderbufferNULL.cpp
new file mode 100644
index 000000000..50f54a620
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/RenderbufferNULL.cpp
@@ -0,0 +1,46 @@
+//
+// 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.
+//
+// RenderbufferNULL.cpp:
+// Implements the class methods for RenderbufferNULL.
+//
+
+#include "libANGLE/renderer/null/RenderbufferNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+RenderbufferNULL::RenderbufferNULL() : RenderbufferImpl()
+{
+}
+
+RenderbufferNULL::~RenderbufferNULL()
+{
+}
+
+gl::Error RenderbufferNULL::setStorage(GLenum internalformat, size_t width, size_t height)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error RenderbufferNULL::setStorageMultisample(size_t samples,
+ GLenum internalformat,
+ size_t width,
+ size_t height)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error RenderbufferNULL::setStorageEGLImageTarget(egl::Image *image)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/RenderbufferNULL.h b/gfx/angle/src/libANGLE/renderer/null/RenderbufferNULL.h
new file mode 100644
index 000000000..79e529c4c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/RenderbufferNULL.h
@@ -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.
+//
+// RenderbufferNULL.h:
+// Defines the class interface for RenderbufferNULL, implementing RenderbufferImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_RENDERBUFFERNULL_H_
+#define LIBANGLE_RENDERER_NULL_RENDERBUFFERNULL_H_
+
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+
+class RenderbufferNULL : public RenderbufferImpl
+{
+ public:
+ RenderbufferNULL();
+ ~RenderbufferNULL() override;
+
+ gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override;
+ gl::Error setStorageMultisample(size_t samples,
+ GLenum internalformat,
+ size_t width,
+ size_t height) override;
+ gl::Error setStorageEGLImageTarget(egl::Image *image) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_RENDERBUFFERNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/SamplerNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/SamplerNULL.cpp
new file mode 100644
index 000000000..e1e8c7c62
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/SamplerNULL.cpp
@@ -0,0 +1,25 @@
+//
+// 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.
+//
+// SamplerNULL.cpp:
+// Implements the class methods for SamplerNULL.
+//
+
+#include "libANGLE/renderer/null/SamplerNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+SamplerNULL::SamplerNULL() : SamplerImpl()
+{
+}
+
+SamplerNULL::~SamplerNULL()
+{
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/SamplerNULL.h b/gfx/angle/src/libANGLE/renderer/null/SamplerNULL.h
new file mode 100644
index 000000000..031fafa39
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/SamplerNULL.h
@@ -0,0 +1,27 @@
+//
+// 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.
+//
+// SamplerNULL.h:
+// Defines the class interface for SamplerNULL, implementing SamplerImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_SAMPLERNULL_H_
+#define LIBANGLE_RENDERER_NULL_SAMPLERNULL_H_
+
+#include "libANGLE/renderer/SamplerImpl.h"
+
+namespace rx
+{
+
+class SamplerNULL : public SamplerImpl
+{
+ public:
+ SamplerNULL();
+ ~SamplerNULL() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_SAMPLERNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/ShaderNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/ShaderNULL.cpp
new file mode 100644
index 000000000..168f4bdca
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/ShaderNULL.cpp
@@ -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.
+//
+// ShaderNULL.cpp:
+// Implements the class methods for ShaderNULL.
+//
+
+#include "libANGLE/renderer/null/ShaderNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ShaderNULL::ShaderNULL(const gl::ShaderState &data) : ShaderImpl(data)
+{
+}
+
+ShaderNULL::~ShaderNULL()
+{
+}
+
+ShCompileOptions ShaderNULL::prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string *sourcePath)
+{
+ UNIMPLEMENTED();
+ return ShCompileOptions();
+}
+
+bool ShaderNULL::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+std::string ShaderNULL::getDebugInfo() const
+{
+ UNIMPLEMENTED();
+ return std::string();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/ShaderNULL.h b/gfx/angle/src/libANGLE/renderer/null/ShaderNULL.h
new file mode 100644
index 000000000..d29b4cfb7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/ShaderNULL.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.
+//
+// ShaderNULL.h:
+// Defines the class interface for ShaderNULL, implementing ShaderImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_SHADERNULL_H_
+#define LIBANGLE_RENDERER_NULL_SHADERNULL_H_
+
+#include "libANGLE/renderer/ShaderImpl.h"
+
+namespace rx
+{
+
+class ShaderNULL : public ShaderImpl
+{
+ public:
+ ShaderNULL(const gl::ShaderState &data);
+ ~ShaderNULL() override;
+
+ // Returns additional sh::Compile options.
+ ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string *sourcePath) override;
+ // Returns success for compiling on the driver. Returns success.
+ bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override;
+
+ std::string getDebugInfo() const override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_SHADERNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/SurfaceNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/SurfaceNULL.cpp
new file mode 100644
index 000000000..81d763783
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/SurfaceNULL.cpp
@@ -0,0 +1,103 @@
+//
+// 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.
+//
+// SurfaceNULL.cpp:
+// Implements the class methods for SurfaceNULL.
+//
+
+#include "libANGLE/renderer/null/SurfaceNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+SurfaceNULL::SurfaceNULL(const egl::SurfaceState &surfaceState) : SurfaceImpl(surfaceState)
+{
+}
+
+SurfaceNULL::~SurfaceNULL()
+{
+}
+
+egl::Error SurfaceNULL::initialize()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+FramebufferImpl *SurfaceNULL::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+ UNIMPLEMENTED();
+ return static_cast<FramebufferImpl *>(0);
+}
+
+egl::Error SurfaceNULL::swap()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error SurfaceNULL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error SurfaceNULL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error SurfaceNULL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error SurfaceNULL::releaseTexImage(EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+void SurfaceNULL::setSwapInterval(EGLint interval)
+{
+ UNIMPLEMENTED();
+}
+
+EGLint SurfaceNULL::getWidth() const
+{
+ UNIMPLEMENTED();
+ return EGLint();
+}
+
+EGLint SurfaceNULL::getHeight() const
+{
+ UNIMPLEMENTED();
+ return EGLint();
+}
+
+EGLint SurfaceNULL::isPostSubBufferSupported() const
+{
+ UNIMPLEMENTED();
+ return EGLint();
+}
+
+EGLint SurfaceNULL::getSwapBehavior() const
+{
+ UNIMPLEMENTED();
+ return EGLint();
+}
+
+gl::Error SurfaceNULL::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/SurfaceNULL.h b/gfx/angle/src/libANGLE/renderer/null/SurfaceNULL.h
new file mode 100644
index 000000000..597f1c21c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/SurfaceNULL.h
@@ -0,0 +1,46 @@
+//
+// 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.
+//
+// SurfaceNULL.h:
+// Defines the class interface for SurfaceNULL, implementing SurfaceImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_SURFACENULL_H_
+#define LIBANGLE_RENDERER_NULL_SURFACENULL_H_
+
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+namespace rx
+{
+
+class SurfaceNULL : public SurfaceImpl
+{
+ public:
+ SurfaceNULL(const egl::SurfaceState &surfaceState);
+ ~SurfaceNULL() override;
+
+ egl::Error initialize() override;
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ // width and height can change with client window resizing
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_SURFACENULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/TextureNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/TextureNULL.cpp
new file mode 100644
index 000000000..2c952e528
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/TextureNULL.cpp
@@ -0,0 +1,143 @@
+//
+// 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.
+//
+// TextureNULL.cpp:
+// Implements the class methods for TextureNULL.
+//
+
+#include "libANGLE/renderer/null/TextureNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+TextureNULL::TextureNULL(const gl::TextureState &state) : TextureImpl(state)
+{
+}
+
+TextureNULL::~TextureNULL()
+{
+}
+
+gl::Error TextureNULL::setImage(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureNULL::setSubImage(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureNULL::setCompressedImage(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureNULL::setCompressedSubImage(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureNULL::copyImage(GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureNULL::copySubImage(GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureNULL::setStorage(GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureNULL::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureNULL::setImageExternal(GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureNULL::generateMipmap()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+void TextureNULL::setBaseLevel(GLuint baseLevel)
+{
+ UNIMPLEMENTED();
+}
+
+void TextureNULL::bindTexImage(egl::Surface *surface)
+{
+ UNIMPLEMENTED();
+}
+
+void TextureNULL::releaseTexImage()
+{
+ UNIMPLEMENTED();
+}
+
+void TextureNULL::syncState(const gl::Texture::DirtyBits &dirtyBits)
+{
+ UNIMPLEMENTED();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/TextureNULL.h b/gfx/angle/src/libANGLE/renderer/null/TextureNULL.h
new file mode 100644
index 000000000..10c2d3503
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/TextureNULL.h
@@ -0,0 +1,89 @@
+//
+// 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.
+//
+// TextureNULL.h:
+// Defines the class interface for TextureNULL, implementing TextureImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_TEXTURENULL_H_
+#define LIBANGLE_RENDERER_NULL_TEXTURENULL_H_
+
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace rx
+{
+
+class TextureNULL : public TextureImpl
+{
+ public:
+ TextureNULL(const gl::TextureState &state);
+ ~TextureNULL() override;
+
+ gl::Error setImage(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+ gl::Error setSubImage(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ gl::Error copyImage(GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorage(GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+ gl::Error setImageExternal(GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+
+ gl::Error generateMipmap() override;
+
+ void setBaseLevel(GLuint baseLevel) override;
+
+ void bindTexImage(egl::Surface *surface) override;
+ void releaseTexImage() override;
+
+ void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_TEXTURENULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.cpp
new file mode 100644
index 000000000..e1433fb2d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.cpp
@@ -0,0 +1,57 @@
+//
+// 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.
+//
+// TransformFeedbackNULL.cpp:
+// Implements the class methods for TransformFeedbackNULL.
+//
+
+#include "libANGLE/renderer/null/TransformFeedbackNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+TransformFeedbackNULL::TransformFeedbackNULL(const gl::TransformFeedbackState &state)
+ : TransformFeedbackImpl(state)
+{
+}
+
+TransformFeedbackNULL::~TransformFeedbackNULL()
+{
+}
+
+void TransformFeedbackNULL::begin(GLenum primitiveMode)
+{
+ UNIMPLEMENTED();
+}
+
+void TransformFeedbackNULL::end()
+{
+ UNIMPLEMENTED();
+}
+
+void TransformFeedbackNULL::pause()
+{
+ UNIMPLEMENTED();
+}
+
+void TransformFeedbackNULL::resume()
+{
+ UNIMPLEMENTED();
+}
+
+void TransformFeedbackNULL::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
+{
+ UNIMPLEMENTED();
+}
+
+void TransformFeedbackNULL::bindIndexedBuffer(size_t index,
+ const OffsetBindingPointer<gl::Buffer> &binding)
+{
+ UNIMPLEMENTED();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.h b/gfx/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.h
new file mode 100644
index 000000000..477e81d85
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/TransformFeedbackNULL.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.
+//
+// TransformFeedbackNULL.h:
+// Defines the class interface for TransformFeedbackNULL, implementing TransformFeedbackImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_TRANSFORMFEEDBACKNULL_H_
+#define LIBANGLE_RENDERER_NULL_TRANSFORMFEEDBACKNULL_H_
+
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace rx
+{
+
+class TransformFeedbackNULL : public TransformFeedbackImpl
+{
+ public:
+ TransformFeedbackNULL(const gl::TransformFeedbackState &state);
+ ~TransformFeedbackNULL() override;
+
+ void begin(GLenum primitiveMode) override;
+ void end() override;
+ void pause() override;
+ void resume() override;
+
+ void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
+ void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_TRANSFORMFEEDBACKNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/null/VertexArrayNULL.cpp b/gfx/angle/src/libANGLE/renderer/null/VertexArrayNULL.cpp
new file mode 100644
index 000000000..95a835df1
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/VertexArrayNULL.cpp
@@ -0,0 +1,25 @@
+//
+// 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.
+//
+// VertexArrayNULL.cpp:
+// Implements the class methods for VertexArrayNULL.
+//
+
+#include "libANGLE/renderer/null/VertexArrayNULL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+VertexArrayNULL::VertexArrayNULL(const gl::VertexArrayState &data) : VertexArrayImpl(data)
+{
+}
+
+VertexArrayNULL::~VertexArrayNULL()
+{
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/null/VertexArrayNULL.h b/gfx/angle/src/libANGLE/renderer/null/VertexArrayNULL.h
new file mode 100644
index 000000000..f8b2b0490
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/null/VertexArrayNULL.h
@@ -0,0 +1,27 @@
+//
+// 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.
+//
+// VertexArrayNULL.h:
+// Defines the class interface for VertexArrayNULL, implementing VertexArrayImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_NULL_VERTEXARRAYNULL_H_
+#define LIBANGLE_RENDERER_NULL_VERTEXARRAYNULL_H_
+
+#include "libANGLE/renderer/VertexArrayImpl.h"
+
+namespace rx
+{
+
+class VertexArrayNULL : public VertexArrayImpl
+{
+ public:
+ VertexArrayNULL(const gl::VertexArrayState &data);
+ ~VertexArrayNULL() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_NULL_VERTEXARRAYNULL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/renderer_utils.cpp b/gfx/angle/src/libANGLE/renderer/renderer_utils.cpp
new file mode 100755
index 000000000..cc04dbb14
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/renderer_utils.cpp
@@ -0,0 +1,292 @@
+//
+// 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 "image_util/copyimage.h"
+#include "image_util/imageformats.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/Format.h"
+
+#include <string.h>
+
+namespace rx
+{
+
+namespace
+{
+typedef std::pair<gl::FormatType, ColorWriteFunction> FormatWriteFunctionPair;
+typedef std::map<gl::FormatType, ColorWriteFunction> FormatWriteFunctionMap;
+
+static inline void InsertFormatWriteFunctionMapping(FormatWriteFunctionMap *map,
+ GLenum format,
+ GLenum type,
+ ColorWriteFunction writeFunc)
+{
+ map->insert(FormatWriteFunctionPair(gl::FormatType(format, type), writeFunc));
+}
+
+static FormatWriteFunctionMap BuildFormatWriteFunctionMap()
+{
+ using namespace angle; // For image writing functions
+
+ FormatWriteFunctionMap map;
+
+ // clang-format off
+ // | Format | Type | Color write function |
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_BYTE, WriteColor<R8G8B8A8S, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, WriteColor<R4G4B4A4, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, WriteColor<R5G5B5A1, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor<R10G10B10A2, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_FLOAT, WriteColor<R32G32B32A32F, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT, WriteColor<R16G16B16A16F, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, WriteColor<R16G16B16A16F, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT,
+ WriteColor<R16G16B16A16, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_SHORT, WriteColor<R16G16B16A16S, GLfloat>);
+
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_BYTE, WriteColor<R8G8B8A8S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16B16A16, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_SHORT, WriteColor<R16G16B16A16S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32B32A32, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_INT, WriteColor<R32G32B32A32S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor<R10G10B10A2, GLuint> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_BYTE, WriteColor<R8G8B8S, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, WriteColor<R5G6B5, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, WriteColor<R11G11B10F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, WriteColor<R9G9B9E5, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_FLOAT, WriteColor<R32G32B32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT, WriteColor<R16G16B16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, WriteColor<R16G16B16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_SHORT,
+ WriteColor<R16G16B16, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_SHORT, WriteColor<R16G16B16S, GLfloat>);
+
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_BYTE, WriteColor<R8G8B8S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16B16, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_SHORT, WriteColor<R16G16B16S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32B32, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_INT, WriteColor<R32G32B32S, GLint> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_UNSIGNED_BYTE, WriteColor<R8G8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_BYTE, WriteColor<R8G8S, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_FLOAT, WriteColor<R32G32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT, WriteColor<R16G16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT_OES, WriteColor<R16G16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_UNSIGNED_SHORT, WriteColor<R16G16, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_SHORT, WriteColor<R16G16S, GLfloat>);
+
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_BYTE, WriteColor<R8G8S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_SHORT, WriteColor<R16G16S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_INT, WriteColor<R32G32S, GLint> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_UNSIGNED_BYTE, WriteColor<R8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_BYTE, WriteColor<R8S, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_FLOAT, WriteColor<R32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT, WriteColor<R16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT_OES, WriteColor<R16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_UNSIGNED_SHORT, WriteColor<R16, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_SHORT, WriteColor<R16S, GLfloat>);
+
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_BYTE, WriteColor<R8S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_SHORT, WriteColor<R16S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, WriteColor<R32, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_INT, WriteColor<R32S, GLint> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, WriteColor<L8A8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, WriteColor<L8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, WriteColor<A8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, WriteColor<L32A32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_FLOAT, WriteColor<L32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_FLOAT, WriteColor<A32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, WriteColor<L16A16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, WriteColor<L16A16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, WriteColor<L16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, WriteColor<L16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT, WriteColor<A16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, WriteColor<A16F, GLfloat> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, WriteColor<B8G8R8A8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, WriteColor<A4R4G4B4, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, WriteColor<A1R5G5B5, GLfloat> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLfloat> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, NULL );
+ InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, NULL );
+ InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, NULL );
+ InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, NULL );
+
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL );
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL );
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, NULL );
+
+ InsertFormatWriteFunctionMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, NULL );
+
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL );
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL );
+ // clang-format on
+
+ return map;
+}
+} // anonymous namespace
+
+PackPixelsParams::PackPixelsParams()
+ : format(GL_NONE), type(GL_NONE), outputPitch(0), packBuffer(nullptr), offset(0)
+{
+}
+
+PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn,
+ GLenum formatIn,
+ GLenum typeIn,
+ GLuint outputPitchIn,
+ const gl::PixelPackState &packIn,
+ ptrdiff_t offsetIn)
+ : area(areaIn),
+ format(formatIn),
+ type(typeIn),
+ outputPitch(outputPitchIn),
+ packBuffer(packIn.pixelBuffer.get()),
+ pack(packIn.alignment, packIn.reverseRowOrder),
+ offset(offsetIn)
+{
+}
+
+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;
+
+ if (params.pack.reverseRowOrder)
+ {
+ source += inputPitch * (params.area.height - 1);
+ inputPitch = -inputPitch;
+ }
+
+ const auto &sourceGLInfo = gl::GetInternalFormatInfo(sourceFormat.glInternalFormat);
+
+ if (sourceGLInfo.format == params.format && sourceGLInfo.type == params.type)
+ {
+ // Direct copy possible
+ for (int y = 0; y < params.area.height; ++y)
+ {
+ memcpy(destWithOffset + y * params.outputPitch, source + y * inputPitch,
+ params.area.width * sourceGLInfo.pixelBytes);
+ }
+ return;
+ }
+
+ ASSERT(sourceGLInfo.pixelBytes > 0);
+
+ gl::FormatType formatType(params.format, params.type);
+ ColorCopyFunction fastCopyFunc =
+ GetFastCopyFunction(sourceFormat.fastCopyFunctions, formatType);
+ GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(formatType.format, formatType.type);
+ const auto &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat);
+
+ if (fastCopyFunc)
+ {
+ // Fast copy is possible through some special function
+ for (int y = 0; y < params.area.height; ++y)
+ {
+ for (int x = 0; x < params.area.width; ++x)
+ {
+ uint8_t *dest =
+ destWithOffset + y * params.outputPitch + x * destFormatInfo.pixelBytes;
+ const uint8_t *src = source + y * inputPitch + x * sourceGLInfo.pixelBytes;
+
+ fastCopyFunc(src, dest);
+ }
+ }
+ return;
+ }
+
+ ColorWriteFunction colorWriteFunction = GetColorWriteFunction(formatType);
+
+ // 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),
+ "Unexpected size of gl::Color struct.");
+
+ const auto &colorReadFunction = sourceFormat.colorReadFunction;
+
+ for (int y = 0; y < params.area.height; ++y)
+ {
+ for (int x = 0; x < params.area.width; ++x)
+ {
+ uint8_t *dest = destWithOffset + y * params.outputPitch + x * destFormatInfo.pixelBytes;
+ const uint8_t *src = source + y * inputPitch + x * sourceGLInfo.pixelBytes;
+
+ // readFunc and writeFunc will be using the same type of color, CopyTexImage
+ // will not allow the copy otherwise.
+ colorReadFunction(src, temp);
+ colorWriteFunction(temp, dest);
+ }
+ }
+}
+
+ColorWriteFunction GetColorWriteFunction(const gl::FormatType &formatType)
+{
+ static const FormatWriteFunctionMap formatTypeMap = BuildFormatWriteFunctionMap();
+ auto iter = formatTypeMap.find(formatType);
+ ASSERT(iter != formatTypeMap.end());
+ if (iter != formatTypeMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+ColorCopyFunction GetFastCopyFunction(const FastCopyFunctionMap &fastCopyFunctions,
+ const gl::FormatType &formatType)
+{
+ return fastCopyFunctions.get(formatType);
+}
+
+bool FastCopyFunctionMap::has(const gl::FormatType &formatType) const
+{
+ return (get(formatType) != nullptr);
+}
+
+ColorCopyFunction FastCopyFunctionMap::get(const gl::FormatType &formatType) const
+{
+ for (size_t index = 0; index < mSize; ++index)
+ {
+ if (mData[index].format == formatType.format && mData[index].type == formatType.type)
+ {
+ return mData[index].func;
+ }
+ }
+
+ return nullptr;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/renderer_utils.h b/gfx/angle/src/libANGLE/renderer/renderer_utils.h
new file mode 100755
index 000000000..440548e9c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/renderer_utils.h
@@ -0,0 +1,124 @@
+//
+// 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 <map>
+
+#include "libANGLE/angletypes.h"
+
+namespace angle
+{
+struct Format;
+}
+
+namespace gl
+{
+struct FormatType;
+struct InternalFormat;
+}
+
+namespace rx
+{
+
+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 (*ColorReadFunction)(const uint8_t *source, uint8_t *dest);
+typedef void (*ColorWriteFunction)(const uint8_t *source, uint8_t *dest);
+typedef void (*ColorCopyFunction)(const uint8_t *source, uint8_t *dest);
+
+class FastCopyFunctionMap
+{
+ public:
+ struct Entry
+ {
+ GLenum format;
+ GLenum type;
+ ColorCopyFunction func;
+ };
+
+ constexpr FastCopyFunctionMap() : FastCopyFunctionMap(nullptr, 0) {}
+
+ constexpr FastCopyFunctionMap(const Entry *data, size_t size) : mSize(size), mData(data) {}
+
+ bool has(const gl::FormatType &formatType) const;
+ ColorCopyFunction get(const gl::FormatType &formatType) const;
+
+ private:
+ size_t mSize;
+ const Entry *mData;
+};
+
+struct PackPixelsParams
+{
+ PackPixelsParams();
+ PackPixelsParams(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLuint outputPitch,
+ const gl::PixelPackState &pack,
+ ptrdiff_t offset);
+
+ gl::Rectangle area;
+ GLenum format;
+ GLenum type;
+ GLuint outputPitch;
+ gl::Buffer *packBuffer;
+ gl::PixelPackState pack;
+ ptrdiff_t offset;
+};
+
+void PackPixels(const PackPixelsParams &params,
+ const angle::Format &sourceFormat,
+ int inputPitch,
+ const uint8_t *source,
+ uint8_t *destination);
+
+ColorWriteFunction GetColorWriteFunction(const gl::FormatType &formatType);
+ColorCopyFunction GetFastCopyFunction(const FastCopyFunctionMap &fastCopyFunctions,
+ const gl::FormatType &formatType);
+
+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);
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_RENDERER_UTILS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp
new file mode 100755
index 000000000..0b1babd5a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp
@@ -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.
+//
+// BufferVk.cpp:
+// Implements the class methods for BufferVk.
+//
+
+#include "libANGLE/renderer/vulkan/BufferVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+BufferVk::BufferVk(const gl::BufferState &state) : BufferImpl(state)
+{
+}
+
+BufferVk::~BufferVk()
+{
+}
+
+gl::Error BufferVk::setData(GLenum target, const void *data, size_t size, GLenum usage)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferVk::setSubData(GLenum target, const void *data, size_t size, size_t offset)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferVk::copySubData(BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferVk::map(GLenum access, GLvoid **mapPtr)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferVk::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferVk::unmap(GLboolean *result)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error BufferVk::getIndexRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ gl::IndexRange *outRange)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/BufferVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/BufferVk.h
new file mode 100755
index 000000000..27792962f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/BufferVk.h
@@ -0,0 +1,43 @@
+//
+// 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.
+//
+// BufferVk.h:
+// Defines the class interface for BufferVk, implementing BufferImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
+
+#include "libANGLE/renderer/BufferImpl.h"
+
+namespace rx
+{
+
+class BufferVk : public BufferImpl
+{
+ public:
+ BufferVk(const gl::BufferState &state);
+ ~BufferVk() override;
+
+ gl::Error setData(GLenum target, const void *data, size_t size, GLenum usage) override;
+ gl::Error setSubData(GLenum target, const void *data, size_t size, size_t offset) override;
+ gl::Error copySubData(BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size) override;
+ gl::Error map(GLenum access, GLvoid **mapPtr) override;
+ gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override;
+ gl::Error unmap(GLboolean *result) override;
+
+ gl::Error getIndexRange(GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ gl::IndexRange *outRange) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/CompilerVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/CompilerVk.cpp
new file mode 100755
index 000000000..d3f31eb0b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/CompilerVk.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.
+//
+// CompilerVk.cpp:
+// Implements the class methods for CompilerVk.
+//
+
+#include "libANGLE/renderer/vulkan/CompilerVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+CompilerVk::CompilerVk() : CompilerImpl()
+{
+}
+
+CompilerVk::~CompilerVk()
+{
+}
+
+gl::Error CompilerVk::release()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+ShShaderOutput CompilerVk::getTranslatorOutputType() const
+{
+ UNIMPLEMENTED();
+ return ShShaderOutput();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/CompilerVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/CompilerVk.h
new file mode 100755
index 000000000..2246a2711
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/CompilerVk.h
@@ -0,0 +1,32 @@
+//
+// 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.
+//
+// CompilerVk.h:
+// Defines the class interface for CompilerVk, implementing CompilerImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_COMPILERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_COMPILERVK_H_
+
+#include "libANGLE/renderer/CompilerImpl.h"
+
+namespace rx
+{
+
+class CompilerVk : public CompilerImpl
+{
+ public:
+ CompilerVk();
+ ~CompilerVk() override;
+
+ gl::Error release() override;
+
+ // TODO(jmadill): Expose translator built-in resources init method.
+ ShShaderOutput getTranslatorOutputType() const override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_COMPILERVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp
new file mode 100755
index 000000000..d0660bfdc
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp
@@ -0,0 +1,254 @@
+//
+// 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.
+//
+// ContextVk.cpp:
+// Implements the class methods for ContextVk.
+//
+
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/vulkan/BufferVk.h"
+#include "libANGLE/renderer/vulkan/CompilerVk.h"
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/DeviceVk.h"
+#include "libANGLE/renderer/vulkan/FenceNVVk.h"
+#include "libANGLE/renderer/vulkan/FenceSyncVk.h"
+#include "libANGLE/renderer/vulkan/FramebufferVk.h"
+#include "libANGLE/renderer/vulkan/ImageVk.h"
+#include "libANGLE/renderer/vulkan/ProgramVk.h"
+#include "libANGLE/renderer/vulkan/QueryVk.h"
+#include "libANGLE/renderer/vulkan/RenderbufferVk.h"
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+#include "libANGLE/renderer/vulkan/SamplerVk.h"
+#include "libANGLE/renderer/vulkan/ShaderVk.h"
+#include "libANGLE/renderer/vulkan/TextureVk.h"
+#include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
+#include "libANGLE/renderer/vulkan/VertexArrayVk.h"
+
+namespace rx
+{
+
+ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
+ : ContextImpl(state), mRenderer(renderer)
+{
+}
+
+ContextVk::~ContextVk()
+{
+}
+
+gl::Error ContextVk::initialize()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextVk::flush()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextVk::finish()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextVk::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextVk::drawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextVk::drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextVk::drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ContextVk::drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+GLenum ContextVk::getResetStatus()
+{
+ UNIMPLEMENTED();
+ return GL_NO_ERROR;
+}
+
+std::string ContextVk::getVendorString() const
+{
+ UNIMPLEMENTED();
+ return std::string();
+}
+
+std::string ContextVk::getRendererDescription() const
+{
+ UNIMPLEMENTED();
+ return std::string();
+}
+
+void ContextVk::insertEventMarker(GLsizei length, const char *marker)
+{
+ UNIMPLEMENTED();
+}
+
+void ContextVk::pushGroupMarker(GLsizei length, const char *marker)
+{
+ UNIMPLEMENTED();
+}
+
+void ContextVk::popGroupMarker()
+{
+ UNIMPLEMENTED();
+}
+
+void ContextVk::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
+{
+ UNIMPLEMENTED();
+}
+
+GLint ContextVk::getGPUDisjoint()
+{
+ UNIMPLEMENTED();
+ return GLint();
+}
+
+GLint64 ContextVk::getTimestamp()
+{
+ UNIMPLEMENTED();
+ return GLint64();
+}
+
+void ContextVk::onMakeCurrent(const gl::ContextState &data)
+{
+ UNIMPLEMENTED();
+}
+
+const gl::Caps &ContextVk::getNativeCaps() const
+{
+ return mRenderer->getNativeCaps();
+}
+
+const gl::TextureCapsMap &ContextVk::getNativeTextureCaps() const
+{
+ return mRenderer->getNativeTextureCaps();
+}
+
+const gl::Extensions &ContextVk::getNativeExtensions() const
+{
+ return mRenderer->getNativeExtensions();
+}
+
+const gl::Limitations &ContextVk::getNativeLimitations() const
+{
+ return mRenderer->getNativeLimitations();
+}
+
+CompilerImpl *ContextVk::createCompiler()
+{
+ return new CompilerVk();
+}
+
+ShaderImpl *ContextVk::createShader(const gl::ShaderState &state)
+{
+ return new ShaderVk(state);
+}
+
+ProgramImpl *ContextVk::createProgram(const gl::ProgramState &state)
+{
+ return new ProgramVk(state);
+}
+
+FramebufferImpl *ContextVk::createFramebuffer(const gl::FramebufferState &state)
+{
+ return new FramebufferVk(state);
+}
+
+TextureImpl *ContextVk::createTexture(const gl::TextureState &state)
+{
+ return new TextureVk(state);
+}
+
+RenderbufferImpl *ContextVk::createRenderbuffer()
+{
+ return new RenderbufferVk();
+}
+
+BufferImpl *ContextVk::createBuffer(const gl::BufferState &state)
+{
+ return new BufferVk(state);
+}
+
+VertexArrayImpl *ContextVk::createVertexArray(const gl::VertexArrayState &state)
+{
+ return new VertexArrayVk(state);
+}
+
+QueryImpl *ContextVk::createQuery(GLenum type)
+{
+ return new QueryVk(type);
+}
+
+FenceNVImpl *ContextVk::createFenceNV()
+{
+ return new FenceNVVk();
+}
+
+FenceSyncImpl *ContextVk::createFenceSync()
+{
+ return new FenceSyncVk();
+}
+
+TransformFeedbackImpl *ContextVk::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+ return new TransformFeedbackVk(state);
+}
+
+SamplerImpl *ContextVk::createSampler()
+{
+ return new SamplerVk();
+}
+
+std::vector<PathImpl *> ContextVk::createPaths(GLsizei)
+{
+ return std::vector<PathImpl *>();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/ContextVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/ContextVk.h
new file mode 100755
index 000000000..64e85c984
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/ContextVk.h
@@ -0,0 +1,126 @@
+//
+// 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.
+//
+// ContextVk.h:
+// Defines the class interface for ContextVk, implementing ContextImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
+#define LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
+
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace rx
+{
+class RendererVk;
+
+class ContextVk : public ContextImpl
+{
+ public:
+ ContextVk(const gl::ContextState &state, RendererVk *renderer);
+ ~ContextVk() override;
+
+ gl::Error initialize() override;
+
+ // Flush and finish.
+ gl::Error flush() override;
+ gl::Error finish() override;
+
+ // Drawing methods.
+ gl::Error drawArrays(GLenum mode, GLint first, GLsizei count) override;
+ gl::Error drawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) override;
+
+ gl::Error drawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange) override;
+ gl::Error drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei instances,
+ const gl::IndexRange &indexRange) override;
+ gl::Error drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const gl::IndexRange &indexRange) override;
+
+ // Device loss
+ GLenum getResetStatus() override;
+
+ // Vendor and description strings.
+ std::string getVendorString() const override;
+ std::string getRendererDescription() const override;
+
+ // Debug markers.
+ void insertEventMarker(GLsizei length, const char *marker) override;
+ void pushGroupMarker(GLsizei length, const char *marker) override;
+ void popGroupMarker() override;
+
+ // State sync with dirty bits.
+ void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) override;
+
+ // Disjoint timer queries
+ GLint getGPUDisjoint() override;
+ GLint64 getTimestamp() override;
+
+ // Context switching
+ void onMakeCurrent(const gl::ContextState &data) override;
+
+ // Native capabilities, unmodified by gl::Context.
+ const gl::Caps &getNativeCaps() const override;
+ const gl::TextureCapsMap &getNativeTextureCaps() const override;
+ const gl::Extensions &getNativeExtensions() const override;
+ const gl::Limitations &getNativeLimitations() const override;
+
+ // Shader creation
+ CompilerImpl *createCompiler() override;
+ ShaderImpl *createShader(const gl::ShaderState &state) override;
+ ProgramImpl *createProgram(const gl::ProgramState &state) override;
+
+ // Framebuffer creation
+ FramebufferImpl *createFramebuffer(const gl::FramebufferState &state) override;
+
+ // Texture creation
+ TextureImpl *createTexture(const gl::TextureState &state) override;
+
+ // Renderbuffer creation
+ RenderbufferImpl *createRenderbuffer() override;
+
+ // Buffer creation
+ BufferImpl *createBuffer(const gl::BufferState &state) override;
+
+ // Vertex Array creation
+ VertexArrayImpl *createVertexArray(const gl::VertexArrayState &state) override;
+
+ // Query and Fence creation
+ QueryImpl *createQuery(GLenum type) override;
+ FenceNVImpl *createFenceNV() override;
+ FenceSyncImpl *createFenceSync() override;
+
+ // Transform Feedback creation
+ TransformFeedbackImpl *createTransformFeedback(
+ const gl::TransformFeedbackState &state) override;
+
+ // Sampler object creation
+ SamplerImpl *createSampler() override;
+
+ // Path object creation
+ std::vector<PathImpl *> createPaths(GLsizei) override;
+
+ private:
+ RendererVk *mRenderer;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/DeviceVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/DeviceVk.cpp
new file mode 100755
index 000000000..f4f60b90b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/DeviceVk.cpp
@@ -0,0 +1,48 @@
+//
+// 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.
+//
+// DeviceVk.cpp:
+// Implements the class methods for DeviceVk.
+//
+
+#include "libANGLE/renderer/vulkan/DeviceVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+DeviceVk::DeviceVk() : DeviceImpl()
+{
+}
+
+DeviceVk::~DeviceVk()
+{
+}
+
+egl::Error DeviceVk::getDevice(void **outValue)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+EGLint DeviceVk::getType()
+{
+ UNIMPLEMENTED();
+ return EGLint();
+}
+
+void DeviceVk::generateExtensions(egl::DeviceExtensions *outExtensions) const
+{
+ UNIMPLEMENTED();
+}
+
+bool DeviceVk::deviceExternallySourced()
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/DeviceVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/DeviceVk.h
new file mode 100755
index 000000000..4613c1751
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/DeviceVk.h
@@ -0,0 +1,32 @@
+//
+// 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.
+//
+// DeviceVk.h:
+// Defines the class interface for DeviceVk, implementing DeviceImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_DEVICEVK_H_
+#define LIBANGLE_RENDERER_VULKAN_DEVICEVK_H_
+
+#include "libANGLE/renderer/DeviceImpl.h"
+
+namespace rx
+{
+
+class DeviceVk : public DeviceImpl
+{
+ public:
+ DeviceVk();
+ ~DeviceVk() override;
+
+ egl::Error getDevice(void **outValue) override;
+ EGLint getType() override;
+ void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
+ bool deviceExternallySourced() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_DEVICEVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp
new file mode 100755
index 000000000..2c652ce3c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/DisplayVk.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.
+//
+// DisplayVk.cpp:
+// Implements the class methods for DisplayVk.
+//
+
+#include "libANGLE/renderer/vulkan/DisplayVk.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+
+namespace rx
+{
+
+DisplayVk::DisplayVk() : DisplayImpl(), mRenderer(nullptr)
+{
+}
+
+DisplayVk::~DisplayVk()
+{
+}
+
+egl::Error DisplayVk::initialize(egl::Display *display)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+void DisplayVk::terminate()
+{
+ UNIMPLEMENTED();
+}
+
+egl::Error DisplayVk::makeCurrent(egl::Surface *drawSurface,
+ egl::Surface *readSurface,
+ gl::Context *context)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::ConfigSet DisplayVk::generateConfigs()
+{
+ UNIMPLEMENTED();
+ return egl::ConfigSet();
+}
+
+bool DisplayVk::testDeviceLost()
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+egl::Error DisplayVk::restoreLostDevice()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+bool DisplayVk::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+std::string DisplayVk::getVendorString() const
+{
+ UNIMPLEMENTED();
+ return std::string();
+}
+
+egl::Error DisplayVk::getDevice(DeviceImpl **device)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error DisplayVk::waitClient() const
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error DisplayVk::waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+SurfaceImpl *DisplayVk::createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return static_cast<SurfaceImpl *>(0);
+}
+
+SurfaceImpl *DisplayVk::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return static_cast<SurfaceImpl *>(0);
+}
+
+SurfaceImpl *DisplayVk::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return static_cast<SurfaceImpl *>(0);
+}
+
+SurfaceImpl *DisplayVk::createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return static_cast<SurfaceImpl *>(0);
+}
+
+ImageImpl *DisplayVk::createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return static_cast<ImageImpl *>(0);
+}
+
+ContextImpl *DisplayVk::createContext(const gl::ContextState &state)
+{
+ return new ContextVk(state, mRenderer);
+}
+
+StreamProducerImpl *DisplayVk::createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return static_cast<StreamProducerImpl *>(0);
+}
+
+gl::Version DisplayVk::getMaxSupportedESVersion() const
+{
+ UNIMPLEMENTED();
+ return gl::Version(0, 0);
+}
+
+void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ UNIMPLEMENTED();
+}
+
+void DisplayVk::generateCaps(egl::Caps *outCaps) const
+{
+ UNIMPLEMENTED();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/DisplayVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/DisplayVk.h
new file mode 100755
index 000000000..26eab5139
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/DisplayVk.h
@@ -0,0 +1,85 @@
+//
+// 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.
+//
+// DisplayVk.h:
+// Defines the class interface for DisplayVk, implementing DisplayImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_
+#define LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_
+
+#include "libANGLE/renderer/DisplayImpl.h"
+
+namespace rx
+{
+class RendererVk;
+
+class DisplayVk : public DisplayImpl
+{
+ public:
+ DisplayVk();
+ ~DisplayVk() override;
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ egl::Error makeCurrent(egl::Surface *drawSurface,
+ egl::Surface *readSurface,
+ gl::Context *context) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() override;
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+ std::string getVendorString() const override;
+
+ egl::Error getDevice(DeviceImpl **device) override;
+
+ egl::Error waitClient() const override;
+ egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const override;
+
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ ImageImpl *createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs) override;
+
+ ContextImpl *createContext(const gl::ContextState &state) override;
+
+ StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) override;
+ gl::Version getMaxSupportedESVersion() const override;
+
+ private:
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+ void generateCaps(egl::Caps *outCaps) const override;
+
+ RendererVk *mRenderer;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/FenceNVVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/FenceNVVk.cpp
new file mode 100755
index 000000000..c46bd0121
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/FenceNVVk.cpp
@@ -0,0 +1,43 @@
+//
+// 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.
+//
+// FenceNVVk.cpp:
+// Implements the class methods for FenceNVVk.
+//
+
+#include "libANGLE/renderer/vulkan/FenceNVVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+FenceNVVk::FenceNVVk() : FenceNVImpl()
+{
+}
+
+FenceNVVk::~FenceNVVk()
+{
+}
+
+gl::Error FenceNVVk::set(GLenum condition)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceNVVk::test(GLboolean *outFinished)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceNVVk::finish()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/FenceNVVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/FenceNVVk.h
new file mode 100755
index 000000000..be054715c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/FenceNVVk.h
@@ -0,0 +1,31 @@
+//
+// 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.
+//
+// FenceNVVk.h:
+// Defines the class interface for FenceNVVk, implementing FenceNVImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_FENCENVVK_H_
+#define LIBANGLE_RENDERER_VULKAN_FENCENVVK_H_
+
+#include "libANGLE/renderer/FenceNVImpl.h"
+
+namespace rx
+{
+
+class FenceNVVk : public FenceNVImpl
+{
+ public:
+ FenceNVVk();
+ ~FenceNVVk() override;
+
+ gl::Error set(GLenum condition) override;
+ gl::Error test(GLboolean *outFinished) override;
+ gl::Error finish() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_FENCENVVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.cpp
new file mode 100755
index 000000000..d27f13088
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.cpp
@@ -0,0 +1,49 @@
+//
+// 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.
+//
+// FenceSyncVk.cpp:
+// Implements the class methods for FenceSyncVk.
+//
+
+#include "libANGLE/renderer/vulkan/FenceSyncVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+FenceSyncVk::FenceSyncVk() : FenceSyncImpl()
+{
+}
+
+FenceSyncVk::~FenceSyncVk()
+{
+}
+
+gl::Error FenceSyncVk::set(GLenum condition, GLbitfield flags)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceSyncVk::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceSyncVk::serverWait(GLbitfield flags, GLuint64 timeout)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FenceSyncVk::getStatus(GLint *outResult)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.h
new file mode 100755
index 000000000..ab9a10720
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/FenceSyncVk.h
@@ -0,0 +1,32 @@
+//
+// 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.
+//
+// FenceSyncVk.h:
+// Defines the class interface for FenceSyncVk, implementing FenceSyncImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_FENCESYNCVK_H_
+#define LIBANGLE_RENDERER_VULKAN_FENCESYNCVK_H_
+
+#include "libANGLE/renderer/FenceSyncImpl.h"
+
+namespace rx
+{
+
+class FenceSyncVk : public FenceSyncImpl
+{
+ public:
+ FenceSyncVk();
+ ~FenceSyncVk() override;
+
+ gl::Error set(GLenum condition, GLbitfield flags) override;
+ gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override;
+ gl::Error serverWait(GLbitfield flags, GLuint64 timeout) override;
+ gl::Error getStatus(GLint *outResult) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_FENCESYNCVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
new file mode 100755
index 000000000..e351dea93
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -0,0 +1,131 @@
+//
+// 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.
+//
+// FramebufferVk.cpp:
+// Implements the class methods for FramebufferVk.
+//
+
+#include "libANGLE/renderer/vulkan/FramebufferVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+FramebufferVk::FramebufferVk(const gl::FramebufferState &state) : FramebufferImpl(state)
+{
+}
+
+FramebufferVk::~FramebufferVk()
+{
+}
+
+gl::Error FramebufferVk::discard(size_t count, const GLenum *attachments)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::invalidate(size_t count, const GLenum *attachments)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::invalidateSub(size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::clear(ContextImpl *context, GLbitfield mask)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::clearBufferfv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::clearBufferuiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::clearBufferiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::clearBufferfi(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+GLenum FramebufferVk::getImplementationColorReadFormat() const
+{
+ UNIMPLEMENTED();
+ return GLenum();
+}
+
+GLenum FramebufferVk::getImplementationColorReadType() const
+{
+ UNIMPLEMENTED();
+ return GLenum();
+}
+
+gl::Error FramebufferVk::readPixels(ContextImpl *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels) const
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error FramebufferVk::blit(ContextImpl *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+bool FramebufferVk::checkStatus() const
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+void FramebufferVk::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
+{
+ UNIMPLEMENTED();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/FramebufferVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/FramebufferVk.h
new file mode 100755
index 000000000..9eb4abf92
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/FramebufferVk.h
@@ -0,0 +1,70 @@
+//
+// 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.
+//
+// FramebufferVk.h:
+// Defines the class interface for FramebufferVk, implementing FramebufferImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_FRAMEBUFFERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_FRAMEBUFFERVK_H_
+
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace rx
+{
+
+class FramebufferVk : public FramebufferImpl
+{
+ public:
+ FramebufferVk(const gl::FramebufferState &state);
+ ~FramebufferVk() override;
+
+ gl::Error discard(size_t count, const GLenum *attachments) override;
+ gl::Error invalidate(size_t count, const GLenum *attachments) override;
+ gl::Error invalidateSub(size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area) override;
+
+ gl::Error clear(ContextImpl *context, GLbitfield mask) override;
+ gl::Error clearBufferfv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values) override;
+ gl::Error clearBufferuiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values) override;
+ gl::Error clearBufferiv(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values) override;
+ gl::Error clearBufferfi(ContextImpl *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil) override;
+
+ GLenum getImplementationColorReadFormat() const override;
+ GLenum getImplementationColorReadType() const override;
+ gl::Error readPixels(ContextImpl *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels) const override;
+
+ gl::Error blit(ContextImpl *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter) override;
+
+ bool checkStatus() const override;
+
+ void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_FRAMEBUFFERVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp
new file mode 100755
index 000000000..0956a5efc
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/ImageVk.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.
+//
+// ImageVk.cpp:
+// Implements the class methods for ImageVk.
+//
+
+#include "libANGLE/renderer/vulkan/ImageVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ImageVk::ImageVk() : ImageImpl()
+{
+}
+
+ImageVk::~ImageVk()
+{
+}
+
+egl::Error ImageVk::initialize()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+gl::Error ImageVk::orphan(egl::ImageSibling *sibling)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/ImageVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/ImageVk.h
new file mode 100755
index 000000000..bc25e6122
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/ImageVk.h
@@ -0,0 +1,30 @@
+//
+// 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.
+//
+// ImageVk.h:
+// Defines the class interface for ImageVk, implementing ImageImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_IMAGEVK_H_
+#define LIBANGLE_RENDERER_VULKAN_IMAGEVK_H_
+
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace rx
+{
+
+class ImageVk : public ImageImpl
+{
+ public:
+ ImageVk();
+ ~ImageVk() override;
+ egl::Error initialize() override;
+
+ gl::Error orphan(egl::ImageSibling *sibling) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_IMAGEVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp
new file mode 100755
index 000000000..a83f826e7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp
@@ -0,0 +1,212 @@
+//
+// 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.
+//
+// ProgramVk.cpp:
+// Implements the class methods for ProgramVk.
+//
+
+#include "libANGLE/renderer/vulkan/ProgramVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ProgramVk::ProgramVk(const gl::ProgramState &state) : ProgramImpl(state)
+{
+}
+
+ProgramVk::~ProgramVk()
+{
+}
+
+LinkResult ProgramVk::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error ProgramVk::save(gl::BinaryOutputStream *stream)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+void ProgramVk::setBinaryRetrievableHint(bool retrievable)
+{
+ UNIMPLEMENTED();
+}
+
+LinkResult ProgramVk::link(const gl::ContextState &data, gl::InfoLog &infoLog)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
+{
+ UNIMPLEMENTED();
+ return GLboolean();
+}
+
+void ProgramVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+{
+ UNIMPLEMENTED();
+}
+
+bool ProgramVk::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+bool ProgramVk::getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ UNIMPLEMENTED();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/ProgramVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/ProgramVk.h
new file mode 100755
index 000000000..8d8a1f7ca
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/ProgramVk.h
@@ -0,0 +1,100 @@
+//
+// 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.
+//
+// ProgramVk.h:
+// Defines the class interface for ProgramVk, implementing ProgramImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_
+#define LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_
+
+#include "libANGLE/renderer/ProgramImpl.h"
+
+namespace rx
+{
+
+class ProgramVk : public ProgramImpl
+{
+ public:
+ ProgramVk(const gl::ProgramState &state);
+ ~ProgramVk() override;
+
+ LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
+ gl::Error save(gl::BinaryOutputStream *stream) override;
+ void setBinaryRetrievableHint(bool retrievable) override;
+
+ LinkResult link(const gl::ContextState &data, gl::InfoLog &infoLog) override;
+ GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
+
+ 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;
+
+ // TODO: synchronize in syncState when dirty bits exist.
+ void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
+
+ // May only be called after a successful link operation.
+ // Return false for inactive blocks.
+ bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
+
+ // May only be called after a successful link operation.
+ // Returns false for inactive members.
+ bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const override;
+
+ void setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp
new file mode 100755
index 000000000..01fd0c45a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp
@@ -0,0 +1,73 @@
+//
+// 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.
+//
+// QueryVk.cpp:
+// Implements the class methods for QueryVk.
+//
+
+#include "libANGLE/renderer/vulkan/QueryVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+QueryVk::QueryVk(GLenum type) : QueryImpl(type)
+{
+}
+
+QueryVk::~QueryVk()
+{
+}
+
+gl::Error QueryVk::begin()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::end()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::queryCounter()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::getResult(GLint *params)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::getResult(GLuint *params)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::getResult(GLint64 *params)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::getResult(GLuint64 *params)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error QueryVk::isResultAvailable(bool *available)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/QueryVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/QueryVk.h
new file mode 100755
index 000000000..7c9273400
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/QueryVk.h
@@ -0,0 +1,36 @@
+//
+// 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.
+//
+// QueryVk.h:
+// Defines the class interface for QueryVk, implementing QueryImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_QUERYVK_H_
+#define LIBANGLE_RENDERER_VULKAN_QUERYVK_H_
+
+#include "libANGLE/renderer/QueryImpl.h"
+
+namespace rx
+{
+
+class QueryVk : public QueryImpl
+{
+ public:
+ QueryVk(GLenum type);
+ ~QueryVk() override;
+
+ gl::Error begin() override;
+ gl::Error end() override;
+ gl::Error queryCounter() override;
+ gl::Error getResult(GLint *params) override;
+ gl::Error getResult(GLuint *params) override;
+ gl::Error getResult(GLint64 *params) override;
+ gl::Error getResult(GLuint64 *params) override;
+ gl::Error isResultAvailable(bool *available) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_QUERYVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
new file mode 100755
index 000000000..18f394700
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
@@ -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.
+//
+// RenderbufferVk.cpp:
+// Implements the class methods for RenderbufferVk.
+//
+
+#include "libANGLE/renderer/vulkan/RenderbufferVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+RenderbufferVk::RenderbufferVk() : RenderbufferImpl()
+{
+}
+
+RenderbufferVk::~RenderbufferVk()
+{
+}
+
+gl::Error RenderbufferVk::setStorage(GLenum internalformat, size_t width, size_t height)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error RenderbufferVk::setStorageMultisample(size_t samples,
+ GLenum internalformat,
+ size_t width,
+ size_t height)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error RenderbufferVk::setStorageEGLImageTarget(egl::Image *image)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error RenderbufferVk::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h
new file mode 100755
index 000000000..54c5f866e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h
@@ -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.
+//
+// RenderbufferVk.h:
+// Defines the class interface for RenderbufferVk, implementing RenderbufferImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_RENDERBUFFERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_RENDERBUFFERVK_H_
+
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+
+class RenderbufferVk : public RenderbufferImpl
+{
+ public:
+ RenderbufferVk();
+ ~RenderbufferVk() override;
+
+ gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override;
+ gl::Error setStorageMultisample(size_t samples,
+ GLenum internalformat,
+ size_t width,
+ size_t height) override;
+ gl::Error setStorageEGLImageTarget(egl::Image *image) override;
+
+ gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_RENDERBUFFERVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp
new file mode 100755
index 000000000..a9dc1f679
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -0,0 +1,66 @@
+//
+// 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.
+//
+// RendererVk.cpp:
+// Implements the class methods for RendererVk.
+//
+
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+RendererVk::RendererVk() : mCapsInitialized(false)
+{
+}
+
+RendererVk::~RendererVk()
+{
+}
+
+void RendererVk::ensureCapsInitialized() const
+{
+ if (!mCapsInitialized)
+ {
+ generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
+ mCapsInitialized = true;
+ }
+}
+
+void RendererVk::generateCaps(gl::Caps * /*outCaps*/,
+ gl::TextureCapsMap * /*outTextureCaps*/,
+ gl::Extensions * /*outExtensions*/,
+ gl::Limitations * /* outLimitations */) const
+{
+ // TODO(jmadill): Caps
+}
+
+const gl::Caps &RendererVk::getNativeCaps() const
+{
+ ensureCapsInitialized();
+ return mNativeCaps;
+}
+
+const gl::TextureCapsMap &RendererVk::getNativeTextureCaps() const
+{
+ ensureCapsInitialized();
+ return mNativeTextureCaps;
+}
+
+const gl::Extensions &RendererVk::getNativeExtensions() const
+{
+ ensureCapsInitialized();
+ return mNativeExtensions;
+}
+
+const gl::Limitations &RendererVk::getNativeLimitations() const
+{
+ ensureCapsInitialized();
+ return mNativeLimitations;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/RendererVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/RendererVk.h
new file mode 100755
index 000000000..8a7489496
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/RendererVk.h
@@ -0,0 +1,46 @@
+//
+// 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.
+//
+// RendererVk.h:
+// Defines the class interface for RendererVk.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Caps.h"
+
+namespace rx
+{
+
+class RendererVk : angle::NonCopyable
+{
+ public:
+ RendererVk();
+ ~RendererVk();
+
+ const gl::Caps &getNativeCaps() const;
+ const gl::TextureCapsMap &getNativeTextureCaps() const;
+ const gl::Extensions &getNativeExtensions() const;
+ const gl::Limitations &getNativeLimitations() const;
+
+ private:
+ void ensureCapsInitialized() const;
+ void generateCaps(gl::Caps *outCaps,
+ gl::TextureCapsMap *outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations *outLimitations) const;
+
+ mutable bool mCapsInitialized;
+ mutable gl::Caps mNativeCaps;
+ mutable gl::TextureCapsMap mNativeTextureCaps;
+ mutable gl::Extensions mNativeExtensions;
+ mutable gl::Limitations mNativeLimitations;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/SamplerVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/SamplerVk.cpp
new file mode 100755
index 000000000..00bb81b6e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/SamplerVk.cpp
@@ -0,0 +1,25 @@
+//
+// 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.
+//
+// SamplerVk.cpp:
+// Implements the class methods for SamplerVk.
+//
+
+#include "libANGLE/renderer/vulkan/SamplerVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+SamplerVk::SamplerVk() : SamplerImpl()
+{
+}
+
+SamplerVk::~SamplerVk()
+{
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/SamplerVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/SamplerVk.h
new file mode 100755
index 000000000..1111f4095
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/SamplerVk.h
@@ -0,0 +1,27 @@
+//
+// 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.
+//
+// SamplerVk.h:
+// Defines the class interface for SamplerVk, implementing SamplerImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_SAMPLERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_SAMPLERVK_H_
+
+#include "libANGLE/renderer/SamplerImpl.h"
+
+namespace rx
+{
+
+class SamplerVk : public SamplerImpl
+{
+ public:
+ SamplerVk();
+ ~SamplerVk() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_SAMPLERVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/ShaderVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/ShaderVk.cpp
new file mode 100755
index 000000000..8bece9b45
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/ShaderVk.cpp
@@ -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.
+//
+// ShaderVk.cpp:
+// Implements the class methods for ShaderVk.
+//
+
+#include "libANGLE/renderer/vulkan/ShaderVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ShaderVk::ShaderVk(const gl::ShaderState &data) : ShaderImpl(data)
+{
+}
+
+ShaderVk::~ShaderVk()
+{
+}
+
+ShCompileOptions ShaderVk::prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string *sourcePath)
+{
+ UNIMPLEMENTED();
+ return int();
+}
+
+bool ShaderVk::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
+{
+ UNIMPLEMENTED();
+ return bool();
+}
+
+std::string ShaderVk::getDebugInfo() const
+{
+ UNIMPLEMENTED();
+ return std::string();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/ShaderVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/ShaderVk.h
new file mode 100755
index 000000000..10f8fe423
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/ShaderVk.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.
+//
+// ShaderVk.h:
+// Defines the class interface for ShaderVk, implementing ShaderImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_SHADERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_SHADERVK_H_
+
+#include "libANGLE/renderer/ShaderImpl.h"
+
+namespace rx
+{
+
+class ShaderVk : public ShaderImpl
+{
+ public:
+ ShaderVk(const gl::ShaderState &data);
+ ~ShaderVk() override;
+
+ // Returns additional sh::Compile options.
+ ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string *sourcePath) override;
+ // Returns success for compiling on the driver. Returns success.
+ bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override;
+
+ std::string getDebugInfo() const override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_SHADERVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
new file mode 100755
index 000000000..06732c2c8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
@@ -0,0 +1,103 @@
+//
+// 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.
+//
+// SurfaceVk.cpp:
+// Implements the class methods for SurfaceVk.
+//
+
+#include "libANGLE/renderer/vulkan/SurfaceVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+SurfaceVk::SurfaceVk(const egl::SurfaceState &surfaceState) : SurfaceImpl(surfaceState)
+{
+}
+
+SurfaceVk::~SurfaceVk()
+{
+}
+
+egl::Error SurfaceVk::initialize()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+FramebufferImpl *SurfaceVk::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+ UNIMPLEMENTED();
+ return static_cast<FramebufferImpl *>(0);
+}
+
+egl::Error SurfaceVk::swap()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error SurfaceVk::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error SurfaceVk::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error SurfaceVk::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+egl::Error SurfaceVk::releaseTexImage(EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_ACCESS);
+}
+
+void SurfaceVk::setSwapInterval(EGLint interval)
+{
+ UNIMPLEMENTED();
+}
+
+EGLint SurfaceVk::getWidth() const
+{
+ UNIMPLEMENTED();
+ return EGLint();
+}
+
+EGLint SurfaceVk::getHeight() const
+{
+ UNIMPLEMENTED();
+ return EGLint();
+}
+
+EGLint SurfaceVk::isPostSubBufferSupported() const
+{
+ UNIMPLEMENTED();
+ return EGLint();
+}
+
+EGLint SurfaceVk::getSwapBehavior() const
+{
+ UNIMPLEMENTED();
+ return EGLint();
+}
+
+gl::Error SurfaceVk::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h
new file mode 100755
index 000000000..f7d54e4a7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h
@@ -0,0 +1,46 @@
+//
+// 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.
+//
+// SurfaceVk.h:
+// Defines the class interface for SurfaceVk, implementing SurfaceImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_
+#define LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_
+
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+namespace rx
+{
+
+class SurfaceVk : public SurfaceImpl
+{
+ public:
+ SurfaceVk(const egl::SurfaceState &surfaceState);
+ ~SurfaceVk() override;
+
+ egl::Error initialize() override;
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ // width and height can change with client window resizing
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
new file mode 100755
index 000000000..a2220fcad
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -0,0 +1,150 @@
+//
+// 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.
+//
+// TextureVk.cpp:
+// Implements the class methods for TextureVk.
+//
+
+#include "libANGLE/renderer/vulkan/TextureVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+TextureVk::TextureVk(const gl::TextureState &state) : TextureImpl(state)
+{
+}
+
+TextureVk::~TextureVk()
+{
+}
+
+gl::Error TextureVk::setImage(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::setSubImage(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::setCompressedImage(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::setCompressedSubImage(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::copyImage(GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::copySubImage(GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::setStorage(GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::setEGLImageTarget(GLenum target, egl::Image *image)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::setImageExternal(GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error TextureVk::generateMipmap()
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+void TextureVk::setBaseLevel(GLuint baseLevel)
+{
+ UNIMPLEMENTED();
+}
+
+void TextureVk::bindTexImage(egl::Surface *surface)
+{
+ UNIMPLEMENTED();
+}
+
+void TextureVk::releaseTexImage()
+{
+ UNIMPLEMENTED();
+}
+
+gl::Error TextureVk::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+void TextureVk::syncState(const gl::Texture::DirtyBits &dirtyBits)
+{
+ UNIMPLEMENTED();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/TextureVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/TextureVk.h
new file mode 100755
index 000000000..d5b9106c7
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/TextureVk.h
@@ -0,0 +1,92 @@
+//
+// 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.
+//
+// TextureVk.h:
+// Defines the class interface for TextureVk, implementing TextureImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
+#define LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
+
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace rx
+{
+
+class TextureVk : public TextureImpl
+{
+ public:
+ TextureVk(const gl::TextureState &state);
+ ~TextureVk() override;
+
+ gl::Error setImage(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+ gl::Error setSubImage(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ gl::Error copyImage(GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorage(GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+
+ gl::Error setImageExternal(GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+
+ gl::Error generateMipmap() override;
+
+ void setBaseLevel(GLuint baseLevel) override;
+
+ void bindTexImage(egl::Surface *surface) override;
+ void releaseTexImage() override;
+
+ gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ FramebufferAttachmentRenderTarget **rtOut) override;
+
+ void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp
new file mode 100755
index 000000000..ea445c753
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp
@@ -0,0 +1,57 @@
+//
+// 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.
+//
+// TransformFeedbackVk.cpp:
+// Implements the class methods for TransformFeedbackVk.
+//
+
+#include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+TransformFeedbackVk::TransformFeedbackVk(const gl::TransformFeedbackState &state)
+ : TransformFeedbackImpl(state)
+{
+}
+
+TransformFeedbackVk::~TransformFeedbackVk()
+{
+}
+
+void TransformFeedbackVk::begin(GLenum primitiveMode)
+{
+ UNIMPLEMENTED();
+}
+
+void TransformFeedbackVk::end()
+{
+ UNIMPLEMENTED();
+}
+
+void TransformFeedbackVk::pause()
+{
+ UNIMPLEMENTED();
+}
+
+void TransformFeedbackVk::resume()
+{
+ UNIMPLEMENTED();
+}
+
+void TransformFeedbackVk::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
+{
+ UNIMPLEMENTED();
+}
+
+void TransformFeedbackVk::bindIndexedBuffer(size_t index,
+ const OffsetBindingPointer<gl::Buffer> &binding)
+{
+ UNIMPLEMENTED();
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h
new file mode 100755
index 000000000..ed8522c9c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/TransformFeedbackVk.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.
+//
+// TransformFeedbackVk.h:
+// Defines the class interface for TransformFeedbackVk, implementing TransformFeedbackImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_TRANSFORMFEEDBACKVK_H_
+#define LIBANGLE_RENDERER_VULKAN_TRANSFORMFEEDBACKVK_H_
+
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace rx
+{
+
+class TransformFeedbackVk : public TransformFeedbackImpl
+{
+ public:
+ TransformFeedbackVk(const gl::TransformFeedbackState &state);
+ ~TransformFeedbackVk() override;
+
+ void begin(GLenum primitiveMode) override;
+ void end() override;
+ void pause() override;
+ void resume() override;
+
+ void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
+ void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_TRANSFORMFEEDBACKVK_H_
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/gfx/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
new file mode 100755
index 000000000..9f639b951
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
@@ -0,0 +1,25 @@
+//
+// 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.
+//
+// VertexArrayVk.cpp:
+// Implements the class methods for VertexArrayVk.
+//
+
+#include "libANGLE/renderer/vulkan/VertexArrayVk.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &data) : VertexArrayImpl(data)
+{
+}
+
+VertexArrayVk::~VertexArrayVk()
+{
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h b/gfx/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h
new file mode 100755
index 000000000..9340d2757
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h
@@ -0,0 +1,27 @@
+//
+// 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.
+//
+// VertexArrayVk.h:
+// Defines the class interface for VertexArrayVk, implementing VertexArrayImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_
+#define LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_
+
+#include "libANGLE/renderer/VertexArrayImpl.h"
+
+namespace rx
+{
+
+class VertexArrayVk : public VertexArrayImpl
+{
+ public:
+ VertexArrayVk(const gl::VertexArrayState &data);
+ ~VertexArrayVk() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_
diff --git a/gfx/angle/src/libANGLE/signal_utils.cpp b/gfx/angle/src/libANGLE/signal_utils.cpp
new file mode 100755
index 000000000..62d45b953
--- /dev/null
+++ b/gfx/angle/src/libANGLE/signal_utils.cpp
@@ -0,0 +1,103 @@
+//
+// 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.
+//
+// signal_utils:
+// Helper classes for tracking dependent state changes between objects.
+// These changes are signaled to the dependent class via channels.
+
+#include "libANGLE/signal_utils.h"
+
+#include <algorithm>
+
+#include "common/debug.h"
+
+namespace angle
+{
+
+BroadcastChannel::BroadcastChannel()
+{
+}
+
+BroadcastChannel::~BroadcastChannel()
+{
+ reset();
+}
+
+void BroadcastChannel::addReceiver(ChannelBinding *receiver)
+{
+ ASSERT(std::find(mReceivers.begin(), mReceivers.end(), receiver) == mReceivers.end());
+ mReceivers.push_back(receiver);
+}
+
+void BroadcastChannel::removeReceiver(ChannelBinding *receiver)
+{
+ auto iter = std::find(mReceivers.begin(), mReceivers.end(), receiver);
+ ASSERT(iter != mReceivers.end());
+ mReceivers.erase(iter);
+}
+
+void BroadcastChannel::signal() const
+{
+ if (mReceivers.empty())
+ return;
+
+ for (const auto *receiver : mReceivers)
+ {
+ receiver->signal();
+ }
+}
+
+void BroadcastChannel::reset()
+{
+ for (auto receiver : mReceivers)
+ {
+ receiver->onChannelClosed();
+ }
+ mReceivers.clear();
+}
+
+ChannelBinding::ChannelBinding(SignalReceiver *receiver, SignalToken token)
+ : mChannel(nullptr), mReceiver(receiver), mToken(token)
+{
+ ASSERT(receiver);
+}
+
+ChannelBinding::~ChannelBinding()
+{
+ reset();
+}
+
+void ChannelBinding::bind(BroadcastChannel *channel)
+{
+ ASSERT(mReceiver);
+ if (mChannel)
+ {
+ mChannel->removeReceiver(this);
+ }
+
+ mChannel = channel;
+
+ if (mChannel)
+ {
+ mChannel->addReceiver(this);
+ }
+}
+
+void ChannelBinding::reset()
+{
+ bind(nullptr);
+}
+
+void ChannelBinding::signal() const
+{
+ mReceiver->signal(mToken);
+}
+
+void ChannelBinding::onChannelClosed()
+{
+ mChannel = nullptr;
+}
+
+} // namespace angle
diff --git a/gfx/angle/src/libANGLE/signal_utils.h b/gfx/angle/src/libANGLE/signal_utils.h
new file mode 100755
index 000000000..835f2c602
--- /dev/null
+++ b/gfx/angle/src/libANGLE/signal_utils.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.
+//
+// signal_utils:
+// Helper classes for tracking dependent state changes between objects.
+// These changes are signaled to the dependent class via channels.
+
+#ifndef LIBANGLE_SIGNAL_UTILS_H_
+#define LIBANGLE_SIGNAL_UTILS_H_
+
+#include <set>
+
+#include "common/angleutils.h"
+
+namespace angle
+{
+
+// Message token passed to the receiver;
+using SignalToken = uint32_t;
+
+// Interface that the depending class inherits from.
+class SignalReceiver
+{
+ public:
+ virtual ~SignalReceiver() = default;
+ virtual void signal(SignalToken token) = 0;
+};
+
+class ChannelBinding;
+
+// The host class owns the channel. It uses the channel to fire signals to the receiver.
+class BroadcastChannel final : NonCopyable
+{
+ public:
+ BroadcastChannel();
+ ~BroadcastChannel();
+
+ void signal() const;
+ void reset();
+
+ private:
+ // Only the ChannelBinding class should add or remove receivers.
+ friend class ChannelBinding;
+ void addReceiver(ChannelBinding *receiver);
+ void removeReceiver(ChannelBinding *receiver);
+
+ std::vector<ChannelBinding *> mReceivers;
+};
+
+// The dependent class keeps bindings to the host's BroadcastChannel.
+class ChannelBinding final
+{
+ public:
+ ChannelBinding(SignalReceiver *receiver, SignalToken token);
+ ~ChannelBinding();
+ ChannelBinding(const ChannelBinding &other) = default;
+ ChannelBinding &operator=(const ChannelBinding &other) = default;
+
+ void bind(BroadcastChannel *channel);
+ void reset();
+ void signal() const;
+ void onChannelClosed();
+
+ private:
+ BroadcastChannel *mChannel;
+ SignalReceiver *mReceiver;
+ SignalToken mToken;
+};
+
+} // namespace angle
+
+#endif // LIBANGLE_SIGNAL_UTILS_H_
diff --git a/gfx/angle/src/libANGLE/signal_utils_unittest.cpp b/gfx/angle/src/libANGLE/signal_utils_unittest.cpp
new file mode 100755
index 000000000..fac9b67df
--- /dev/null
+++ b/gfx/angle/src/libANGLE/signal_utils_unittest.cpp
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 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.
+//
+// signal_utils_unittest:
+// Unit tests for signals and related utils.
+
+#include <gtest/gtest.h>
+
+#include "libANGLE/signal_utils.h"
+
+using namespace angle;
+using namespace testing;
+
+namespace
+{
+
+struct SignalThing : public SignalReceiver
+{
+ void signal(SignalToken token) override { wasSignaled = true; }
+ bool wasSignaled = false;
+};
+
+// Test that broadcast signals work.
+TEST(SignalTest, BroadcastSignals)
+{
+ BroadcastChannel channel;
+ SignalThing thing;
+ ChannelBinding binding(&thing, 0u);
+
+ binding.bind(&channel);
+ ASSERT_FALSE(thing.wasSignaled);
+ channel.signal();
+ ASSERT_TRUE(thing.wasSignaled);
+}
+
+} // anonymous namespace
diff --git a/gfx/angle/src/libANGLE/validationEGL.cpp b/gfx/angle/src/libANGLE/validationEGL.cpp
new file mode 100755
index 000000000..7ee92e83e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/validationEGL.cpp
@@ -0,0 +1,1616 @@
+//
+// Copyright (c) 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.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Device.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+
+#include <EGL/eglext.h>
+
+namespace
+{
+size_t GetMaximumMipLevel(const gl::Context *context, GLenum target)
+{
+ const gl::Caps &caps = context->getCaps();
+
+ size_t maxDimension = 0;
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ maxDimension = caps.max2DTextureSize;
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ maxDimension = caps.maxCubeMapTextureSize;
+ break;
+ case GL_TEXTURE_3D:
+ maxDimension = caps.max3DTextureSize;
+ break;
+ case GL_TEXTURE_2D_ARRAY:
+ maxDimension = caps.max2DTextureSize;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return gl::log2(static_cast<int>(maxDimension));
+}
+
+bool TextureHasNonZeroMipLevelsSpecified(const gl::Context *context, const gl::Texture *texture)
+{
+ size_t maxMip = GetMaximumMipLevel(context, texture->getTarget());
+ for (size_t level = 1; level < maxMip; level++)
+ {
+ if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
+ {
+ for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget;
+ face++)
+ {
+ if (texture->getFormat(face, level).valid())
+ {
+ return true;
+ }
+ }
+ }
+ else
+ {
+ if (texture->getFormat(texture->getTarget(), level).valid())
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool CubeTextureHasUnspecifiedLevel0Face(const gl::Texture *texture)
+{
+ ASSERT(texture->getTarget() == GL_TEXTURE_CUBE_MAP);
+ for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget; face++)
+ {
+ if (!texture->getFormat(face, 0).valid())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+egl::Error ValidateStreamAttribute(const EGLAttrib attribute,
+ const EGLAttrib value,
+ const egl::DisplayExtensions &extensions)
+{
+ switch (attribute)
+ {
+ case EGL_STREAM_STATE_KHR:
+ case EGL_PRODUCER_FRAME_KHR:
+ case EGL_CONSUMER_FRAME_KHR:
+ return egl::Error(EGL_BAD_ACCESS, "Attempt to initialize readonly parameter");
+ case EGL_CONSUMER_LATENCY_USEC_KHR:
+ // Technically not in spec but a latency < 0 makes no sense so we check it
+ if (value < 0)
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "Latency must be positive");
+ }
+ break;
+ case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
+ if (!extensions.streamConsumerGLTexture)
+ {
+ return egl::Error(EGL_BAD_ATTRIBUTE, "Consumer GL extension not enabled");
+ }
+ // Again not in spec but it should be positive anyways
+ if (value < 0)
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "Timeout must be positive");
+ }
+ break;
+ default:
+ return egl::Error(EGL_BAD_ATTRIBUTE, "Invalid stream attribute");
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error ValidateCreateImageKHRMipLevelCommon(gl::Context *context,
+ const gl::Texture *texture,
+ EGLAttrib level)
+{
+ // Note that the spec EGL_KHR_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()))
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "texture must be complete if level is non-zero.");
+ }
+
+ if (level == 0 && !texture->isMipmapComplete() &&
+ TextureHasNonZeroMipLevelsSpecified(context, texture))
+ {
+ return egl::Error(EGL_BAD_PARAMETER,
+ "if level is zero and the texture is incomplete, it must have no mip "
+ "levels specified except zero.");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+} // namespace
+
+namespace egl
+{
+
+Error ValidateDisplay(const Display *display)
+{
+ if (display == EGL_NO_DISPLAY)
+ {
+ return Error(EGL_BAD_DISPLAY, "display is EGL_NO_DISPLAY.");
+ }
+
+ if (!Display::isValidDisplay(display))
+ {
+ return Error(EGL_BAD_DISPLAY, "display is not a valid display.");
+ }
+
+ if (!display->isInitialized())
+ {
+ return Error(EGL_NOT_INITIALIZED, "display is not initialized.");
+ }
+
+ if (display->isDeviceLost())
+ {
+ return Error(EGL_CONTEXT_LOST, "display had a context loss");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateSurface(const Display *display, const Surface *surface)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ if (!display->isValidSurface(surface))
+ {
+ return Error(EGL_BAD_SURFACE);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateConfig(const Display *display, const Config *config)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ if (!display->isValidConfig(config))
+ {
+ return Error(EGL_BAD_CONFIG);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateContext(const Display *display, const gl::Context *context)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ if (!display->isValidContext(context))
+ {
+ return Error(EGL_BAD_CONTEXT);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateImage(const Display *display, const Image *image)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ if (!display->isValidImage(image))
+ {
+ return Error(EGL_BAD_PARAMETER, "image is not valid.");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateStream(const Display *display, const Stream *stream)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.stream)
+ {
+ return Error(EGL_BAD_ACCESS, "Stream extension not active");
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ return Error(EGL_BAD_STREAM_KHR, "Invalid stream");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext,
+ const AttributeMap& attributes)
+{
+ ANGLE_TRY(ValidateConfig(display, configuration));
+
+ // Get the requested client version (default is 1) and check it is 2 or 3.
+ EGLAttrib clientMajorVersion = 1;
+ EGLAttrib clientMinorVersion = 0;
+ EGLAttrib contextFlags = 0;
+ bool resetNotification = false;
+ for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
+ {
+ EGLAttrib attribute = attributeIter->first;
+ EGLAttrib value = attributeIter->second;
+
+ switch (attribute)
+ {
+ case EGL_CONTEXT_CLIENT_VERSION:
+ clientMajorVersion = value;
+ break;
+
+ case EGL_CONTEXT_MINOR_VERSION:
+ clientMinorVersion = value;
+ break;
+
+ case EGL_CONTEXT_FLAGS_KHR:
+ contextFlags = value;
+ break;
+
+ case EGL_CONTEXT_OPENGL_DEBUG:
+ break;
+
+ case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
+ // Only valid for OpenGL (non-ES) contexts
+ return Error(EGL_BAD_ATTRIBUTE);
+
+ case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
+ if (!display->getExtensions().createContextRobustness)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
+ static_assert(EGL_LOSE_CONTEXT_ON_RESET_EXT == EGL_LOSE_CONTEXT_ON_RESET_KHR, "EGL extension enums not equal.");
+ static_assert(EGL_NO_RESET_NOTIFICATION_EXT == EGL_NO_RESET_NOTIFICATION_KHR, "EGL extension enums not equal.");
+ // same as EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, fall through
+ case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
+ if (!display->getExtensions().createContextRobustness)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ if (value == EGL_LOSE_CONTEXT_ON_RESET_EXT)
+ {
+ resetNotification = true;
+ }
+ else if (value != EGL_NO_RESET_NOTIFICATION_EXT)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
+ if (!display->getExtensions().createContextNoError)
+ {
+ return Error(EGL_BAD_ATTRIBUTE, "Invalid Context attribute.");
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return Error(EGL_BAD_ATTRIBUTE, "Attribute must be EGL_TRUE or EGL_FALSE.");
+ }
+ break;
+
+ case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
+ if (!display->getExtensions().createContextWebGLCompatibility)
+ {
+ return Error(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE requires "
+ "EGL_ANGLE_create_context_webgl_compatibility.");
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return Error(
+ EGL_BAD_ATTRIBUTE,
+ "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE must be EGL_TRUE or EGL_FALSE.");
+ }
+ break;
+
+ case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
+ if (!display->getExtensions().createContextBindGeneratesResource)
+ {
+ return Error(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM requires "
+ "EGL_CHROMIUM_create_context_bind_generates_resource.");
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return Error(EGL_BAD_ATTRIBUTE,
+ "EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM must be EGL_TRUE or "
+ "EGL_FALSE.");
+ }
+ break;
+
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ }
+
+ switch (clientMajorVersion)
+ {
+ case 2:
+ if (clientMinorVersion != 0)
+ {
+ return Error(EGL_BAD_CONFIG);
+ }
+ break;
+ case 3:
+ if (clientMinorVersion != 0 && clientMinorVersion != 1)
+ {
+ return Error(EGL_BAD_CONFIG);
+ }
+ if (!(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR))
+ {
+ return Error(EGL_BAD_CONFIG);
+ }
+ if (display->getMaxSupportedESVersion() <
+ gl::Version(static_cast<GLuint>(clientMajorVersion),
+ static_cast<GLuint>(clientMinorVersion)))
+ {
+ return Error(EGL_BAD_CONFIG, "Requested GLES version is not supported.");
+ }
+ break;
+ default:
+ return Error(EGL_BAD_CONFIG);
+ break;
+ }
+
+ // Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
+ const EGLint validContextFlags = (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR |
+ EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
+ if ((contextFlags & ~validContextFlags) != 0)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+
+ if (shareContext)
+ {
+ // Shared context is invalid or is owned by another display
+ if (!display->isValidContext(shareContext))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ if (shareContext->isResetNotificationEnabled() != resetNotification)
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ if (shareContext->getClientMajorVersion() != clientMajorVersion ||
+ shareContext->getClientMinorVersion() != clientMinorVersion)
+ {
+ return Error(EGL_BAD_CONTEXT);
+ }
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWindowType window,
+ const AttributeMap& attributes)
+{
+ ANGLE_TRY(ValidateConfig(display, config));
+
+ if (!display->isValidNativeWindow(window))
+ {
+ return Error(EGL_BAD_NATIVE_WINDOW);
+ }
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+
+ for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
+ {
+ 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:
+ return Error(EGL_BAD_MATCH); // Rendering directly to front buffer not supported
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+ if (!displayExtensions.postSubBuffer)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
+ if (!displayExtensions.flexibleSurfaceCompatibility)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_WIDTH:
+ case EGL_HEIGHT:
+ if (!displayExtensions.windowFixedSize)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ if (value < 0)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ break;
+
+ case EGL_FIXED_SIZE_ANGLE:
+ if (!displayExtensions.windowFixedSize)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_SURFACE_ORIENTATION_ANGLE:
+ if (!displayExtensions.surfaceOrientation)
+ {
+ return Error(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_surface_orientation is not enabled.");
+ }
+ break;
+
+ case EGL_VG_COLORSPACE:
+ return Error(EGL_BAD_MATCH);
+
+ case EGL_VG_ALPHA_FORMAT:
+ return Error(EGL_BAD_MATCH);
+
+ case EGL_DIRECT_COMPOSITION_ANGLE:
+ if (!displayExtensions.directComposition)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ }
+
+ if (Display::hasExistingWindowSurface(window))
+ {
+ return Error(EGL_BAD_ALLOC);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap& attributes)
+{
+ ANGLE_TRY(ValidateConfig(display, config));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+
+ 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 (value < 0)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ 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:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_TEXTURE_TARGET:
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_2D:
+ break;
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_MIPMAP_TEXTURE:
+ break;
+
+ case EGL_VG_COLORSPACE:
+ break;
+
+ case EGL_VG_ALPHA_FORMAT:
+ break;
+
+ case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
+ if (!displayExtensions.flexibleSurfaceCompatibility)
+ {
+ return Error(
+ EGL_BAD_ATTRIBUTE,
+ "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used without "
+ "EGL_ANGLE_flexible_surface_compatibility support.");
+ }
+ break;
+
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ }
+
+ if (!(config->surfaceType & EGL_PBUFFER_BIT))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ 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))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
+ (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+
+ 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)))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer,
+ Config *config, const AttributeMap& attributes)
+{
+ ANGLE_TRY(ValidateConfig(display, config));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+
+ switch (buftype)
+ {
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ if (!displayExtensions.d3dShareHandleClientBuffer)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ if (buffer == nullptr)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ break;
+
+ case EGL_D3D_TEXTURE_ANGLE:
+ if (!displayExtensions.d3dTextureClientBuffer)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ if (buffer == nullptr)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ break;
+
+ default:
+ return Error(EGL_BAD_PARAMETER);
+ }
+
+ 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 (!displayExtensions.d3dShareHandleClientBuffer)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ if (value < 0)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ break;
+
+ case EGL_TEXTURE_FORMAT:
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_RGB:
+ case EGL_TEXTURE_RGBA:
+ break;
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_TEXTURE_TARGET:
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_2D:
+ break;
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_MIPMAP_TEXTURE:
+ break;
+
+ case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
+ if (!displayExtensions.flexibleSurfaceCompatibility)
+ {
+ return Error(
+ EGL_BAD_ATTRIBUTE,
+ "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used without "
+ "EGL_ANGLE_flexible_surface_compatibility support.");
+ }
+ break;
+
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ }
+
+ if (!(config->surfaceType & EGL_PBUFFER_BIT))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ 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))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
+ (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+
+ 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)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+
+ const Caps &caps = display->getCaps();
+ if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+ }
+
+ ANGLE_TRY(display->validateClientBuffer(config, buftype, buffer, attributes));
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCompatibleConfigs(const Display *display,
+ const Config *config1,
+ const Surface *surface,
+ const Config *config2,
+ EGLint surfaceType)
+{
+
+ if (!surface->flexibleSurfaceCompatibilityRequested())
+ {
+ // Config compatibility is defined in section 2.2 of the EGL 1.5 spec
+
+ bool colorBufferCompat = config1->colorBufferType == config2->colorBufferType;
+ if (!colorBufferCompat)
+ {
+ return Error(EGL_BAD_MATCH, "Color buffer types are not compatible.");
+ }
+
+ bool colorCompat =
+ config1->redSize == config2->redSize && config1->greenSize == config2->greenSize &&
+ config1->blueSize == config2->blueSize && config1->alphaSize == config2->alphaSize &&
+ config1->luminanceSize == config2->luminanceSize;
+ if (!colorCompat)
+ {
+ return Error(EGL_BAD_MATCH, "Color buffer sizes are not compatible.");
+ }
+
+ bool dsCompat = config1->depthSize == config2->depthSize &&
+ config1->stencilSize == config2->stencilSize;
+ if (!dsCompat)
+ {
+ return Error(EGL_BAD_MATCH, "Depth-stencil buffer types are not compatible.");
+ }
+ }
+
+ bool surfaceTypeCompat = (config1->surfaceType & config2->surfaceType & surfaceType) != 0;
+ if (!surfaceTypeCompat)
+ {
+ return Error(EGL_BAD_MATCH, "Surface types are not compatible.");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateImageKHR(const Display *display,
+ gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const AttributeMap &attributes)
+{
+ ANGLE_TRY(ValidateContext(display, context));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+
+ if (!displayExtensions.imageBase && !displayExtensions.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.
+ return Error(EGL_BAD_DISPLAY, "EGL_KHR_image not supported.");
+ }
+
+ // 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_KHR:
+ switch (value)
+ {
+ case EGL_TRUE:
+ case EGL_FALSE:
+ break;
+
+ default:
+ return Error(EGL_BAD_PARAMETER,
+ "EGL_IMAGE_PRESERVED_KHR must be EGL_TRUE or EGL_FALSE.");
+ }
+ break;
+
+ case EGL_GL_TEXTURE_LEVEL_KHR:
+ if (!displayExtensions.glTexture2DImage &&
+ !displayExtensions.glTextureCubemapImage && !displayExtensions.glTexture3DImage)
+ {
+ return Error(EGL_BAD_PARAMETER,
+ "EGL_GL_TEXTURE_LEVEL_KHR cannot be used without "
+ "KHR_gl_texture_*_image support.");
+ }
+
+ if (value < 0)
+ {
+ return Error(EGL_BAD_PARAMETER, "EGL_GL_TEXTURE_LEVEL_KHR cannot be negative.");
+ }
+ break;
+
+ case EGL_GL_TEXTURE_ZOFFSET_KHR:
+ if (!displayExtensions.glTexture3DImage)
+ {
+ return Error(EGL_BAD_PARAMETER,
+ "EGL_GL_TEXTURE_ZOFFSET_KHR cannot be used without "
+ "KHR_gl_texture_3D_image support.");
+ }
+ break;
+
+ default:
+ return Error(EGL_BAD_PARAMETER, "invalid attribute: 0x%X", attribute);
+ }
+ }
+
+ switch (target)
+ {
+ case EGL_GL_TEXTURE_2D_KHR:
+ {
+ if (!displayExtensions.glTexture2DImage)
+ {
+ return Error(EGL_BAD_PARAMETER, "KHR_gl_texture_2D_image not supported.");
+ }
+
+ if (buffer == 0)
+ {
+ return Error(EGL_BAD_PARAMETER,
+ "buffer cannot reference a 2D texture with the name 0.");
+ }
+
+ const gl::Texture *texture =
+ context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
+ if (texture == nullptr || texture->getTarget() != GL_TEXTURE_2D)
+ {
+ return Error(EGL_BAD_PARAMETER, "target is not a 2D texture.");
+ }
+
+ if (texture->getBoundSurface() != nullptr)
+ {
+ return Error(EGL_BAD_ACCESS, "texture has a surface bound to it.");
+ }
+
+ EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
+ if (texture->getWidth(GL_TEXTURE_2D, static_cast<size_t>(level)) == 0 ||
+ texture->getHeight(GL_TEXTURE_2D, static_cast<size_t>(level)) == 0)
+ {
+ return Error(EGL_BAD_PARAMETER,
+ "target 2D texture does not have a valid size at specified level.");
+ }
+
+ ANGLE_TRY(ValidateCreateImageKHRMipLevelCommon(context, texture, level));
+ }
+ break;
+
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
+ {
+ if (!displayExtensions.glTextureCubemapImage)
+ {
+ return Error(EGL_BAD_PARAMETER, "KHR_gl_texture_cubemap_image not supported.");
+ }
+
+ if (buffer == 0)
+ {
+ return Error(EGL_BAD_PARAMETER,
+ "buffer cannot reference a cubemap texture with the name 0.");
+ }
+
+ const gl::Texture *texture =
+ context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
+ if (texture == nullptr || texture->getTarget() != GL_TEXTURE_CUBE_MAP)
+ {
+ return Error(EGL_BAD_PARAMETER, "target is not a cubemap texture.");
+ }
+
+ if (texture->getBoundSurface() != nullptr)
+ {
+ return Error(EGL_BAD_ACCESS, "texture has a surface bound to it.");
+ }
+
+ EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
+ GLenum cubeMapFace = egl_gl::EGLCubeMapTargetToGLCubeMapTarget(target);
+ if (texture->getWidth(cubeMapFace, static_cast<size_t>(level)) == 0 ||
+ texture->getHeight(cubeMapFace, static_cast<size_t>(level)) == 0)
+ {
+ return Error(EGL_BAD_PARAMETER,
+ "target cubemap texture does not have a valid size at specified level "
+ "and face.");
+ }
+
+ ANGLE_TRY(ValidateCreateImageKHRMipLevelCommon(context, texture, level));
+
+ if (level == 0 && !texture->isMipmapComplete() &&
+ CubeTextureHasUnspecifiedLevel0Face(texture))
+ {
+ return Error(EGL_BAD_PARAMETER,
+ "if level is zero and the texture is incomplete, it must have all of "
+ "its faces specified at level zero.");
+ }
+ }
+ break;
+
+ case EGL_GL_TEXTURE_3D_KHR:
+ {
+ if (!displayExtensions.glTexture3DImage)
+ {
+ return Error(EGL_BAD_PARAMETER, "KHR_gl_texture_3D_image not supported.");
+ }
+
+ if (buffer == 0)
+ {
+ return Error(EGL_BAD_PARAMETER,
+ "buffer cannot reference a 3D texture with the name 0.");
+ }
+
+ const gl::Texture *texture =
+ context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
+ if (texture == nullptr || texture->getTarget() != GL_TEXTURE_3D)
+ {
+ return Error(EGL_BAD_PARAMETER, "target is not a 3D texture.");
+ }
+
+ if (texture->getBoundSurface() != nullptr)
+ {
+ return Error(EGL_BAD_ACCESS, "texture has a surface bound to it.");
+ }
+
+ EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
+ EGLAttrib zOffset = attributes.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0);
+ if (texture->getWidth(GL_TEXTURE_3D, static_cast<size_t>(level)) == 0 ||
+ texture->getHeight(GL_TEXTURE_3D, static_cast<size_t>(level)) == 0 ||
+ texture->getDepth(GL_TEXTURE_3D, static_cast<size_t>(level)) == 0)
+ {
+ return Error(EGL_BAD_PARAMETER,
+ "target 3D texture does not have a valid size at specified level.");
+ }
+
+ if (static_cast<size_t>(zOffset) >=
+ texture->getDepth(GL_TEXTURE_3D, static_cast<size_t>(level)))
+ {
+ return Error(EGL_BAD_PARAMETER,
+ "target 3D texture does not have enough layers for the specified Z "
+ "offset at the specified level.");
+ }
+
+ ANGLE_TRY(ValidateCreateImageKHRMipLevelCommon(context, texture, level));
+ }
+ break;
+
+ case EGL_GL_RENDERBUFFER_KHR:
+ {
+ if (!displayExtensions.glRenderbufferImage)
+ {
+ return Error(EGL_BAD_PARAMETER, "KHR_gl_renderbuffer_image not supported.");
+ }
+
+ if (attributes.contains(EGL_GL_TEXTURE_LEVEL_KHR))
+ {
+ return Error(EGL_BAD_PARAMETER,
+ "EGL_GL_TEXTURE_LEVEL_KHR cannot be used in conjunction with a "
+ "renderbuffer target.");
+ }
+
+ if (buffer == 0)
+ {
+ return Error(EGL_BAD_PARAMETER,
+ "buffer cannot reference a renderbuffer with the name 0.");
+ }
+
+ const gl::Renderbuffer *renderbuffer =
+ context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
+ if (renderbuffer == nullptr)
+ {
+ return Error(EGL_BAD_PARAMETER, "target is not a renderbuffer.");
+ }
+
+ if (renderbuffer->getSamples() > 0)
+ {
+ return Error(EGL_BAD_PARAMETER, "target renderbuffer cannot be multisampled.");
+ }
+ }
+ break;
+
+ default:
+ return Error(EGL_BAD_PARAMETER, "invalid target: 0x%X", target);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateDestroyImageKHR(const Display *display, const Image *image)
+{
+ ANGLE_TRY(ValidateImage(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.
+ return Error(EGL_BAD_DISPLAY);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateDeviceANGLE(EGLint device_type,
+ void *native_device,
+ const EGLAttrib *attrib_list)
+{
+ const ClientExtensions &clientExtensions = Display::getClientExtensions();
+ if (!clientExtensions.deviceCreation)
+ {
+ return Error(EGL_BAD_ACCESS, "Device creation extension not active");
+ }
+
+ if (attrib_list != nullptr && attrib_list[0] != EGL_NONE)
+ {
+ return Error(EGL_BAD_ATTRIBUTE, "Invalid attrib_list parameter");
+ }
+
+ switch (device_type)
+ {
+ case EGL_D3D11_DEVICE_ANGLE:
+ if (!clientExtensions.deviceCreationD3D11)
+ {
+ return Error(EGL_BAD_ATTRIBUTE, "D3D11 device creation extension not active");
+ }
+ break;
+ default:
+ return Error(EGL_BAD_ATTRIBUTE, "Invalid device_type parameter");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateReleaseDeviceANGLE(Device *device)
+{
+ const ClientExtensions &clientExtensions = Display::getClientExtensions();
+ if (!clientExtensions.deviceCreation)
+ {
+ return Error(EGL_BAD_ACCESS, "Device creation extension not active");
+ }
+
+ if (device == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(device))
+ {
+ return Error(EGL_BAD_DEVICE_EXT, "Invalid device parameter");
+ }
+
+ Display *owningDisplay = device->getOwningDisplay();
+ if (owningDisplay != nullptr)
+ {
+ return Error(EGL_BAD_DEVICE_EXT, "Device must have been created using eglCreateDevice");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateStreamKHR(const Display *display, const AttributeMap &attributes)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.stream)
+ {
+ return Error(EGL_BAD_ALLOC, "Stream extension not active");
+ }
+
+ for (const auto &attributeIter : attributes)
+ {
+ EGLAttrib attribute = attributeIter.first;
+ EGLAttrib value = attributeIter.second;
+
+ ANGLE_TRY(ValidateStreamAttribute(attribute, value, displayExtensions));
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateDestroyStreamKHR(const Display *display, const Stream *stream)
+{
+ ANGLE_TRY(ValidateStream(display, stream));
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateStreamAttribKHR(const Display *display,
+ const Stream *stream,
+ EGLint attribute,
+ EGLint value)
+{
+ ANGLE_TRY(ValidateStream(display, stream));
+
+ if (stream->getState() == EGL_STREAM_STATE_DISCONNECTED_KHR)
+ {
+ return Error(EGL_BAD_STATE_KHR, "Bad stream state");
+ }
+
+ return ValidateStreamAttribute(attribute, value, display->getExtensions());
+}
+
+Error ValidateQueryStreamKHR(const Display *display,
+ const Stream *stream,
+ EGLenum attribute,
+ EGLint *value)
+{
+ ANGLE_TRY(ValidateStream(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)
+ {
+ return Error(EGL_BAD_ATTRIBUTE, "Consumer GLTexture extension not active");
+ }
+ break;
+ default:
+ return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateQueryStreamu64KHR(const Display *display,
+ const Stream *stream,
+ EGLenum attribute,
+ EGLuint64KHR *value)
+{
+ ANGLE_TRY(ValidateStream(display, stream));
+
+ switch (attribute)
+ {
+ case EGL_CONSUMER_FRAME_KHR:
+ case EGL_PRODUCER_FRAME_KHR:
+ break;
+ default:
+ return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateStreamConsumerGLTextureExternalKHR(const Display *display,
+ gl::Context *context,
+ const Stream *stream)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+ ANGLE_TRY(ValidateContext(display, context));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamConsumerGLTexture)
+ {
+ return Error(EGL_BAD_ACCESS, "Stream consumer extension not active");
+ }
+
+ if (!context->getExtensions().eglStreamConsumerExternal)
+ {
+ return Error(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ return Error(EGL_BAD_STREAM_KHR, "Invalid stream");
+ }
+
+ if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
+ {
+ return Error(EGL_BAD_STATE_KHR, "Invalid stream state");
+ }
+
+ // Lookup the texture and ensure it is correct
+ gl::Texture *texture = context->getGLState().getTargetTexture(GL_TEXTURE_EXTERNAL_OES);
+ if (texture == nullptr || texture->getId() == 0)
+ {
+ return Error(EGL_BAD_ACCESS, "No external texture bound");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateStreamConsumerAcquireKHR(const Display *display,
+ gl::Context *context,
+ const Stream *stream)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamConsumerGLTexture)
+ {
+ return Error(EGL_BAD_ACCESS, "Stream consumer extension not active");
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ return Error(EGL_BAD_STREAM_KHR, "Invalid stream");
+ }
+
+ if (!context)
+ {
+ return Error(EGL_BAD_ACCESS, "No GL context current to calling thread.");
+ }
+
+ ANGLE_TRY(ValidateContext(display, context));
+
+ if (!stream->isConsumerBoundToContext(context))
+ {
+ return Error(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
+ }
+
+ if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
+ stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
+ {
+ return Error(EGL_BAD_ACCESS, "Invalid stream consumer type");
+ }
+
+ // 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)
+ {
+ return Error(EGL_BAD_STATE_KHR, "Invalid stream state");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateStreamConsumerReleaseKHR(const Display *display,
+ gl::Context *context,
+ const Stream *stream)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamConsumerGLTexture)
+ {
+ return Error(EGL_BAD_ACCESS, "Stream consumer extension not active");
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ return Error(EGL_BAD_STREAM_KHR, "Invalid stream");
+ }
+
+ if (!context)
+ {
+ return Error(EGL_BAD_ACCESS, "No GL context current to calling thread.");
+ }
+
+ ANGLE_TRY(ValidateContext(display, context));
+
+ if (!stream->isConsumerBoundToContext(context))
+ {
+ return Error(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
+ }
+
+ if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
+ stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
+ {
+ return Error(EGL_BAD_ACCESS, "Invalid stream consumer type");
+ }
+
+ if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
+ stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
+ {
+ return Error(EGL_BAD_STATE_KHR, "Invalid stream state");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateStreamConsumerGLTextureExternalAttribsNV(const Display *display,
+ gl::Context *context,
+ const Stream *stream,
+ const AttributeMap &attribs)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamConsumerGLTexture)
+ {
+ return Error(EGL_BAD_ACCESS, "Stream consumer extension not active");
+ }
+
+ // 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().eglStreamConsumerExternal)
+ {
+ return Error(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ return Error(EGL_BAD_STREAM_KHR, "Invalid stream");
+ }
+
+ if (!context)
+ {
+ return Error(EGL_BAD_ACCESS, "No GL context current to calling thread.");
+ }
+
+ ANGLE_TRY(ValidateContext(display, context));
+
+ if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
+ {
+ return Error(EGL_BAD_STATE_KHR, "Invalid stream state");
+ }
+
+ 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;
+ }
+ 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)
+ {
+ return Error(EGL_BAD_PARAMETER, "Invalid color buffer type");
+ }
+ 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)
+ {
+ return Error(EGL_BAD_MATCH, "Invalid plane count");
+ }
+ 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)
+ {
+ return Error(EGL_BAD_ACCESS, "Invalid texture unit");
+ }
+ plane[attribute - EGL_YUV_PLANE0_TEXTURE_UNIT_NV] = value;
+ }
+ else
+ {
+ return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ }
+ }
+ }
+
+ if (colorBufferType == EGL_RGB_BUFFER)
+ {
+ if (planeCount > 0)
+ {
+ return Error(EGL_BAD_MATCH, "Plane count must be 0 for RGB buffer");
+ }
+ for (int i = 0; i < 3; i++)
+ {
+ if (plane[i] != -1)
+ {
+ return Error(EGL_BAD_MATCH, "Planes cannot be specified");
+ }
+ }
+
+ // Lookup the texture and ensure it is correct
+ gl::Texture *texture = context->getGLState().getTargetTexture(GL_TEXTURE_EXTERNAL_OES);
+ if (texture == nullptr || texture->getId() == 0)
+ {
+ return Error(EGL_BAD_ACCESS, "No external texture bound");
+ }
+ }
+ else
+ {
+ if (planeCount == -1)
+ {
+ planeCount = 2;
+ }
+ if (planeCount < 1 || planeCount > 3)
+ {
+ return Error(EGL_BAD_MATCH, "Invalid YUV plane count");
+ }
+ for (EGLAttrib i = planeCount; i < 3; i++)
+ {
+ if (plane[i] != -1)
+ {
+ return Error(EGL_BAD_MATCH, "Invalid plane specified");
+ }
+ }
+
+ // 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)
+ {
+ return Error(EGL_BAD_MATCH, "Not all planes specified");
+ }
+ if (plane[i] != EGL_NONE)
+ {
+ gl::Texture *texture = context->getGLState().getSamplerTexture(
+ static_cast<unsigned int>(plane[i]), GL_TEXTURE_EXTERNAL_OES);
+ if (texture == nullptr || texture->getId() == 0)
+ {
+ return Error(
+ EGL_BAD_ACCESS,
+ "No external texture bound at one or more specified texture units");
+ }
+ if (textureSet.find(texture) != textureSet.end())
+ {
+ return Error(EGL_BAD_ACCESS, "Multiple planes bound to same texture object");
+ }
+ textureSet.insert(texture);
+ }
+ }
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateStreamProducerD3DTextureNV12ANGLE(const Display *display,
+ const Stream *stream,
+ const AttributeMap &attribs)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamProducerD3DTextureNV12)
+ {
+ return Error(EGL_BAD_ACCESS, "Stream producer extension not active");
+ }
+
+ ANGLE_TRY(ValidateStream(display, stream));
+
+ if (!attribs.isEmpty())
+ {
+ return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ }
+
+ if (stream->getState() != EGL_STREAM_STATE_CONNECTING_KHR)
+ {
+ return Error(EGL_BAD_STATE_KHR, "Stream not in connecting state");
+ }
+
+ if (stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV ||
+ stream->getPlaneCount() != 2)
+ {
+ return Error(EGL_BAD_MATCH, "Incompatible stream consumer type");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateStreamPostD3DTextureNV12ANGLE(const Display *display,
+ const Stream *stream,
+ void *texture,
+ const AttributeMap &attribs)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamProducerD3DTextureNV12)
+ {
+ return Error(EGL_BAD_ACCESS, "Stream producer extension not active");
+ }
+
+ ANGLE_TRY(ValidateStream(display, stream));
+
+ for (auto &attributeIter : attribs)
+ {
+ EGLAttrib attribute = attributeIter.first;
+ EGLAttrib value = attributeIter.second;
+
+ switch (attribute)
+ {
+ case EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE:
+ if (value < 0)
+ {
+ return Error(EGL_BAD_PARAMETER, "Invalid subresource index");
+ }
+ break;
+ default:
+ return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ }
+ }
+
+ 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)
+ {
+ return Error(EGL_BAD_STATE_KHR, "Stream not fully configured");
+ }
+
+ if (stream->getProducerType() != Stream::ProducerType::D3D11TextureNV12)
+ {
+ return Error(EGL_BAD_MATCH, "Incompatible stream producer");
+ }
+
+ if (texture == nullptr)
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "Texture is null");
+ }
+
+ return stream->validateD3D11NV12Texture(texture);
+}
+
+Error ValidateSwapBuffersWithDamageEXT(const Display *display,
+ const Surface *surface,
+ EGLint *rects,
+ EGLint n_rects)
+{
+ Error error = ValidateSurface(display, surface);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ 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.
+ return Error(EGL_BAD_DISPLAY, "EGL_EXT_swap_buffers_with_damage is not available.");
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return Error(EGL_BAD_SURFACE, "Swap surface cannot be EGL_NO_SURFACE.");
+ }
+
+ if (n_rects < 0)
+ {
+ return Error(EGL_BAD_PARAMETER, "n_rects cannot be negative.");
+ }
+
+ if (n_rects > 0 && rects == nullptr)
+ {
+ return Error(EGL_BAD_PARAMETER, "n_rects cannot be greater than zero when rects is NULL.");
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/validationEGL.h b/gfx/angle/src/libANGLE/validationEGL.h
new file mode 100755
index 000000000..c299f860c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/validationEGL.h
@@ -0,0 +1,111 @@
+//
+// Copyright (c) 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 "libANGLE/Error.h"
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+namespace gl
+{
+class Context;
+}
+
+namespace egl
+{
+
+class AttributeMap;
+struct Config;
+class Device;
+class Display;
+class Image;
+class Stream;
+class Surface;
+
+// Object validation
+Error ValidateDisplay(const Display *display);
+Error ValidateSurface(const Display *display, const Surface *surface);
+Error ValidateConfig(const Display *display, const Config *config);
+Error ValidateContext(const Display *display, const gl::Context *context);
+Error ValidateImage(const Display *display, const Image *image);
+
+// Entry point validation
+Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext,
+ const AttributeMap& attributes);
+
+Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWindowType window,
+ const AttributeMap& attributes);
+
+Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap& attributes);
+Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer,
+ Config *config, const AttributeMap& attributes);
+
+Error ValidateCreateImageKHR(const Display *display,
+ gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const AttributeMap &attributes);
+Error ValidateDestroyImageKHR(const Display *display, const Image *image);
+
+Error ValidateCreateDeviceANGLE(EGLint device_type,
+ void *native_device,
+ const EGLAttrib *attrib_list);
+Error ValidateReleaseDeviceANGLE(Device *device);
+
+Error ValidateCreateStreamKHR(const Display *display, const AttributeMap &attributes);
+Error ValidateDestroyStreamKHR(const Display *display, const Stream *stream);
+Error ValidateStreamAttribKHR(const Display *display,
+ const Stream *stream,
+ EGLint attribute,
+ EGLint value);
+Error ValidateQueryStreamKHR(const Display *display,
+ const Stream *stream,
+ EGLenum attribute,
+ EGLint *value);
+Error ValidateQueryStreamu64KHR(const Display *display,
+ const Stream *stream,
+ EGLenum attribute,
+ EGLuint64KHR *value);
+Error ValidateStreamConsumerGLTextureExternalKHR(const Display *display,
+ gl::Context *context,
+ const Stream *stream);
+Error ValidateStreamConsumerAcquireKHR(const Display *display,
+ gl::Context *context,
+ const Stream *stream);
+Error ValidateStreamConsumerReleaseKHR(const Display *display,
+ gl::Context *context,
+ const Stream *stream);
+Error ValidateStreamConsumerGLTextureExternalAttribsNV(const Display *display,
+ gl::Context *context,
+ const Stream *stream,
+ const AttributeMap &attribs);
+Error ValidateCreateStreamProducerD3DTextureNV12ANGLE(const Display *display,
+ const Stream *stream,
+ const AttributeMap &attribs);
+Error ValidateStreamPostD3DTextureNV12ANGLE(const Display *display,
+ const Stream *stream,
+ void *texture,
+ const AttributeMap &attribs);
+
+Error ValidateSwapBuffersWithDamageEXT(const Display *display,
+ const Surface *surface,
+ EGLint *rects,
+ EGLint n_rects);
+
+// Other validation
+Error ValidateCompatibleConfigs(const Display *display,
+ const Config *config1,
+ const Surface *surface,
+ const Config *config2,
+ EGLint surfaceType);
+}
+
+#endif // LIBANGLE_VALIDATIONEGL_H_
diff --git a/gfx/angle/src/libANGLE/validationES.cpp b/gfx/angle/src/libANGLE/validationES.cpp
new file mode 100755
index 000000000..79e3f6636
--- /dev/null
+++ b/gfx/angle/src/libANGLE/validationES.cpp
@@ -0,0 +1,5290 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// validationES.h: Validation functions for generic OpenGL ES entry point parameters
+
+#include "libANGLE/validationES.h"
+
+#include "libANGLE/validationES2.h"
+#include "libANGLE/validationES3.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/VertexArray.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+using namespace angle;
+
+namespace gl
+{
+const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
+
+namespace
+{
+bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxVertex)
+{
+ const gl::State &state = context->getGLState();
+ const gl::Program *program = state.getProgram();
+
+ const VertexArray *vao = state.getVertexArray();
+ const auto &vertexAttribs = vao->getVertexAttributes();
+ size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
+ for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
+ {
+ const VertexAttribute &attrib = vertexAttribs[attributeIndex];
+ if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
+ {
+ gl::Buffer *buffer = attrib.buffer.get();
+
+ if (buffer)
+ {
+ GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
+ GLint64 maxVertexElement = 0;
+
+ if (attrib.divisor > 0)
+ {
+ maxVertexElement =
+ static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
+ }
+ else
+ {
+ maxVertexElement = static_cast<GLint64>(maxVertex);
+ }
+
+ // If we're drawing zero vertices, we have enough data.
+ if (maxVertexElement > 0)
+ {
+ // Note: Last vertex element does not take the full stride!
+ GLint64 attribSize =
+ static_cast<GLint64>(ComputeVertexAttributeTypeSize(attrib));
+ GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize;
+ GLint64 attribOffset = static_cast<GLint64>(attrib.offset);
+
+ // [OpenGL ES 3.0.2] section 2.9.4 page 40:
+ // We can return INVALID_OPERATION if our vertex attribute does not have
+ // enough backing data.
+ if (attribDataSize + attribOffset > buffer->getSize())
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION,
+ "Vertex buffer is not big enough for the draw call"));
+ return false;
+ }
+ }
+ }
+ else if (attrib.pointer == NULL)
+ {
+ // This is an application error that would normally result in a crash,
+ // but we catch it and return an error
+ context->handleError(Error(
+ GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool ValidReadPixelsFormatType(ValidationContext *context,
+ GLenum framebufferComponentType,
+ GLenum format,
+ GLenum type)
+{
+ switch (framebufferComponentType)
+ {
+ 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
+ return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
+ (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
+ type == GL_UNSIGNED_BYTE);
+
+ case GL_SIGNED_NORMALIZED:
+ return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
+
+ 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:
+ return (format == GL_RGBA && type == GL_FLOAT);
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+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().multisampleCompatibility;
+
+ 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().debug;
+
+ case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+ return queryOnly && context->getExtensions().bindGeneratesResource;
+
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ return context->getExtensions().sRGBWriteControl;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateReadPixelsBase(ValidationContext *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLvoid *pixels)
+{
+ if (length != nullptr)
+ {
+ *length = 0;
+ }
+
+ if (width < 0 || height < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
+ return false;
+ }
+
+ auto readFramebuffer = context->getGLState().getReadFramebuffer();
+
+ if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
+ ASSERT(framebuffer);
+
+ if (framebuffer->getReadBufferState() == GL_NONE)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
+ return false;
+ }
+
+ const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
+ if (!readBuffer)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
+ GLenum currentType = framebuffer->getImplementationColorReadType();
+ GLenum currentInternalFormat = readBuffer->getFormat().asSized();
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
+ bool validFormatTypeCombination =
+ ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
+
+ if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Check for pixel pack buffer related API errors
+ gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
+ if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
+ {
+ // ...the buffer object's data store is currently mapped.
+ context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
+ return false;
+ }
+
+ // .. the data would be packed to the buffer object such that the memory writes required
+ // would exceed the data store size.
+ GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
+ const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
+ const gl::Extents size(width, height, 1);
+ const auto &pack = context->getGLState().getPackState();
+
+ auto endByteOrErr = formatInfo.computePackUnpackEndByte(size, pack, false);
+ if (endByteOrErr.isError())
+ {
+ context->handleError(endByteOrErr.getError());
+ return false;
+ }
+
+ size_t endByte = endByteOrErr.getResult();
+ if (bufSize >= 0)
+ {
+
+ if (static_cast<size_t>(bufSize) < endByte)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
+ 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->handleError(
+ Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
+ return false;
+ }
+ }
+
+ if (length != nullptr)
+ {
+ if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
+ return false;
+ }
+
+ *length = static_cast<GLsizei>(endByte);
+ }
+
+ return true;
+}
+
+bool ValidateGetRenderbufferParameterivBase(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (target != GL_RENDERBUFFER)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
+ return false;
+ }
+
+ Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
+ if (renderbuffer == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
+ 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->getExtensions().framebufferMultisample)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+ return true;
+}
+
+bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (GetValidShader(context, 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().translatedShaderSource)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+ return true;
+}
+
+bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
+ return false;
+ }
+
+ if (context->getTargetTexture(target) == nullptr)
+ {
+ // Should only be possible for external textures
+ context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
+ 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().textureUsage)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->getExtensions().textureFilterAnisotropic)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
+ 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:
+ case GL_TEXTURE_COMPARE_MODE:
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ if (!context->getExtensions().textureSRGBDecode)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
+{
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_CLAMP_TO_EDGE:
+ break;
+
+ case GL_REPEAT:
+ case GL_MIRRORED_REPEAT:
+ if (isExternalTextureTarget)
+ {
+ // OES_EGL_image_external specifies this error.
+ context->handleError(Error(
+ GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureMinFilterValue(Context *context,
+ ParamType *params,
+ bool isExternalTextureTarget)
+{
+ 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 (isExternalTextureTarget)
+ {
+ // OES_EGL_image_external specifies this error.
+ context->handleError(
+ Error(GL_INVALID_ENUM,
+ "external textures only support NEAREST and LINEAR filtering"));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
+{
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureCompareModeValue(Context *context, 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->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureCompareFuncValue(Context *context, 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->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
+{
+ if (!context->getExtensions().textureSRGBDecode)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
+ return false;
+ }
+
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_DECODE_EXT:
+ case GL_SKIP_DECODE_EXT:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTexParameterBase(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ ParamType *params)
+{
+ if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
+ return false;
+ }
+
+ if (context->getTargetTexture(target) == nullptr)
+ {
+ // Should only be possible for external textures
+ context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
+ return false;
+ }
+
+ const GLsizei minBufSize = 1;
+ if (bufSize >= 0 && bufSize < minBufSize)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
+ 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)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
+ return false;
+ }
+ if (target == GL_TEXTURE_EXTERNAL_OES &&
+ !context->getExtensions().eglImageExternalEssl3)
+ {
+ context->handleError(Error(GL_INVALID_ENUM,
+ "ES3 texture parameters are not available without "
+ "GL_OES_EGL_image_external_essl3."));
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MIN_FILTER:
+ if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAG_FILTER:
+ if (!ValidateTextureMagFilterValue(context, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_USAGE_ANGLE:
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_NONE:
+ case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->getExtensions().textureFilterAnisotropic)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
+ return false;
+ }
+
+ // we assume the parameter passed to this validation method is truncated, not rounded
+ if (params[0] < 1)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
+ 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, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (!ValidateTextureCompareFuncValue(context, 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->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_BASE_LEVEL:
+ if (params[0] < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
+ return false;
+ }
+ if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAX_LEVEL:
+ if (params[0] < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ if (!ValidateTextureSRGBDecodeValue(context, params))
+ {
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateSamplerParameterBase(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ ParamType *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
+ return false;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
+ return false;
+ }
+
+ const GLsizei minBufSize = 1;
+ if (bufSize >= 0 && bufSize < minBufSize)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ if (!ValidateTextureWrapModeValue(context, params, false))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MIN_FILTER:
+ if (!ValidateTextureMinFilterValue(context, params, false))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAG_FILTER:
+ if (!ValidateTextureMagFilterValue(context, 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, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (!ValidateTextureCompareFuncValue(context, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ if (!ValidateTextureSRGBDecodeValue(context, params))
+ {
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetSamplerParameterBase(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
+ return false;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
+ 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_SRGB_DECODE_EXT:
+ if (!context->getExtensions().textureSRGBDecode)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+ return true;
+}
+
+bool ValidateGetVertexAttribBase(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei *length,
+ bool pointer,
+ bool pureIntegerEntryPoint)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
+ return false;
+ }
+
+ if (index >= context->getCaps().maxVertexAttributes)
+ {
+ context->handleError(Error(
+ GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
+ return false;
+ }
+
+ if (pointer)
+ {
+ if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown 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().instancedArrays)
+ {
+ context->handleError(Error(GL_INVALID_ENUM,
+ "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
+ "3.0 or GL_ANGLE_instanced_arrays."));
+ return false;
+ }
+ break;
+
+ case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+ return false;
+ }
+ }
+
+ if (length)
+ {
+ if (pname == GL_CURRENT_VERTEX_ATTRIB)
+ {
+ *length = 4;
+ }
+ else
+ {
+ *length = 1;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveUniformBlockivBase(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
+ 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->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+ return false;
+ }
+
+ if (length)
+ {
+ if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
+ {
+ const UniformBlock &uniformBlock =
+ programObject->getUniformBlockByIndex(uniformBlockIndex);
+ *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
+ }
+ else
+ {
+ *length = 1;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferParameterBase(ValidationContext *context,
+ GLenum target,
+ GLenum pname,
+ bool pointerVersion,
+ GLsizei *numParams)
+{
+ if (numParams)
+ {
+ *numParams = 0;
+ }
+
+ if (!ValidBufferTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
+ return false;
+ }
+
+ const Buffer *buffer = context->getGLState().getTargetBuffer(target);
+ if (!buffer)
+ {
+ // A null buffer means that "0" is bound to the requested buffer target
+ context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
+ 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.mapBuffer)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
+ 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.mapBuffer &&
+ !extensions.mapBufferRange)
+ {
+ context->handleError(Error(
+ GL_INVALID_ENUM,
+ "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
+ return false;
+ }
+ break;
+
+ case GL_BUFFER_MAP_POINTER:
+ if (!pointerVersion)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM,
+ "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
+ return false;
+ }
+ break;
+
+ case GL_BUFFER_ACCESS_FLAGS:
+ case GL_BUFFER_MAP_OFFSET:
+ case GL_BUFFER_MAP_LENGTH:
+ if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
+ {
+ context->handleError(Error(
+ GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+ return false;
+ }
+
+ // All buffer parameter queries return one value.
+ if (numParams)
+ {
+ *numParams = 1;
+ }
+
+ return true;
+}
+
+bool ValidateGetInternalFormativBase(Context *context,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams)
+{
+ if (numParams)
+ {
+ *numParams = 0;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
+ return false;
+ }
+
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (!formatCaps.renderable)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_RENDERBUFFER:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+ 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->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+ return false;
+ }
+
+ if (numParams)
+ {
+ // glGetInternalFormativ will not overflow bufSize
+ *numParams = std::min(bufSize, maxWriteParams);
+ }
+
+ return true;
+}
+
+} // anonymous namespace
+
+bool ValidTextureTarget(const ValidationContext *context, GLenum target)
+{
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_CUBE_MAP:
+ return true;
+
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ return (context->getClientMajorVersion() >= 3);
+
+ default:
+ return false;
+ }
+}
+
+bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
+{
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_CUBE_MAP:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
+{
+ switch (target)
+ {
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ return (context->getClientMajorVersion() >= 3);
+
+ 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 ValidationContext *context, GLenum target)
+{
+ return (target == GL_TEXTURE_EXTERNAL_OES) &&
+ (context->getExtensions().eglImageExternal ||
+ context->getExtensions().eglStreamConsumerExternal);
+}
+
+// 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 ValidationContext *context, GLenum target)
+{
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
+{
+ switch (target)
+ {
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool ValidFramebufferTarget(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: return true;
+ case GL_DRAW_FRAMEBUFFER: return true;
+ default: return false;
+ }
+}
+
+bool ValidBufferTarget(const ValidationContext *context, GLenum target)
+{
+ switch (target)
+ {
+ case GL_ARRAY_BUFFER:
+ case GL_ELEMENT_ARRAY_BUFFER:
+ return true;
+
+ case GL_PIXEL_PACK_BUFFER:
+ case GL_PIXEL_UNPACK_BUFFER:
+ return (context->getExtensions().pixelBufferObject ||
+ context->getClientMajorVersion() >= 3);
+
+ case GL_COPY_READ_BUFFER:
+ case GL_COPY_WRITE_BUFFER:
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ case GL_UNIFORM_BUFFER:
+ return (context->getClientMajorVersion() >= 3);
+
+ default:
+ return false;
+ }
+}
+
+bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
+{
+ const auto &caps = context->getCaps();
+ size_t maxDimension = 0;
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ maxDimension = caps.max2DTextureSize;
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ maxDimension = caps.maxCubeMapTextureSize;
+ break;
+ case GL_TEXTURE_3D:
+ maxDimension = caps.max3DTextureSize;
+ break;
+ case GL_TEXTURE_2D_ARRAY:
+ maxDimension = caps.max2DTextureSize;
+ break;
+ default: UNREACHABLE();
+ }
+
+ return level <= gl::log2(static_cast<int>(maxDimension));
+}
+
+bool ValidImageSizeParameters(const Context *context,
+ GLenum target,
+ GLint level,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ bool isSubImage)
+{
+ if (level < 0 || width < 0 || height < 0 || depth < 0)
+ {
+ return false;
+ }
+
+ // TexSubImage parameters can be NPOT without textureNPOT extension,
+ // as long as the destination texture is POT.
+ if (!isSubImage && !context->getExtensions().textureNPOT &&
+ (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
+ {
+ return false;
+ }
+
+ if (!ValidMipLevel(context, target, level))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+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_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidCompressedImageSize(const ValidationContext *context,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height)
+{
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ if (!formatInfo.compressed)
+ {
+ return false;
+ }
+
+ if (width < 0 || height < 0)
+ {
+ return false;
+ }
+
+ if (CompressedTextureFormatRequiresExactSize(internalFormat))
+ {
+ if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
+ width % formatInfo.compressedBlockWidth != 0) ||
+ (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
+ height % formatInfo.compressedBlockHeight != 0))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidImageDataSize(ValidationContext *context,
+ GLenum textureTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum internalFormat,
+ GLenum type,
+ const GLvoid *pixels,
+ GLsizei imageSize)
+{
+ gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
+ 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.
+ GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
+ const gl::Extents size(width, height, depth);
+ const auto &unpack = context->getGLState().getUnpackState();
+
+ bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
+ auto endByteOrErr = formatInfo.computePackUnpackEndByte(size, unpack, targetIs3D);
+ if (endByteOrErr.isError())
+ {
+ context->handleError(endByteOrErr.getError());
+ return false;
+ }
+
+ GLuint endByte = endByteOrErr.getResult();
+
+ if (pixelUnpackBuffer)
+ {
+ CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
+ 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->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ else
+ {
+ ASSERT(imageSize >= 0);
+ if (pixels == nullptr && imageSize != 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
+ return false;
+ }
+
+ if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidQueryType(const Context *context, GLenum queryType)
+{
+ static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
+ static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, "GL extension enums not equal.");
+
+ switch (queryType)
+ {
+ case GL_ANY_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ return true;
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ return (context->getClientMajorVersion() >= 3);
+ case GL_TIME_ELAPSED_EXT:
+ return context->getExtensions().disjointTimerQuery;
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ return context->getExtensions().syncQuery;
+ default:
+ return false;
+ }
+}
+
+Program *GetValidProgram(ValidationContext *context, GLuint 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->getProgram(id);
+
+ if (!validProgram)
+ {
+ if (context->getShader(id))
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
+ }
+ }
+
+ return validProgram;
+}
+
+Shader *GetValidShader(ValidationContext *context, GLuint id)
+{
+ // See ValidProgram for spec details.
+
+ Shader *validShader = context->getShader(id);
+
+ if (!validShader)
+ {
+ if (context->getProgram(id))
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
+ }
+ }
+
+ return validShader;
+}
+
+bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
+{
+ if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+ {
+ const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
+
+ if (colorAttachment >= context->getCaps().maxColorAttachments)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ else
+ {
+ switch (attachment)
+ {
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ break;
+
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (!context->getExtensions().webglCompatibility &&
+ context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height)
+{
+ switch (target)
+ {
+ case GL_RENDERBUFFER:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (width < 0 || height < 0 || samples < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (!formatCaps.renderable)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ 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 gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+ if (formatInfo.pixelBytes == 0)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ GLuint handle = context->getGLState().getRenderbufferId();
+ if (handle == 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height)
+{
+ ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
+
+ // 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 (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ 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->handleError(Error(GL_OUT_OF_MEMORY));
+ return false;
+ }
+ }
+
+ return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
+}
+
+bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
+ GLenum renderbuffertarget, GLuint renderbuffer)
+{
+ if (!ValidFramebufferTarget(target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+
+ ASSERT(framebuffer);
+ if (framebuffer->id() == 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
+ return false;
+ }
+
+ if (!ValidateAttachmentTarget(context, 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 != 0)
+ {
+ if (!context->getRenderbuffer(renderbuffer))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateBlitFramebufferParameters(ValidationContext *context,
+ 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->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (mask == 0)
+ {
+ // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
+ // buffers are copied.
+ 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->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const auto &glState = context->getGLState();
+ gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
+ gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
+
+ if (!readFramebuffer || !drawFramebuffer)
+ {
+ context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if (readFramebuffer->id() == drawFramebuffer->id())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if (drawFramebuffer->getSamples(context->getContextState()) != 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
+
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
+ const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
+ const Extensions &extensions = context->getExtensions();
+
+ if (readColorBuffer && drawColorBuffer)
+ {
+ 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.colorBufferFloat)
+ {
+ bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
+ bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
+
+ if (readFixedOrFloat != drawFixedOrFloat)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "If the read buffer contains fixed-point or "
+ "floating-point values, the draw buffer "
+ "must as well."));
+ return false;
+ }
+ }
+ else if (readFixedPoint != drawFixedPoint)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "If the read buffer contains fixed-point "
+ "values, the draw buffer must as well."));
+ return false;
+ }
+
+ if (readComponentType == GL_UNSIGNED_INT &&
+ drawComponentType != GL_UNSIGNED_INT)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (readComponentType == GL_INT && drawComponentType != GL_INT)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (readColorBuffer->getSamples() > 0 &&
+ (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+
+ if ((readFormat.info->componentType == GL_INT ||
+ readFormat.info->componentType == GL_UNSIGNED_INT) &&
+ filter == GL_LINEAR)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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 gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
+ const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
+
+ if (readBuffer && drawBuffer)
+ {
+ if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (readBuffer->getSamples() > 0 && !sameBounds)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool ValidateReadPixels(ValidationContext *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels)
+{
+ return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
+}
+
+bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLvoid *pixels)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
+ pixels))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateReadnPixelsEXT(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLvoid *pixels)
+{
+ if (bufSize < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
+ return false;
+ }
+
+ return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
+ pixels);
+}
+
+bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLvoid *data)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
+{
+ if (!context->getExtensions().occlusionQueryBoolean &&
+ !context->getExtensions().disjointTimerQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
+{
+ if (!context->getExtensions().occlusionQueryBoolean &&
+ !context->getExtensions().disjointTimerQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
+{
+ if (!ValidQueryType(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
+ return false;
+ }
+
+ if (id == 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
+ 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->getGLState().isQueryActive(target))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
+ return false;
+ }
+
+ Query *queryObject = context->getQuery(id, true, target);
+
+ // check that name was obtained with glGenQueries
+ if (!queryObject)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
+ return false;
+ }
+
+ // check for type mismatch
+ if (queryObject->getType() != target)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
+{
+ if (!context->getExtensions().occlusionQueryBoolean &&
+ !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+ return false;
+ }
+
+ return ValidateBeginQueryBase(context, target, id);
+}
+
+bool ValidateEndQueryBase(gl::Context *context, GLenum target)
+{
+ if (!ValidQueryType(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
+ return false;
+ }
+
+ const Query *queryObject = context->getGLState().getActiveQuery(target);
+
+ if (queryObject == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
+{
+ if (!context->getExtensions().occlusionQueryBoolean &&
+ !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+ return false;
+ }
+
+ return ValidateEndQueryBase(context, target);
+}
+
+bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
+{
+ if (!context->getExtensions().disjointTimerQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
+ return false;
+ }
+
+ if (target != GL_TIMESTAMP_EXT)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
+ return false;
+ }
+
+ Query *queryObject = context->getQuery(id, true, target);
+ if (queryObject == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
+ return false;
+ }
+
+ if (context->getGLState().isQueryActive(queryObject))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
+{
+ if (numParams)
+ {
+ *numParams = 0;
+ }
+
+ if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_CURRENT_QUERY_EXT:
+ if (target == GL_TIMESTAMP_EXT)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
+ return false;
+ }
+ break;
+ case GL_QUERY_COUNTER_BITS_EXT:
+ if (!context->getExtensions().disjointTimerQuery ||
+ (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
+ return false;
+ }
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
+ return false;
+ }
+
+ if (numParams)
+ {
+ // All queries return only one value
+ *numParams = 1;
+ }
+
+ return true;
+}
+
+bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
+{
+ if (!context->getExtensions().occlusionQueryBoolean &&
+ !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+ return false;
+ }
+
+ return ValidateGetQueryivBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetQueryivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetQueryivBase(context, target, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
+{
+ if (numParams)
+ {
+ *numParams = 0;
+ }
+
+ Query *queryObject = context->getQuery(id, false, GL_NONE);
+
+ if (!queryObject)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
+ return false;
+ }
+
+ if (context->getGLState().isQueryActive(queryObject))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_QUERY_RESULT_EXT:
+ case GL_QUERY_RESULT_AVAILABLE_EXT:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
+ return false;
+ }
+
+ if (numParams)
+ {
+ *numParams = 1;
+ }
+
+ return true;
+}
+
+bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
+{
+ if (!context->getExtensions().disjointTimerQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+ return false;
+ }
+ return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectivRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!context->getExtensions().disjointTimerQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
+{
+ if (!context->getExtensions().disjointTimerQuery &&
+ !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+ return false;
+ }
+ return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ if (!context->getExtensions().disjointTimerQuery &&
+ !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
+{
+ if (!context->getExtensions().disjointTimerQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+ return false;
+ }
+ return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params)
+{
+ if (!context->getExtensions().disjointTimerQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
+{
+ if (!context->getExtensions().disjointTimerQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+ return false;
+ }
+ return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint64 *params)
+{
+ if (!context->getExtensions().disjointTimerQuery)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidateUniformCommonBase(gl::Context *context,
+ GLenum targetUniformType,
+ GLint location,
+ GLsizei count,
+ const LinkedUniform **uniformOut)
+{
+ if (count < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::Program *program = context->getGLState().getProgram();
+ if (!program)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (program->isIgnoredUniformLocation(location))
+ {
+ // Silently ignore the uniform command
+ return false;
+ }
+
+ if (!program->isValidUniformLocation(location))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const LinkedUniform &uniform = program->getUniformByLocation(location);
+
+ // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+ if (!uniform.isArray() && count > 1)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ *uniformOut = &uniform;
+ return true;
+}
+
+bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
+{
+ // Check for ES3 uniform entry points
+ if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
+ context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const LinkedUniform *uniform = nullptr;
+ if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
+ {
+ return false;
+ }
+
+ GLenum targetBoolType = VariableBoolVectorType(uniformType);
+ bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
+ if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
+ GLboolean transpose)
+{
+ // Check for ES3 uniform entry points
+ int rows = VariableRowCount(matrixType);
+ int cols = VariableColumnCount(matrixType);
+ if (rows != cols && context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ const LinkedUniform *uniform = nullptr;
+ if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
+ {
+ return false;
+ }
+
+ if (uniform->type != matrixType)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStateQuery(ValidationContext *context,
+ GLenum pname,
+ GLenum *nativeType,
+ unsigned int *numParams)
+{
+ if (!context->getQueryParameterInfo(pname, nativeType, numParams))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+
+ if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
+ {
+ unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
+
+ if (colorAttachment >= caps.maxDrawBuffers)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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:
+ break;
+ case GL_TEXTURE_BINDING_EXTERNAL_OES:
+ if (!context->getExtensions().eglStreamConsumerExternal &&
+ !context->getExtensions().eglImageExternal)
+ {
+ context->handleError(Error(GL_INVALID_ENUM,
+ "Neither NV_EGL_stream_consumer_external nor "
+ "GL_OES_EGL_image_external extensions enabled"));
+ return false;
+ }
+ break;
+
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ {
+ if (context->getGLState().getReadFramebuffer()->checkStatus(
+ context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
+ ASSERT(framebuffer);
+
+ if (framebuffer->getReadBufferState() == GL_NONE)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
+ return false;
+ }
+
+ const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
+ if (!attachment)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // pname is valid, but there are no parameters to return
+ if (*numParams == 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRobustStateQuery(ValidationContext *context,
+ GLenum pname,
+ GLsizei bufSize,
+ GLenum *nativeType,
+ unsigned int *numParams)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateStateQuery(context, pname, nativeType, numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *numParams))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopyTexImageParametersBase(ValidationContext *context,
+ GLenum 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)
+{
+ if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (border != 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (!ValidMipLevel(context, target, level))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ const auto &state = context->getGLState();
+ auto readFramebuffer = state.getReadFramebuffer();
+ if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (readFramebuffer->getReadBufferState() == GL_NONE)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
+ return false;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+
+ GLuint maxDimension = 0;
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ maxDimension = caps.max2DTextureSize;
+ break;
+
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ maxDimension = caps.maxCubeMapTextureSize;
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ maxDimension = caps.max2DTextureSize;
+ break;
+
+ case GL_TEXTURE_3D:
+ maxDimension = caps.max3DTextureSize;
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ gl::Texture *texture =
+ state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ if (!texture)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (texture->getImmutableFormat() && !isSubImage)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+
+ if (formatInfo.depthBits > 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ else
+ {
+ if (IsCubeMapTextureTarget(target) && width != height)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ int maxLevelDimension = (maxDimension >> level);
+ if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+
+ if (textureFormatOut)
+ {
+ *textureFormatOut = texture->getFormat(target, level);
+ }
+ return true;
+}
+
+static bool ValidateDrawBase(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLsizei primcount)
+{
+ switch (mode)
+ {
+ case GL_POINTS:
+ case GL_LINES:
+ case GL_LINE_LOOP:
+ case GL_LINE_STRIP:
+ case GL_TRIANGLES:
+ case GL_TRIANGLE_STRIP:
+ case GL_TRIANGLE_FAN:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (count < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ const State &state = context->getGLState();
+
+ // Check for mapped buffers
+ if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ Framebuffer *framebuffer = state.getDrawFramebuffer();
+ if (context->getLimitations().noSeparateStencilRefsAndMasks)
+ {
+ const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
+ GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
+ GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
+ const DepthStencilState &depthStencilState = state.getDepthStencilState();
+ if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
+ (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
+ state.getStencilRef() != state.getStencilBackRef() ||
+ (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
+ (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
+ {
+ // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
+ // Section 6.10 of the WebGL 1.0 spec
+ ERR(
+ "This ANGLE implementation does not support separate front/back stencil "
+ "writemasks, reference values, or stencil mask values.");
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ gl::Program *program = state.getProgram();
+ if (!program)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!program->validateSamplers(NULL, context->getCaps()))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Uniform buffer validation
+ for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
+ {
+ const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
+ GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
+ const OffsetBindingPointer<Buffer> &uniformBuffer =
+ state.getIndexedUniformBuffer(blockBinding);
+
+ if (uniformBuffer.get() == nullptr)
+ {
+ // undefined behaviour
+ context->handleError(
+ Error(GL_INVALID_OPERATION,
+ "It is undefined behaviour to have a used but unbound uniform buffer."));
+ return false;
+ }
+
+ size_t uniformBufferSize = uniformBuffer.getSize();
+ if (uniformBufferSize == 0)
+ {
+ // Bind the whole buffer.
+ uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
+ }
+
+ if (uniformBufferSize < uniformBlock.dataSize)
+ {
+ // undefined behaviour
+ context->handleError(
+ Error(GL_INVALID_OPERATION,
+ "It is undefined behaviour to use a uniform buffer that is too small."));
+ return false;
+ }
+ }
+
+ // No-op if zero count
+ return (count > 0);
+}
+
+bool ValidateDrawArrays(ValidationContext *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount)
+{
+ if (first < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ const State &state = context->getGLState();
+ gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
+ curTransformFeedback->getPrimitiveMode() != mode)
+ {
+ // 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)
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!ValidateDrawBase(context, mode, count, primcount))
+ {
+ return false;
+ }
+
+ if (!ValidateDrawAttribs(context, primcount, count))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+{
+ if (primcount < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (!ValidateDrawArrays(context, mode, first, count, primcount))
+ {
+ return false;
+ }
+
+ // No-op if zero primitive count
+ return (primcount > 0);
+}
+
+static bool ValidateDrawInstancedANGLE(Context *context)
+{
+ // Verify there is at least one active attribute with a divisor of zero
+ const gl::State &state = context->getGLState();
+
+ gl::Program *program = state.getProgram();
+
+ const VertexArray *vao = state.getVertexArray();
+ for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
+ if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
+ {
+ return true;
+ }
+ }
+
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "ANGLE_instanced_arrays requires that at least one active attribute"
+ "has a divisor of zero."));
+ return false;
+}
+
+bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+{
+ if (!ValidateDrawInstancedANGLE(context))
+ {
+ return false;
+ }
+
+ return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
+}
+
+bool ValidateDrawElements(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei primcount,
+ IndexRange *indexRangeOut)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT:
+ break;
+ case GL_UNSIGNED_INT:
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ const State &state = context->getGLState();
+
+ gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
+ {
+ // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
+ // while transform feedback is active, (3.0.2, section 2.14, pg 86)
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Check for mapped buffers
+ if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::VertexArray *vao = state.getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+ if (!indices && !elementArrayBuffer)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (elementArrayBuffer)
+ {
+ const gl::Type &typeInfo = gl::GetTypeInfo(type);
+
+ GLint64 offset = reinterpret_cast<GLint64>(indices);
+ GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
+
+ // check for integer overflows
+ if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
+ byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
+ {
+ context->handleError(Error(GL_OUT_OF_MEMORY));
+ return false;
+ }
+
+ // Check for reading past the end of the bound buffer object
+ if (byteCount > elementArrayBuffer->getSize())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ else if (!indices)
+ {
+ // Catch this programming error here
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!ValidateDrawBase(context, mode, count, primcount))
+ {
+ return false;
+ }
+
+ // Use max index to validate if our vertex buffers are large enough for the pull.
+ // TODO: offer fast path, with disabled index validation.
+ // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
+ if (elementArrayBuffer)
+ {
+ uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
+ Error error =
+ elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
+ state.isPrimitiveRestartEnabled(), indexRangeOut);
+ if (error.isError())
+ {
+ context->handleError(error);
+ return false;
+ }
+ }
+ else
+ {
+ *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
+ }
+
+ // 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<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
+ return false;
+ }
+
+ if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end + 1)))
+ {
+ return false;
+ }
+
+ // No op if there are no real indices in the index data (all are primitive restart).
+ return (indexRangeOut->vertexIndexCount > 0);
+}
+
+bool ValidateDrawElementsInstanced(Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei primcount,
+ IndexRange *indexRangeOut)
+{
+ if (primcount < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
+ {
+ return false;
+ }
+
+ // No-op zero primitive count
+ return (primcount > 0);
+}
+
+bool ValidateDrawElementsInstancedANGLE(Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei primcount,
+ IndexRange *indexRangeOut)
+{
+ if (!ValidateDrawInstancedANGLE(context))
+ {
+ return false;
+ }
+
+ return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
+}
+
+bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
+ GLuint texture, GLint level)
+{
+ if (!ValidFramebufferTarget(target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (!ValidateAttachmentTarget(context, attachment))
+ {
+ return false;
+ }
+
+ if (texture != 0)
+ {
+ gl::Texture *tex = context->getTexture(texture);
+
+ if (tex == NULL)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (level < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+
+ const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (framebuffer->id() == 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
+ GLenum textarget, GLuint 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().fboRenderMipmap &&
+ level != 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
+ {
+ return false;
+ }
+
+ if (texture != 0)
+ {
+ gl::Texture *tex = context->getTexture(texture);
+ ASSERT(tex);
+
+ const gl::Caps &caps = context->getCaps();
+
+ switch (textarget)
+ {
+ case GL_TEXTURE_2D:
+ {
+ if (level > gl::log2(caps.max2DTextureSize))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ if (tex->getTarget() != GL_TEXTURE_2D)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ {
+ if (level > gl::log2(caps.maxCubeMapTextureSize))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ const Format &format = tex->getFormat(textarget, level);
+ if (format.info->compressed)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
+{
+ if (program == 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (!programObject || !programObject->isLinked())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!programObject->isValidUniformLocation(location))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
+{
+ return ValidateGetUniformBase(context, program, location);
+}
+
+bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
+{
+ return ValidateGetUniformBase(context, program, location);
+}
+
+static bool ValidateSizedGetUniform(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (!ValidateGetUniformBase(context, program, location))
+ {
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+ return false;
+ }
+
+ gl::Program *programObject = context->getProgram(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->handleError(
+ Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
+ return false;
+ }
+
+ if (length)
+ {
+ *length = VariableComponentCount(uniform.type);
+ }
+
+ return true;
+}
+
+bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+{
+ return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
+}
+
+bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
+{
+ return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
+}
+
+bool ValidateGetUniformfvRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ // bufSize is validated in ValidateSizedGetUniform
+ return ValidateSizedGetUniform(context, program, location, bufSize, length);
+}
+
+bool ValidateGetUniformivRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ // bufSize is validated in ValidateSizedGetUniform
+ return ValidateSizedGetUniform(context, program, location, bufSize, length);
+}
+
+bool ValidateGetUniformuivRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
+ return false;
+ }
+
+ // bufSize is validated in ValidateSizedGetUniform
+ return ValidateSizedGetUniform(context, program, location, bufSize, length);
+}
+
+bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
+ const GLenum *attachments, bool defaultFramebuffer)
+{
+ if (numAttachments < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
+ return false;
+ }
+
+ for (GLsizei i = 0; i < numAttachments; ++i)
+ {
+ if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
+ {
+ if (defaultFramebuffer)
+ {
+ context->handleError(Error(
+ GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
+ return false;
+ }
+
+ if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "Requested color attachment is greater than the maximum "
+ "supported color attachments"));
+ return false;
+ }
+ }
+ else
+ {
+ switch (attachments[i])
+ {
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (defaultFramebuffer)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM,
+ "Invalid attachment when the default framebuffer is bound"));
+ return false;
+ }
+ break;
+ case GL_COLOR:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ if (!defaultFramebuffer)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM,
+ "Invalid attachment when the default framebuffer is not bound"));
+ return false;
+ }
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
+{
+ // Note that debug marker calls must not set error state
+
+ if (length < 0)
+ {
+ return false;
+ }
+
+ if (marker == nullptr)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
+{
+ // 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 ValidateEGLImageTargetTexture2DOES(Context *context,
+ egl::Display *display,
+ GLenum target,
+ egl::Image *image)
+{
+ if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ if (!context->getExtensions().eglImage)
+ {
+ context->handleError(Error(
+ GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
+ }
+ break;
+
+ case GL_TEXTURE_EXTERNAL_OES:
+ if (!context->getExtensions().eglImageExternal)
+ {
+ context->handleError(Error(
+ GL_INVALID_ENUM,
+ "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
+ return false;
+ }
+
+ if (!display->isValidImage(image))
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
+ return false;
+ }
+
+ if (image->getSamples() > 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "cannot create a 2D texture from a multisampled EGL image."));
+ return false;
+ }
+
+ const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
+ if (!textureCaps.texturable)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "EGL image internal format is not supported as a texture."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
+ egl::Display *display,
+ GLenum target,
+ egl::Image *image)
+{
+ if (!context->getExtensions().eglImage)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_RENDERBUFFER:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
+ return false;
+ }
+
+ if (!display->isValidImage(image))
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
+ return false;
+ }
+
+ const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
+ if (!textureCaps.renderable)
+ {
+ context->handleError(Error(
+ GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindVertexArrayBase(Context *context, GLuint array)
+{
+ if (!context->isVertexArrayGenerated(array))
+ {
+ // The default VAO should always exist
+ ASSERT(array != 0);
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLinkProgram(Context *context, GLuint program)
+{
+ if (context->hasActiveTransformFeedback(program))
+ {
+ // ES 3.0.4 section 2.15 page 91
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "Cannot link program while program is associated with an active "
+ "transform feedback object."));
+ return false;
+ }
+ return true;
+}
+
+bool ValidateProgramBinaryBase(Context *context,
+ GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length)
+{
+ Program *programObject = GetValidProgram(context, 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->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
+ return false;
+ }
+
+ if (context->hasActiveTransformFeedback(program))
+ {
+ // ES 3.0.4 section 2.15 page 91
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "Cannot change program binary while program is associated with "
+ "an active transform feedback object."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramBinaryBase(Context *context,
+ GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary)
+{
+ Program *programObject = GetValidProgram(context, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateUseProgram(Context *context, GLuint program)
+{
+ if (program != 0)
+ {
+ Program *programObject = context->getProgram(program);
+ if (!programObject)
+ {
+ // ES 3.1.0 section 7.3 page 72
+ if (context->getShader(program))
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION,
+ "Attempted to use a single shader instead of a shader program."));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
+ return false;
+ }
+ }
+ if (!programObject->isLinked())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
+ return false;
+ }
+ }
+ if (context->getGLState().isTransformFeedbackActiveUnpaused())
+ {
+ // ES 3.0.4 section 2.15 page 91
+ context->handleError(
+ Error(GL_INVALID_OPERATION,
+ "Cannot change active program while transform feedback is unpaused."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopyTexImage2D(ValidationContext *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
+ 0, x, y, width, height, border);
+ }
+
+ ASSERT(context->getClientMajorVersion() == 3);
+ return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
+ 0, x, y, width, height, border);
+}
+
+bool ValidateFramebufferRenderbuffer(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer)
+{
+ if (!ValidFramebufferTarget(target) ||
+ (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return ValidateFramebufferRenderbufferParameters(context, target, attachment,
+ renderbuffertarget, renderbuffer);
+}
+
+bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
+{
+ // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
+ if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
+ return false;
+ }
+
+ ASSERT(context->getGLState().getDrawFramebuffer());
+ GLuint frameBufferId = context->getGLState().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->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
+ return false;
+ }
+ else if (bufs[colorAttachment] >= maxColorAttachment)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
+ return false;
+ }
+ else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
+ frameBufferId != 0)
+ {
+ // INVALID_OPERATION-GL is bound to buffer and ith argument
+ // is not COLOR_ATTACHMENTi or NONE
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
+ 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 == 0)
+ {
+ if (n != 1)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "n must be 1 when GL is bound to the default framebuffer"));
+ return false;
+ }
+
+ if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
+ {
+ context->handleError(Error(
+ GL_INVALID_OPERATION,
+ "Only NONE or BACK are valid values when drawing to the default framebuffer"));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateCopyTexSubImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
+ yoffset, x, y, width, height, 0);
+ }
+
+ return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
+ yoffset, 0, x, y, width, height, 0);
+}
+
+bool ValidateGetBufferPointervBase(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei *length,
+ void **params)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION,
+ "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
+ return false;
+ }
+
+ if (!ValidBufferTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_BUFFER_MAP_POINTER:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown 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->getGLState().getTargetBuffer(target) == nullptr)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+
+ return true;
+}
+
+bool ValidateUnmapBufferBase(Context *context, GLenum target)
+{
+ if (!ValidBufferTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
+ return false;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+ if (buffer == nullptr || !buffer->isMapped())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateMapBufferRangeBase(Context *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ if (!ValidBufferTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
+ return false;
+ }
+
+ if (offset < 0 || length < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
+ return false;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
+ 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->handleError(
+ Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
+ return false;
+ }
+
+ // Check for invalid bits in the mask
+ GLbitfield allAccessBits = 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 (access & ~(allAccessBits))
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
+ return false;
+ }
+
+ if (length == 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
+ return false;
+ }
+
+ if (buffer->isMapped())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
+ return false;
+ }
+
+ // Check for invalid bit combinations
+ if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
+ 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->handleError(Error(GL_INVALID_OPERATION,
+ "Invalid access bits when mapping buffer for reading: 0x%X.",
+ access));
+ return false;
+ }
+
+ if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
+ {
+ context->handleError(Error(
+ GL_INVALID_OPERATION,
+ "The explicit flushing bit may only be set if the buffer is mapped for writing."));
+ return false;
+ }
+ return true;
+}
+
+bool ValidateFlushMappedBufferRangeBase(Context *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr length)
+{
+ if (offset < 0 || length < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
+ return false;
+ }
+
+ if (!ValidBufferTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
+ return false;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+ if (buffer == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
+ return false;
+ }
+
+ if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
+ {
+ context->handleError(Error(
+ GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
+ 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->handleError(
+ Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGenerateMipmap(Context *context, GLenum target)
+{
+ if (!ValidTextureTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ Texture *texture = context->getTargetTexture(target);
+
+ if (texture == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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 >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
+ const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
+ const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
+
+ // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
+ // unsized formats or that are color renderable and filterable. Since we do not track if
+ // the texture was created with sized or unsized format (only sized formats are stored),
+ // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
+ // be able to) because they aren't color renderable. Simply do a special case for LUMA
+ // textures since they're the only texture format that can be created with unsized formats
+ // that is not color renderable. New unsized formats are unlikely to be added, since ES2
+ // was the last version to use add them.
+ if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
+ (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // GL_EXT_sRGB does not support mipmap generation on sRGB textures
+ if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Non-power of 2 ES2 check
+ if (!context->getExtensions().textureNPOT &&
+ (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
+ !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
+ {
+ ASSERT(context->getClientMajorVersion() <= 2 &&
+ (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Cube completeness check
+ if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenTextures(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenOrDelete(Context *context, GLint n)
+{
+ if (n < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
+ return false;
+ }
+ return true;
+}
+
+bool ValidateEnable(Context *context, GLenum cap)
+{
+ if (!ValidCap(context, cap, false))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
+ return false;
+ }
+
+ if (context->getLimitations().noSampleAlphaToCoverageSupport &&
+ cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
+ {
+ const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
+ context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
+
+ // We also output an error message to the debugger window if tracing is active, so that
+ // developers can see the error message.
+ ERR("%s", errorMessage);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDisable(Context *context, GLenum cap)
+{
+ if (!ValidCap(context, cap, false))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsEnabled(Context *context, GLenum cap)
+{
+ if (!ValidCap(context, cap, true))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
+{
+ if (!context->getExtensions().robustClientMemory)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
+{
+ if (bufSize < numParams)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "%u parameters are required but %i were provided.", numParams,
+ bufSize));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei *numParams)
+{
+ // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
+ *numParams = 1;
+
+ if (!ValidFramebufferTarget(target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ 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_COLOR_ENCODING:
+ if (clientVersion < 3 && !context->getExtensions().sRGB)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ 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->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ // Determine if the attachment is a valid enum
+ switch (attachment)
+ {
+ case GL_BACK:
+ case GL_FRONT:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (clientVersion < 3)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ break;
+
+ default:
+ if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
+ (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ }
+
+ const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (framebuffer->id() == 0)
+ {
+ if (clientVersion < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ switch (attachment)
+ {
+ case GL_BACK:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+
+ const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(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->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ if (attachmentObject->type() != GL_TEXTURE)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ if (attachmentObject->type() != GL_TEXTURE)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+ if (attachmentObject->type() != GL_TEXTURE)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ 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->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ default:
+ if (clientVersion < 3)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *numParams))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferParameteriv(ValidationContext *context,
+ GLenum target,
+ GLenum pname,
+ GLint *params)
+{
+ return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
+}
+
+bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferParameteri64v(ValidationContext *context,
+ GLenum target,
+ GLenum pname,
+ GLint64 *params)
+{
+ return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
+}
+
+bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
+{
+ // Currently, all GetProgramiv queries return 1 parameter
+ *numParams = 1;
+
+ Program *programObject = GetValidProgram(context, 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().getProgramBinary)
+ {
+ context->handleError(Error(GL_INVALID_ENUM,
+ "Querying GL_PROGRAM_BINARY_LENGTH requires "
+ "GL_OES_get_program_binary or ES 3.0."));
+ 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->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramivRobustANGLE(Context *context,
+ GLuint program,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetProgramiv(context, program, pname, numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *numParams))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetRenderbufferParameteriv(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLint *params)
+{
+ return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
+{
+ return ValidateGetShaderivBase(context, shader, pname, nullptr);
+}
+
+bool ValidateGetShaderivRobustANGLE(Context *context,
+ GLuint shader,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetShaderivBase(context, shader, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
+{
+ return ValidateGetTexParameterBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetTexParameterfvRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetTexParameterBase(context, target, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
+{
+ return ValidateGetTexParameterBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetTexParameterivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetTexParameterBase(context, target, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
+{
+ return ValidateTexParameterBase(context, target, pname, -1, &param);
+}
+
+bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
+{
+ return ValidateTexParameterBase(context, target, pname, -1, params);
+}
+
+bool ValidateTexParameterfvRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateTexParameterBase(context, target, pname, bufSize, params);
+}
+
+bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
+{
+ return ValidateTexParameterBase(context, target, pname, -1, &param);
+}
+
+bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
+{
+ return ValidateTexParameterBase(context, target, pname, -1, params);
+}
+
+bool ValidateTexParameterivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateTexParameterBase(context, target, pname, bufSize, params);
+}
+
+bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
+{
+ return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
+}
+
+bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLuint bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
+{
+ return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
+}
+
+bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLuint bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
+{
+ return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
+}
+
+bool ValidateSamplerParameterfv(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
+}
+
+bool ValidateSamplerParameterfvRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
+}
+
+bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
+{
+ return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
+}
+
+bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
+{
+ return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
+}
+
+bool ValidateSamplerParameterivRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
+}
+
+bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
+{
+ return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
+}
+
+bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
+{
+ return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
+}
+
+bool ValidateGetVertexAttribivRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
+{
+ return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
+}
+
+bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **pointer)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
+{
+ return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
+}
+
+bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
+{
+ return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
+}
+
+bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveUniformBlockiv(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params)
+{
+ return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
+}
+
+bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetInternalFormativ(Context *context,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLint *params)
+{
+ return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
+ nullptr);
+}
+
+bool ValidateGetInternalFormativRobustANGLE(Context *context,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/validationES.h b/gfx/angle/src/libANGLE/validationES.h
new file mode 100755
index 000000000..06da37690
--- /dev/null
+++ b/gfx/angle/src/libANGLE/validationES.h
@@ -0,0 +1,561 @@
+//
+// Copyright (c) 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/mathutil.h"
+
+#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
+#include <GLES3/gl31.h>
+
+namespace egl
+{
+class Display;
+class Image;
+}
+
+namespace gl
+{
+class Context;
+struct Format;
+class Program;
+class Shader;
+class ValidationContext;
+
+bool ValidTextureTarget(const ValidationContext *context, GLenum target);
+bool ValidTexture2DTarget(const ValidationContext *context, GLenum target);
+bool ValidTexture3DTarget(const ValidationContext *context, GLenum target);
+bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target);
+bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target);
+bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target);
+bool ValidFramebufferTarget(GLenum target);
+bool ValidBufferTarget(const ValidationContext *context, GLenum target);
+bool ValidBufferParameter(const ValidationContext *context, GLenum pname, GLsizei *numParams);
+bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level);
+bool ValidImageSizeParameters(const Context *context,
+ GLenum target,
+ GLint level,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ bool isSubImage);
+bool ValidCompressedImageSize(const ValidationContext *context,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height);
+bool ValidImageDataSize(ValidationContext *context,
+ GLenum textureTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum internalFormat,
+ GLenum type,
+ const GLvoid *pixels,
+ GLsizei imageSize);
+
+bool ValidQueryType(const Context *context, GLenum queryType);
+
+// 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(ValidationContext *context, GLuint 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(ValidationContext *context, GLuint id);
+
+bool ValidateAttachmentTarget(Context *context, GLenum attachment);
+bool ValidateRenderbufferStorageParametersBase(Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height);
+bool ValidateRenderbufferStorageParametersANGLE(Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height);
+
+bool ValidateFramebufferRenderbufferParameters(Context *context, GLenum target, GLenum attachment,
+ GLenum renderbuffertarget, GLuint renderbuffer);
+
+bool ValidateBlitFramebufferParameters(ValidationContext *context,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+
+bool ValidateReadPixels(ValidationContext *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLvoid *pixels);
+bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLvoid *pixels);
+bool ValidateReadnPixelsEXT(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLvoid *pixels);
+bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLvoid *data);
+
+bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n);
+bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n);
+bool ValidateBeginQueryBase(Context *context, GLenum target, GLuint id);
+bool ValidateBeginQueryEXT(Context *context, GLenum target, GLuint id);
+bool ValidateEndQueryBase(Context *context, GLenum target);
+bool ValidateEndQueryEXT(Context *context, GLenum target);
+bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target);
+bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams);
+bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params);
+bool ValidateGetQueryivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+bool ValidateGetQueryObjectValueBase(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei *numParams);
+bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params);
+bool ValidateGetQueryObjectivRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params);
+bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params);
+bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params);
+bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params);
+bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint64 *params);
+
+bool ValidateUniform(Context *context, GLenum uniformType, GLint location, GLsizei count);
+bool ValidateUniformMatrix(Context *context, GLenum matrixType, GLint location, GLsizei count,
+ GLboolean transpose);
+
+bool ValidateStateQuery(ValidationContext *context,
+ GLenum pname,
+ GLenum *nativeType,
+ unsigned int *numParams);
+
+bool ValidateRobustStateQuery(ValidationContext *context,
+ GLenum pname,
+ GLsizei bufSize,
+ GLenum *nativeType,
+ unsigned int *numParams);
+
+bool ValidateCopyTexImageParametersBase(ValidationContext *context,
+ GLenum 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);
+
+bool ValidateDrawArrays(ValidationContext *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+
+bool ValidateDrawElements(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei primcount,
+ IndexRange *indexRangeOut);
+
+bool ValidateDrawElementsInstanced(Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei primcount,
+ IndexRange *indexRangeOut);
+bool ValidateDrawElementsInstancedANGLE(Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei primcount,
+ IndexRange *indexRangeOut);
+
+bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
+ GLuint texture, GLint level);
+bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level);
+bool ValidateFramebufferRenderbuffer(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer);
+
+bool ValidateGetUniformBase(Context *context, GLuint program, GLint location);
+bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params);
+bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params);
+bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params);
+bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params);
+bool ValidateGetUniformfvRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+bool ValidateGetUniformivRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+bool ValidateGetUniformuivRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+
+bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
+ const GLenum *attachments, bool defaultFramebuffer);
+
+bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker);
+bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker);
+
+bool ValidateEGLImageTargetTexture2DOES(Context *context,
+ egl::Display *display,
+ GLenum target,
+ egl::Image *image);
+bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
+ egl::Display *display,
+ GLenum target,
+ egl::Image *image);
+
+bool ValidateBindVertexArrayBase(Context *context, GLuint array);
+
+bool ValidateLinkProgram(Context *context, GLuint program);
+bool ValidateProgramBinaryBase(Context *context,
+ GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length);
+bool ValidateGetProgramBinaryBase(Context *context,
+ GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary);
+bool ValidateUseProgram(Context *context, GLuint program);
+
+bool ValidateCopyTexImage2D(ValidationContext *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border);
+bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs);
+bool ValidateCopyTexSubImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+
+bool ValidateGetBufferPointervBase(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei *length,
+ void **params);
+bool ValidateUnmapBufferBase(Context *context, GLenum target);
+bool ValidateMapBufferRangeBase(Context *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+bool ValidateFlushMappedBufferRangeBase(Context *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr length);
+
+bool ValidateGenerateMipmap(Context *context, GLenum target);
+
+bool ValidateGenBuffers(Context *context, GLint n, GLuint *buffers);
+bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *buffers);
+bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *framebuffers);
+bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *framebuffers);
+bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *renderbuffers);
+bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *renderbuffers);
+bool ValidateGenTextures(Context *context, GLint n, GLuint *textures);
+bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *textures);
+
+bool ValidateGenOrDelete(Context *context, GLint n);
+
+bool ValidateEnable(Context *context, GLenum cap);
+bool ValidateDisable(Context *context, GLenum cap);
+bool ValidateIsEnabled(Context *context, GLenum cap);
+
+bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize);
+bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams);
+
+bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei *numParams);
+bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams);
+
+bool ValidateGetBufferParameteriv(ValidationContext *context,
+ GLenum target,
+ GLenum pname,
+ GLint *params);
+bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetBufferParameteri64v(ValidationContext *context,
+ GLenum target,
+ GLenum pname,
+ GLint64 *params);
+bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params);
+
+bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams);
+bool ValidateGetProgramivRobustANGLE(Context *context,
+ GLuint program,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams);
+
+bool ValidateGetRenderbufferParameteriv(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLint *params);
+bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params);
+bool ValidateGetShaderivRobustANGLE(Context *context,
+ GLuint shader,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params);
+bool ValidateGetTexParameterfvRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params);
+bool ValidateGetTexParameterivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param);
+bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params);
+bool ValidateTexParameterfvRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params);
+bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param);
+bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params);
+bool ValidateTexParameterivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params);
+
+bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params);
+bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLuint bufSize,
+ GLsizei *length,
+ GLfloat *params);
+bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params);
+bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLuint bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param);
+bool ValidateSamplerParameterfv(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateSamplerParameterfvRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params);
+bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param);
+bool ValidateSamplerParameteriv(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ const GLint *params);
+bool ValidateSamplerParameterivRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params);
+
+bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params);
+bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+
+bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params);
+bool ValidateGetVertexAttribivRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer);
+bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **pointer);
+
+bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params);
+bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params);
+bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+
+bool ValidateGetActiveUniformBlockiv(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params);
+bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetInternalFormativ(Context *context,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLint *params);
+bool ValidateGetInternalFormativRobustANGLE(Context *context,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+// Error messages shared here for use in testing.
+extern const char *g_ExceedsMaxElementErrorMessage;
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES_H_
diff --git a/gfx/angle/src/libANGLE/validationES2.cpp b/gfx/angle/src/libANGLE/validationES2.cpp
new file mode 100755
index 000000000..3133102f3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/validationES2.cpp
@@ -0,0 +1,3867 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
+
+#include "libANGLE/validationES2.h"
+
+#include <cstdint>
+
+#include "common/mathutil.h"
+#include "common/string_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES3.h"
+
+namespace gl
+{
+
+namespace
+{
+
+bool IsPartialBlit(gl::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->getGLState().isScissorTestEnabled())
+ {
+ const Rectangle &scissor = context->getGLState().getScissor();
+ return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
+ scissor.height < writeSize.height;
+ }
+
+ return false;
+}
+
+template <typename T>
+bool ValidatePathInstances(gl::Context *context,
+ GLsizei numPaths,
+ const void *paths,
+ GLuint pathBase)
+{
+ const auto *array = static_cast<const T *>(paths);
+
+ for (GLsizei i = 0; i < numPaths; ++i)
+ {
+ const GLuint pathName = array[i] + pathBase;
+ if (context->hasPath(pathName) && !context->hasPathData(pathName))
+ {
+ context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateInstancedPathParameters(gl::Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+
+ if (paths == nullptr)
+ {
+ context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
+ return false;
+ }
+
+ if (numPaths < 0)
+ {
+ context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
+ return false;
+ }
+
+ if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
+ {
+ context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
+ return false;
+ }
+
+ std::uint32_t pathNameTypeSize = 0;
+ std::uint32_t componentCount = 0;
+
+ switch (pathNameType)
+ {
+ case GL_UNSIGNED_BYTE:
+ pathNameTypeSize = sizeof(GLubyte);
+ if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
+ return false;
+ break;
+
+ case GL_BYTE:
+ pathNameTypeSize = sizeof(GLbyte);
+ if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
+ return false;
+ break;
+
+ case GL_UNSIGNED_SHORT:
+ pathNameTypeSize = sizeof(GLushort);
+ if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
+ return false;
+ break;
+
+ case GL_SHORT:
+ pathNameTypeSize = sizeof(GLshort);
+ if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
+ return false;
+ break;
+
+ case GL_UNSIGNED_INT:
+ pathNameTypeSize = sizeof(GLuint);
+ if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
+ return false;
+ break;
+
+ case GL_INT:
+ pathNameTypeSize = sizeof(GLint);
+ if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
+ return false;
+ break;
+
+ default:
+ context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
+ return false;
+ }
+
+ switch (transformType)
+ {
+ case GL_NONE:
+ componentCount = 0;
+ break;
+ case GL_TRANSLATE_X_CHROMIUM:
+ case GL_TRANSLATE_Y_CHROMIUM:
+ componentCount = 1;
+ break;
+ case GL_TRANSLATE_2D_CHROMIUM:
+ componentCount = 2;
+ break;
+ case GL_TRANSLATE_3D_CHROMIUM:
+ componentCount = 3;
+ break;
+ case GL_AFFINE_2D_CHROMIUM:
+ case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
+ componentCount = 6;
+ break;
+ case GL_AFFINE_3D_CHROMIUM:
+ case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
+ componentCount = 12;
+ break;
+ default:
+ context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
+ return false;
+ }
+ if (componentCount != 0 && transformValues == nullptr)
+ {
+ context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
+ return false;
+ }
+
+ angle::CheckedNumeric<std::uint32_t> checkedSize(0);
+ checkedSize += (numPaths * pathNameTypeSize);
+ checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
+ if (!checkedSize.IsValid())
+ {
+ context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
+ return false;
+ }
+
+ return true;
+}
+
+bool IsValidCopyTextureFormat(Context *context, GLenum internalFormat)
+{
+ const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat);
+ switch (internalFormatInfo.format)
+ {
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGB:
+ case GL_RGBA:
+ return true;
+
+ case GL_RED:
+ return context->getClientMajorVersion() >= 3 || context->getExtensions().textureRG;
+
+ case GL_BGRA_EXT:
+ return context->getExtensions().textureFormatBGRA8888;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
+{
+ switch (internalFormat)
+ {
+ case GL_RGB:
+ case GL_RGBA:
+ break;
+
+ case GL_BGRA_EXT:
+ return context->getExtensions().textureFormatBGRA8888;
+
+ default:
+ return false;
+ }
+
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool IsValidCopyTextureDestinationTarget(Context *context, GLenum target)
+{
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ return true;
+
+ // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
+ // supported
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
+{
+ if (IsValidCopyTextureDestinationTarget(context, target))
+ {
+ return true;
+ }
+
+ // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
+ // supported
+
+ return false;
+}
+
+} // anonymous namespace
+
+bool ValidateES2TexImageParameters(Context *context,
+ GLenum 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 GLvoid *pixels)
+{
+ if (!ValidTexture2DDestinationTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (level < 0 || xoffset < 0 ||
+ std::numeric_limits<GLsizei>::max() - xoffset < width ||
+ std::numeric_limits<GLsizei>::max() - yoffset < height)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (!isSubImage && !isCompressed && internalformat != format)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+
+ if (target == GL_TEXTURE_2D)
+ {
+ if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ else if (IsCubeMapTextureTarget(target))
+ {
+ if (!isSubImage && width != height)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ if (!texture)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (isSubImage)
+ {
+ GLenum textureFormat = texture->getFormat(target, level).asSized();
+ if (textureFormat == GL_NONE)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
+ return false;
+ }
+
+ if (format != GL_NONE)
+ {
+ if (gl::GetSizedInternalFormat(format, type) != textureFormat)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
+ static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ else
+ {
+ if (texture->getImmutableFormat())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ // Verify zero border
+ if (border != 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (isCompressed)
+ {
+ GLenum actualInternalFormat =
+ isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
+ switch (actualInternalFormat)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (!context->getExtensions().textureCompressionDXT1)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (!context->getExtensions().textureCompressionDXT1)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (!context->getExtensions().textureCompressionDXT5)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_OES:
+ if (!context->getExtensions().compressedETC1RGB8Texture)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ if (!context->getExtensions().lossyETCDecode)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
+ return false;
+ }
+ break;
+ default:
+ context->handleError(Error(
+ GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
+ return false;
+ }
+ if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ 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->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ case GL_RED:
+ case GL_RG:
+ if (!context->getExtensions().textureRG)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ case GL_SRGB_EXT:
+ case GL_SRGB_ALPHA_EXT:
+ if (!context->getExtensions().sRGB)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ break;
+ case GL_DEPTH_COMPONENT:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_INT:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ case GL_DEPTH_STENCIL_OES:
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_24_8_OES:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ switch (format)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (context->getExtensions().textureCompressionDXT1)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (context->getExtensions().textureCompressionDXT3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (context->getExtensions().textureCompressionDXT5)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_OES:
+ if (context->getExtensions().compressedETC1RGB8Texture)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ if (context->getExtensions().lossyETCDecode)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION,
+ "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
+ return false;
+ }
+ else
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
+ return false;
+ }
+ break;
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL_OES:
+ if (!context->getExtensions().depthTextures)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ if (target != GL_TEXTURE_2D)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ // OES_depth_texture supports loading depth data and multiple levels,
+ // but ANGLE_depth_texture does not
+ if (pixels != NULL || level != 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (type == GL_FLOAT)
+ {
+ if (!context->getExtensions().textureFloat)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ }
+ else if (type == GL_HALF_FLOAT_OES)
+ {
+ if (!context->getExtensions().textureHalfFloat)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ }
+ }
+
+ if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
+ imageSize))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateES2CopyTexImageParameters(ValidationContext *context,
+ GLenum 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->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
+ return false;
+ }
+
+ Format textureFormat = Format::Invalid();
+ if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
+ xoffset, yoffset, 0, x, y, width, height, border,
+ &textureFormat))
+ {
+ return false;
+ }
+
+ const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
+ GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
+ const auto &formatInfo = *textureFormat.info;
+
+ // [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)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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_BGRA8_EXT &&
+ colorbufferFormat != GL_R32F &&
+ colorbufferFormat != GL_RG32F &&
+ colorbufferFormat != GL_RGB32F &&
+ colorbufferFormat != GL_RGBA32F)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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_BGRA8_EXT &&
+ colorbufferFormat != GL_RG32F &&
+ colorbufferFormat != GL_RGB32F &&
+ colorbufferFormat != GL_RGBA32F)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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_BGRA8_EXT &&
+ colorbufferFormat != GL_RGB32F &&
+ colorbufferFormat != GL_RGBA32F)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ if (colorbufferFormat != GL_RGBA4 &&
+ colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_RGBA32F)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ 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_ETC1_RGB8_OES:
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL_OES:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ default:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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_BGRA8_EXT &&
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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_BGRA8_EXT &&
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (context->getExtensions().textureCompressionDXT1)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (context->getExtensions().textureCompressionDXT3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (context->getExtensions().textureCompressionDXT5)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_OES:
+ if (context->getExtensions().compressedETC1RGB8Texture)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ if (context->getExtensions().lossyETCDecode)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
+ return false;
+ }
+ else
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
+ return false;
+ }
+ break;
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT32_OES:
+ case GL_DEPTH_STENCIL_OES:
+ case GL_DEPTH24_STENCIL8_OES:
+ if (context->getExtensions().depthTextures)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ 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 ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
+ GLsizei width, GLsizei height)
+{
+ if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (width < 1 || height < 1 || levels < 1)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (target == GL_TEXTURE_CUBE_MAP && width != height)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+ if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+ static_cast<GLuint>(height) > caps.max2DTextureSize)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
+ static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (levels != 1 && !context->getExtensions().textureNPOT)
+ {
+ if (!gl::isPow2(width) || !gl::isPow2(height))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ switch (internalformat)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (!context->getExtensions().textureCompressionDXT1)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (!context->getExtensions().textureCompressionDXT3)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (!context->getExtensions().textureCompressionDXT5)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_OES:
+ if (!context->getExtensions().compressedETC1RGB8Texture)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ if (!context->getExtensions().lossyETCDecode)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
+ return false;
+ }
+ break;
+ case GL_RGBA32F_EXT:
+ case GL_RGB32F_EXT:
+ case GL_ALPHA32F_EXT:
+ case GL_LUMINANCE32F_EXT:
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ if (!context->getExtensions().textureFloat)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_RGBA16F_EXT:
+ case GL_RGB16F_EXT:
+ case GL_ALPHA16F_EXT:
+ case GL_LUMINANCE16F_EXT:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ if (!context->getExtensions().textureHalfFloat)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_R8_EXT:
+ case GL_RG8_EXT:
+ case GL_R16F_EXT:
+ case GL_RG16F_EXT:
+ case GL_R32F_EXT:
+ case GL_RG32F_EXT:
+ if (!context->getExtensions().textureRG)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT32_OES:
+ case GL_DEPTH24_STENCIL8_OES:
+ if (!context->getExtensions().depthTextures)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ if (target != GL_TEXTURE_2D)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ // ANGLE_depth_texture only supports 1-level textures
+ if (levels != 1)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ gl::Texture *texture = context->getTargetTexture(target);
+ if (!texture || texture->id() == 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (texture->getImmutableFormat())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ if (!context->getExtensions().discardFramebuffer)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ bool defaultFramebuffer = false;
+
+ switch (target)
+ {
+ case GL_FRAMEBUFFER:
+ defaultFramebuffer =
+ (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
+ return false;
+ }
+
+ return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
+}
+
+bool ValidateBindVertexArrayOES(Context *context, GLuint array)
+{
+ if (!context->getExtensions().vertexArrayObject)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateBindVertexArrayBase(context, array);
+}
+
+bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
+{
+ if (!context->getExtensions().vertexArrayObject)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
+{
+ if (!context->getExtensions().vertexArrayObject)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateIsVertexArrayOES(Context *context)
+{
+ if (!context->getExtensions().vertexArrayObject)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramBinaryOES(Context *context,
+ GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length)
+{
+ if (!context->getExtensions().getProgramBinary)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
+}
+
+bool ValidateGetProgramBinaryOES(Context *context,
+ GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary)
+{
+ if (!context->getExtensions().getProgramBinary)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateGetProgramBinaryBase(context, 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(Context *context,
+ GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
+ return false;
+ }
+
+ if (!ValidDebugType(type) && type != GL_DONT_CARE)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
+ return false;
+ }
+
+ if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
+ return false;
+ }
+
+ if (count > 0)
+ {
+ if (source == GL_DONT_CARE || type == GL_DONT_CARE)
+ {
+ context->handleError(Error(
+ GL_INVALID_OPERATION,
+ "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
+ return false;
+ }
+
+ if (severity != GL_DONT_CARE)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION,
+ "If count is greater than zero, severity must be GL_DONT_CARE."));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateDebugMessageInsertKHR(Context *context,
+ GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (!context->getGLState().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->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
+ return false;
+ }
+
+ if (!ValidDebugType(type))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
+ return false;
+ }
+
+ if (!ValidDebugSource(source, true))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
+ return false;
+ }
+
+ size_t messageLength = (length < 0) ? strlen(buf) : length;
+ if (messageLength > context->getExtensions().maxDebugMessageLength)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDebugMessageCallbackKHR(Context *context,
+ GLDEBUGPROCKHR callback,
+ const void *userParam)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetDebugMessageLogKHR(Context *context,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (bufSize < 0 && messageLog != nullptr)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePushDebugGroupKHR(Context *context,
+ GLenum source,
+ GLuint id,
+ GLsizei length,
+ const GLchar *message)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (!ValidDebugSource(source, true))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
+ return false;
+ }
+
+ size_t messageLength = (length < 0) ? strlen(message) : length;
+ if (messageLength > context->getExtensions().maxDebugMessageLength)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
+ return false;
+ }
+
+ size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
+ if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
+ {
+ context->handleError(
+ Error(GL_STACK_OVERFLOW,
+ "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePopDebugGroupKHR(Context *context)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
+ if (currentStackSize <= 1)
+ {
+ context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
+{
+ switch (identifier)
+ {
+ case GL_BUFFER:
+ if (context->getBuffer(name) == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
+ return false;
+ }
+ return true;
+
+ case GL_SHADER:
+ if (context->getShader(name) == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
+ return false;
+ }
+ return true;
+
+ case GL_PROGRAM:
+ if (context->getProgram(name) == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
+ return false;
+ }
+ return true;
+
+ case GL_VERTEX_ARRAY:
+ if (context->getVertexArray(name) == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
+ return false;
+ }
+ return true;
+
+ case GL_QUERY:
+ if (context->getQuery(name) == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
+ return false;
+ }
+ return true;
+
+ case GL_TRANSFORM_FEEDBACK:
+ if (context->getTransformFeedback(name) == nullptr)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
+ return false;
+ }
+ return true;
+
+ case GL_SAMPLER:
+ if (context->getSampler(name) == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
+ return false;
+ }
+ return true;
+
+ case GL_TEXTURE:
+ if (context->getTexture(name) == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
+ return false;
+ }
+ return true;
+
+ case GL_RENDERBUFFER:
+ if (context->getRenderbuffer(name) == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
+ return false;
+ }
+ return true;
+
+ case GL_FRAMEBUFFER:
+ if (context->getFramebuffer(name) == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
+ return false;
+ }
+ return true;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
+ return false;
+ }
+}
+
+static bool ValidateLabelLength(Context *context, 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->getExtensions().maxLabelLength)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateObjectLabelKHR(Context *context,
+ GLenum identifier,
+ GLuint name,
+ GLsizei length,
+ const GLchar *label)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (!ValidateObjectIdentifierAndName(context, identifier, name))
+ {
+ return false;
+ }
+
+ if (!ValidateLabelLength(context, length, label))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetObjectLabelKHR(Context *context,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+ return false;
+ }
+
+ if (!ValidateObjectIdentifierAndName(context, identifier, name))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidateObjectPtrName(Context *context, const void *ptr)
+{
+ if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateObjectPtrLabelKHR(Context *context,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (!ValidateObjectPtrName(context, ptr))
+ {
+ return false;
+ }
+
+ if (!ValidateLabelLength(context, length, label))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetObjectPtrLabelKHR(Context *context,
+ const void *ptr,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+ return false;
+ }
+
+ if (!ValidateObjectPtrName(context, ptr))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ // TODO: represent this in Context::getQueryParameterInfo.
+ switch (pname)
+ {
+ case GL_DEBUG_CALLBACK_FUNCTION:
+ case GL_DEBUG_CALLBACK_USER_PARAM:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlitFramebufferANGLE(Context *context,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
+{
+ if (!context->getExtensions().framebufferBlit)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
+ return false;
+ }
+
+ if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
+ {
+ // TODO(jmadill): Determine if this should be available on other implementations.
+ context->handleError(Error(
+ GL_INVALID_OPERATION,
+ "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
+ return false;
+ }
+
+ if (filter == GL_LINEAR)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
+ return false;
+ }
+
+ Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
+ Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
+
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
+ const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
+
+ if (readColorAttachment && drawColorAttachment)
+ {
+ if (!(readColorAttachment->type() == GL_TEXTURE &&
+ readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
+ readColorAttachment->type() != GL_RENDERBUFFER &&
+ readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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().type == GL_TEXTURE_2D) &&
+ attachment->type() != GL_RENDERBUFFER &&
+ attachment->type() != GL_FRAMEBUFFER_DEFAULT)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Return an error if the destination formats do not match
+ if (!Format::SameSized(attachment->getFormat(),
+ readColorAttachment->getFormat()))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+
+ if (readFramebuffer->getSamples(context->getContextState()) != 0 &&
+ IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
+ srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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(attachments[i]);
+ const FramebufferAttachment *drawBuffer =
+ drawFramebuffer->getAttachment(attachments[i]);
+
+ if (readBuffer && drawBuffer)
+ {
+ if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1))
+ {
+ // only whole-buffer copies are permitted
+ ERR(
+ "Only whole-buffer depth and stencil blits are supported by this "
+ "implementation.");
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+ }
+
+ return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
+ dstX1, dstY1, mask, filter);
+}
+
+bool ValidateClear(ValidationContext *context, GLbitfield mask)
+{
+ auto fbo = context->getGLState().getDrawFramebuffer();
+ if (fbo->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
+{
+ if (!context->getExtensions().drawBuffers)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
+ return false;
+ }
+
+ return ValidateDrawBuffersBase(context, n, bufs);
+}
+
+bool ValidateTexImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
+ 0, 0, width, height, border, format, type, -1, pixels);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
+ 0, 0, width, height, 1, border, format, type, -1,
+ pixels);
+}
+
+bool ValidateTexImage2DRobust(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLvoid *pixels)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
+ 0, 0, width, height, border, format, type, bufSize,
+ pixels);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
+ 0, 0, width, height, 1, border, format, type, bufSize,
+ pixels);
+}
+
+bool ValidateTexSubImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels)
+{
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
+ yoffset, width, height, 0, format, type, -1, pixels);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
+ yoffset, 0, width, height, 1, 0, format, type, -1,
+ pixels);
+}
+
+bool ValidateTexSubImage2DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLvoid *pixels)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
+ yoffset, width, height, 0, format, type, bufSize,
+ pixels);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
+ yoffset, 0, width, height, 1, 0, format, type, bufSize,
+ pixels);
+}
+
+bool ValidateCompressedTexImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const GLvoid *data)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ if (!ValidateES2TexImageParameters(context, 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, target, level, internalformat, true, false, 0,
+ 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
+ data))
+ {
+ return false;
+ }
+ }
+
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
+ auto blockSizeOrErr =
+ formatInfo.computeCompressedImageSize(gl::Extents(width, height, 1));
+ if (blockSizeOrErr.isError())
+ {
+ context->handleError(blockSizeOrErr.getError());
+ return false;
+ }
+
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCompressedTexSubImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const GLvoid *data)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
+ yoffset, width, height, 0, GL_NONE, GL_NONE, -1, data))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ ASSERT(context->getClientMajorVersion() >= 3);
+ if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
+ yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, -1,
+ data))
+ {
+ return false;
+ }
+ }
+
+ const InternalFormat &formatInfo = GetInternalFormatInfo(format);
+ auto blockSizeOrErr =
+ formatInfo.computeCompressedImageSize(gl::Extents(width, height, 1));
+ if (blockSizeOrErr.isError())
+ {
+ context->handleError(blockSizeOrErr.getError());
+ return false;
+ }
+
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
+{
+ return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
+}
+
+bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
+{
+ if (!context->getExtensions().mapBuffer)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
+ return false;
+ }
+
+ if (!ValidBufferTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
+ return false;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+ if (buffer == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
+ return false;
+ }
+
+ if (access != GL_WRITE_ONLY_OES)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
+ return false;
+ }
+
+ if (buffer->isMapped())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateUnmapBufferOES(Context *context, GLenum target)
+{
+ if (!context->getExtensions().mapBuffer)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
+ return false;
+ }
+
+ return ValidateUnmapBufferBase(context, target);
+}
+
+bool ValidateMapBufferRangeEXT(Context *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ if (!context->getExtensions().mapBufferRange)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
+ return false;
+ }
+
+ return ValidateMapBufferRangeBase(context, target, offset, length, access);
+}
+
+bool ValidateFlushMappedBufferRangeEXT(Context *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr length)
+{
+ if (!context->getExtensions().mapBufferRange)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
+ return false;
+ }
+
+ return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
+}
+
+bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
+{
+ Texture *textureObject = context->getTexture(texture);
+ if (textureObject && textureObject->getTarget() != target && texture != 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
+ return false;
+ }
+
+ if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+ !context->isTextureGenerated(texture))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_CUBE_MAP:
+ break;
+
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
+ return false;
+ }
+ break;
+ case GL_TEXTURE_EXTERNAL_OES:
+ if (!context->getExtensions().eglImageExternal &&
+ !context->getExtensions().eglStreamConsumerExternal)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "External texture extension not enabled"));
+ return false;
+ }
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindUniformLocationCHROMIUM(Context *context,
+ GLuint program,
+ GLint location,
+ const GLchar *name)
+{
+ if (!context->getExtensions().bindUniformLocation)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (location < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (static_cast<size_t>(location) >=
+ (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
+ {
+ context->handleError(Error(GL_INVALID_VALUE,
+ "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
+ "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
+ return false;
+ }
+
+ if (strncmp(name, "gl_", 3) == 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
+{
+ if (!context->getExtensions().framebufferMixedSamples)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
+ return false;
+ }
+ switch (components)
+ {
+ case GL_RGB:
+ case GL_RGBA:
+ case GL_ALPHA:
+ case GL_NONE:
+ break;
+ default:
+ context->handleError(
+ Error(GL_INVALID_ENUM,
+ "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
+ return false;
+ }
+
+ return true;
+}
+
+// CHROMIUM_path_rendering
+
+bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+ if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
+ return false;
+ }
+ if (matrix == nullptr)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
+ return false;
+ }
+ return true;
+}
+
+bool ValidateMatrixMode(Context *context, GLenum matrixMode)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+ if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGenPaths(Context *context, GLsizei range)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+
+ // range = 0 is undefined in NV_path_rendering.
+ // we add stricter semantic check here and require a non zero positive range.
+ if (range <= 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
+ return false;
+ }
+
+ if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+
+ // range = 0 is undefined in NV_path_rendering.
+ // we add stricter semantic check here and require a non zero positive range.
+ if (range <= 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
+ return false;
+ }
+
+ angle::CheckedNumeric<std::uint32_t> checkedRange(path);
+ checkedRange += range;
+
+ if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
+ return false;
+ }
+ return true;
+}
+
+bool ValidatePathCommands(Context *context,
+ GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+ if (!context->hasPath(path))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
+ return false;
+ }
+
+ if (numCommands < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
+ return false;
+ }
+ else if (numCommands > 0)
+ {
+ if (!commands)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
+ return false;
+ }
+ }
+
+ if (numCoords < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
+ return false;
+ }
+ else if (numCoords > 0)
+ {
+ if (!coords)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
+ return false;
+ }
+ }
+
+ std::uint32_t coordTypeSize = 0;
+ switch (coordType)
+ {
+ case GL_BYTE:
+ coordTypeSize = sizeof(GLbyte);
+ break;
+
+ case GL_UNSIGNED_BYTE:
+ coordTypeSize = sizeof(GLubyte);
+ break;
+
+ case GL_SHORT:
+ coordTypeSize = sizeof(GLshort);
+ break;
+
+ case GL_UNSIGNED_SHORT:
+ coordTypeSize = sizeof(GLushort);
+ break;
+
+ case GL_FLOAT:
+ coordTypeSize = sizeof(GLfloat);
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
+ return false;
+ }
+
+ angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
+ checkedSize += (coordTypeSize * numCoords);
+ if (!checkedSize.IsValid())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
+ return false;
+ }
+
+ // early return skips command data validation when it doesn't exist.
+ if (!commands)
+ return true;
+
+ GLsizei expectedNumCoords = 0;
+ for (GLsizei i = 0; i < numCommands; ++i)
+ {
+ switch (commands[i])
+ {
+ case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
+ break;
+ case GL_MOVE_TO_CHROMIUM:
+ case GL_LINE_TO_CHROMIUM:
+ expectedNumCoords += 2;
+ break;
+ case GL_QUADRATIC_CURVE_TO_CHROMIUM:
+ expectedNumCoords += 4;
+ break;
+ case GL_CUBIC_CURVE_TO_CHROMIUM:
+ expectedNumCoords += 6;
+ break;
+ case GL_CONIC_CURVE_TO_CHROMIUM:
+ expectedNumCoords += 5;
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
+ return false;
+ }
+ }
+ if (expectedNumCoords != numCoords)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+ if (!context->hasPath(path))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_PATH_STROKE_WIDTH_CHROMIUM:
+ if (value < 0.0f)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
+ return false;
+ }
+ break;
+ case GL_PATH_END_CAPS_CHROMIUM:
+ switch (static_cast<GLenum>(value))
+ {
+ case GL_FLAT_CHROMIUM:
+ case GL_SQUARE_CHROMIUM:
+ case GL_ROUND_CHROMIUM:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
+ return false;
+ }
+ break;
+ case GL_PATH_JOIN_STYLE_CHROMIUM:
+ switch (static_cast<GLenum>(value))
+ {
+ case GL_MITER_REVERT_CHROMIUM:
+ case GL_BEVEL_CHROMIUM:
+ case GL_ROUND_CHROMIUM:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
+ return false;
+ }
+ case GL_PATH_MITER_LIMIT_CHROMIUM:
+ if (value < 0.0f)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
+ return false;
+ }
+ break;
+
+ case GL_PATH_STROKE_BOUND_CHROMIUM:
+ // no errors, only clamping.
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+
+ if (!context->hasPath(path))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
+ return false;
+ }
+ if (!value)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "No value array."));
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_PATH_STROKE_WIDTH_CHROMIUM:
+ case GL_PATH_END_CAPS_CHROMIUM:
+ case GL_PATH_JOIN_STYLE_CHROMIUM:
+ case GL_PATH_MITER_LIMIT_CHROMIUM:
+ case GL_PATH_STROKE_BOUND_CHROMIUM:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+
+ 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:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
+ return false;
+ }
+
+ return true;
+}
+
+// Note that the spec specifies that for the path drawing commands
+// if the path object is not an existing path object the command
+// does nothing and no error is generated.
+// However if the path object exists but has not been specified any
+// commands then an error is generated.
+
+bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+ if (context->hasPath(path) && !context->hasPathData(path))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
+ return false;
+ }
+
+ switch (fillMode)
+ {
+ case GL_COUNT_UP_CHROMIUM:
+ case GL_COUNT_DOWN_CHROMIUM:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
+ return false;
+ }
+
+ if (!isPow2(mask + 1))
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+ if (context->hasPath(path) && !context->hasPathData(path))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+ if (context->hasPath(path) && !context->hasPathData(path))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
+ return false;
+ }
+
+ switch (coverMode)
+ {
+ case GL_CONVEX_HULL_CHROMIUM:
+ case GL_BOUNDING_BOX_CHROMIUM:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
+ return false;
+ }
+ return true;
+}
+
+bool ValidateStencilThenCoverFillPath(Context *context,
+ GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode)
+{
+ return ValidateStencilFillPath(context, path, fillMode, mask) &&
+ ValidateCoverPath(context, path, coverMode);
+}
+
+bool ValidateStencilThenCoverStrokePath(Context *context,
+ GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode)
+{
+ return ValidateStencilStrokePath(context, path, reference, mask) &&
+ ValidateCoverPath(context, path, coverMode);
+}
+
+bool ValidateIsPath(Context *context)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+ return true;
+}
+
+bool ValidateCoverFillPathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+ transformType, transformValues))
+ return false;
+
+ switch (coverMode)
+ {
+ case GL_CONVEX_HULL_CHROMIUM:
+ case GL_BOUNDING_BOX_CHROMIUM:
+ case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCoverStrokePathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+ transformType, transformValues))
+ return false;
+
+ switch (coverMode)
+ {
+ case GL_CONVEX_HULL_CHROMIUM:
+ case GL_BOUNDING_BOX_CHROMIUM:
+ case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilFillPathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+
+ if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+ transformType, transformValues))
+ return false;
+
+ switch (fillMode)
+ {
+ case GL_COUNT_UP_CHROMIUM:
+ case GL_COUNT_DOWN_CHROMIUM:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
+ return false;
+ }
+ if (!isPow2(mask + 1))
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
+ return false;
+ }
+ return true;
+}
+
+bool ValidateStencilStrokePathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+ transformType, transformValues))
+ return false;
+
+ // no more validation here.
+
+ return true;
+}
+
+bool ValidateStencilThenCoverFillPathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+ transformType, transformValues))
+ return false;
+
+ switch (coverMode)
+ {
+ case GL_CONVEX_HULL_CHROMIUM:
+ case GL_BOUNDING_BOX_CHROMIUM:
+ case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
+ return false;
+ }
+
+ switch (fillMode)
+ {
+ case GL_COUNT_UP_CHROMIUM:
+ case GL_COUNT_DOWN_CHROMIUM:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
+ return false;
+ }
+ if (!isPow2(mask + 1))
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+ transformType, transformValues))
+ return false;
+
+ switch (coverMode)
+ {
+ case GL_CONVEX_HULL_CHROMIUM:
+ case GL_BOUNDING_BOX_CHROMIUM:
+ case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindFragmentInputLocation(Context *context,
+ GLuint program,
+ GLint location,
+ const GLchar *name)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+
+ const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
+ if (location >= MaxLocation)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
+ return false;
+ }
+
+ const auto *programObject = context->getProgram(program);
+ if (!programObject)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
+ return false;
+ }
+
+ if (!name)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "No name given."));
+ return false;
+ }
+
+ if (angle::BeginsWith(name, "gl_"))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramPathFragmentInputGen(Context *context,
+ GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
+ return false;
+ }
+
+ const auto *programObject = context->getProgram(program);
+ if (!programObject || programObject->isFlaggedForDeletion())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
+ return false;
+ }
+
+ switch (genMode)
+ {
+ case GL_NONE:
+ if (components != 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
+ return false;
+ }
+ break;
+
+ case GL_OBJECT_LINEAR_CHROMIUM:
+ case GL_EYE_LINEAR_CHROMIUM:
+ case GL_CONSTANT_CHROMIUM:
+ if (components < 1 || components > 4)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
+ return false;
+ }
+ if (!coeffs)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
+ return false;
+ }
+
+ // If the location is -1 then the command is silently ignored
+ // and no further validation is needed.
+ if (location == -1)
+ return true;
+
+ const auto &binding = programObject->getFragmentInputBindingInfo(location);
+
+ if (!binding.valid)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
+ return false;
+ }
+
+ if (binding.type != GL_NONE)
+ {
+ GLint expectedComponents = 0;
+ switch (binding.type)
+ {
+ case GL_FLOAT:
+ expectedComponents = 1;
+ break;
+ case GL_FLOAT_VEC2:
+ expectedComponents = 2;
+ break;
+ case GL_FLOAT_VEC3:
+ expectedComponents = 3;
+ break;
+ case GL_FLOAT_VEC4:
+ expectedComponents = 4;
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "Fragment input type is not a floating point scalar or vector."));
+ return false;
+ }
+ if (expectedComponents != components && genMode != GL_NONE)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateCopyTextureCHROMIUM(Context *context,
+ GLuint sourceId,
+ GLuint destId,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ if (!context->getExtensions().copyTexture)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
+ return false;
+ }
+
+ const gl::Texture *source = context->getTexture(sourceId);
+ if (source == nullptr)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
+ return false;
+ }
+
+ if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
+ return false;
+ }
+
+ GLenum sourceTarget = source->getTarget();
+ ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
+ if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
+ return false;
+ }
+
+ const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
+ if (!IsValidCopyTextureFormat(context, sourceFormat.format))
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
+ return false;
+ }
+
+ const gl::Texture *dest = context->getTexture(destId);
+ if (dest == nullptr)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION,
+ "Destination internal format and type combination is not valid."));
+ return false;
+ }
+
+ if (dest->getImmutableFormat())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopySubTextureCHROMIUM(Context *context,
+ GLuint sourceId,
+ GLuint destId,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ if (!context->getExtensions().copyTexture)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
+ return false;
+ }
+
+ const gl::Texture *source = context->getTexture(sourceId);
+ if (source == nullptr)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
+ return false;
+ }
+
+ if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
+ return false;
+ }
+
+ GLenum sourceTarget = source->getTarget();
+ ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
+ if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
+ return false;
+ }
+
+ if (x < 0 || y < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
+ return false;
+ }
+
+ if (width < 0 || height < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
+ return false;
+ }
+
+ if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
+ static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
+ return false;
+ }
+
+ const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
+ if (!IsValidCopyTextureFormat(context, sourceFormat.format))
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
+ return false;
+ }
+
+ const gl::Texture *dest = context->getTexture(destId);
+ if (dest == nullptr)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
+ return false;
+ }
+
+ GLenum destTarget = dest->getTarget();
+ ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
+ if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
+ return false;
+ }
+
+ const gl::Format &destFormat = dest->getFormat(destTarget, 0);
+ if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION,
+ "Destination internal format and type combination is not valid."));
+ return false;
+ }
+
+ if (xoffset < 0 || yoffset < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
+ return false;
+ }
+
+ if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
+ static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
+{
+ if (!context->getExtensions().copyCompressedTexture)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "GL_CHROMIUM_copy_compressed_texture extension not available."));
+ return false;
+ }
+
+ const gl::Texture *source = context->getTexture(sourceId);
+ if (source == nullptr)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
+ return false;
+ }
+
+ if (source->getTarget() != GL_TEXTURE_2D)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
+ return false;
+ }
+
+ if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
+ return false;
+ }
+
+ const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
+ if (!sourceFormat.info->compressed)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
+ return false;
+ }
+
+ const gl::Texture *dest = context->getTexture(destId);
+ if (dest == nullptr)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
+ return false;
+ }
+
+ if (dest->getTarget() != GL_TEXTURE_2D)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
+ return false;
+ }
+
+ if (dest->getImmutableFormat())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreateShader(Context *context, GLenum type)
+{
+ switch (type)
+ {
+ case GL_VERTEX_SHADER:
+ case GL_FRAGMENT_SHADER:
+ break;
+
+ case GL_COMPUTE_SHADER:
+ if (context->getClientVersion() < Version(3, 1))
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBufferData(ValidationContext *context,
+ GLenum target,
+ GLsizeiptr size,
+ const GLvoid *data,
+ GLenum usage)
+{
+ if (size < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ switch (usage)
+ {
+ case GL_STREAM_DRAW:
+ case GL_STATIC_DRAW:
+ case GL_DYNAMIC_DRAW:
+ break;
+
+ case GL_STREAM_READ:
+ case GL_STREAM_COPY:
+ case GL_STATIC_READ:
+ case GL_STATIC_COPY:
+ case GL_DYNAMIC_READ:
+ case GL_DYNAMIC_COPY:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (!ValidBufferTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBufferSubData(ValidationContext *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr size,
+ const GLvoid *data)
+{
+ if (size < 0 || offset < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (!ValidBufferTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (buffer->isMapped())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Check for possible overflow of size + offset
+ angle::CheckedNumeric<size_t> checkedSize(size);
+ checkedSize += offset;
+ if (!checkedSize.IsValid())
+ {
+ context->handleError(Error(GL_OUT_OF_MEMORY));
+ return false;
+ }
+
+ if (size + offset > buffer->getSize())
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name)
+{
+ if (!context->getExtensions().webglCompatibility)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_ANGLE_webgl_compatibility is not available."));
+ return false;
+ }
+
+ const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
+ auto extension = extensionInfos.find(name);
+ if (extension == extensionInfos.end() || !extension->second.Enableable)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not enableable.", name));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
+{
+ if (texture < GL_TEXTURE0 ||
+ texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
+{
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ switch (shaderObject->getType())
+ {
+ case GL_VERTEX_SHADER:
+ {
+ if (programObject->getAttachedVertexShader())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ if (programObject->getAttachedFragmentShader())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ }
+ case GL_COMPUTE_SHADER:
+ {
+ if (programObject->getAttachedComputeShader())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return true;
+}
+
+bool ValidateBindAttribLocation(ValidationContext *context,
+ GLuint program,
+ GLuint index,
+ const GLchar *name)
+{
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
+ return false;
+ }
+
+ if (strncmp(name, "gl_", 3) == 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
+ return false;
+ }
+
+ return GetValidProgram(context, program) != nullptr;
+}
+
+bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
+{
+ if (!ValidBufferTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
+ return false;
+ }
+
+ if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+ !context->isBufferGenerated(buffer))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
+{
+ if (!ValidFramebufferTarget(target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
+ return false;
+ }
+
+ if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+ !context->isFramebufferGenerated(framebuffer))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
+{
+ if (target != GL_RENDERBUFFER)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
+ return false;
+ }
+
+ if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+ !context->isRenderbufferGenerated(renderbuffer))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidBlendEquationMode(GLenum mode)
+{
+ switch (mode)
+ {
+ case GL_FUNC_ADD:
+ case GL_FUNC_SUBTRACT:
+ case GL_FUNC_REVERSE_SUBTRACT:
+ case GL_MIN:
+ case GL_MAX:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
+{
+ if (!ValidBlendEquationMode(mode))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
+{
+ if (!ValidBlendEquationMode(modeRGB))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
+ return false;
+ }
+
+ if (!ValidBlendEquationMode(modeAlpha))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
+{
+ return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
+}
+
+static bool ValidSrcBlendFunc(GLenum srcBlend)
+{
+ switch (srcBlend)
+ {
+ 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:
+ case GL_SRC_ALPHA_SATURATE:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
+{
+ switch (dstBlend)
+ {
+ 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;
+
+ case GL_SRC_ALPHA_SATURATE:
+ return (contextMajorVersion >= 3);
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateBlendFuncSeparate(ValidationContext *context,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha)
+{
+ if (!ValidSrcBlendFunc(srcRGB))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
+ return false;
+ }
+
+ if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
+ return false;
+ }
+
+ if (!ValidSrcBlendFunc(srcAlpha))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
+ return false;
+ }
+
+ if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
+ return false;
+ }
+
+ if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc)
+ {
+ 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)
+ {
+ ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
+ "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
+ "implementation.");
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "Simultaneous use of "
+ "GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
+ "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not "
+ "supported by this implementation."));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/validationES2.h b/gfx/angle/src/libANGLE/validationES2.h
new file mode 100755
index 000000000..d40a62606
--- /dev/null
+++ b/gfx/angle/src/libANGLE/validationES2.h
@@ -0,0 +1,375 @@
+//
+// Copyright (c) 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.h: Validation functions for OpenGL ES 2.0 entry point parameters
+
+#ifndef LIBANGLE_VALIDATION_ES2_H_
+#define LIBANGLE_VALIDATION_ES2_H_
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+namespace gl
+{
+class Context;
+class ValidationContext;
+class Texture;
+
+bool ValidateES2TexImageParameters(Context *context,
+ GLenum 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 GLvoid *pixels);
+
+bool ValidateES2CopyTexImageParameters(ValidationContext *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border);
+
+bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
+ GLsizei width, GLsizei height);
+
+bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
+ const GLenum *attachments);
+
+bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs);
+
+bool ValidateBindVertexArrayOES(Context *context, GLuint array);
+bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n);
+bool ValidateGenVertexArraysOES(Context *context, GLsizei n);
+bool ValidateIsVertexArrayOES(Context *context);
+
+bool ValidateProgramBinaryOES(Context *context,
+ GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length);
+bool ValidateGetProgramBinaryOES(Context *context,
+ GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary);
+
+// GL_KHR_debug
+bool ValidateDebugMessageControlKHR(Context *context,
+ GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled);
+bool ValidateDebugMessageInsertKHR(Context *context,
+ GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf);
+bool ValidateDebugMessageCallbackKHR(Context *context,
+ GLDEBUGPROCKHR callback,
+ const void *userParam);
+bool ValidateGetDebugMessageLogKHR(Context *context,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog);
+bool ValidatePushDebugGroupKHR(Context *context,
+ GLenum source,
+ GLuint id,
+ GLsizei length,
+ const GLchar *message);
+bool ValidatePopDebugGroupKHR(Context *context);
+bool ValidateObjectLabelKHR(Context *context,
+ GLenum identifier,
+ GLuint name,
+ GLsizei length,
+ const GLchar *label);
+bool ValidateGetObjectLabelKHR(Context *context,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label);
+bool ValidateObjectPtrLabelKHR(Context *context,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label);
+bool ValidateGetObjectPtrLabelKHR(Context *context,
+ const void *ptr,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label);
+bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params);
+bool ValidateBlitFramebufferANGLE(Context *context,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+
+bool ValidateClear(ValidationContext *context, GLbitfield mask);
+bool ValidateTexImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels);
+bool ValidateTexImage2DRobust(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLvoid *pixels);
+bool ValidateTexSubImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels);
+bool ValidateTexSubImage2DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLvoid *pixels);
+bool ValidateCompressedTexImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const GLvoid *data);
+bool ValidateCompressedTexSubImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const GLvoid *data);
+bool ValidateBindTexture(Context *context, GLenum target, GLuint texture);
+
+bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params);
+bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access);
+bool ValidateUnmapBufferOES(Context *context, GLenum target);
+bool ValidateMapBufferRangeEXT(Context *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+bool ValidateFlushMappedBufferRangeEXT(Context *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr length);
+
+bool ValidateBindUniformLocationCHROMIUM(Context *context,
+ GLuint program,
+ GLint location,
+ const GLchar *name);
+
+bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components);
+
+// CHROMIUM_path_rendering
+bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix);
+bool ValidateMatrixMode(Context *context, GLenum matrixMode);
+bool ValidateGenPaths(Context *context, GLsizei range);
+bool ValidateDeletePaths(Context *context, GLuint first, GLsizei range);
+bool ValidatePathCommands(Context *context,
+ GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords);
+bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value);
+bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value);
+bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask);
+bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask);
+bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask);
+bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode);
+bool ValidateStencilThenCoverFillPath(Context *context,
+ GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode);
+bool ValidateStencilThenCoverStrokePath(Context *context,
+ GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode);
+bool ValidateIsPath(Context *context);
+bool ValidateCoverFillPathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+bool ValidateCoverStrokePathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+bool ValidateStencilFillPathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBAse,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+bool ValidateStencilStrokePathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+bool ValidateStencilThenCoverFillPathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+bool ValidateBindFragmentInputLocation(Context *context,
+ GLuint program,
+ GLint location,
+ const GLchar *name);
+bool ValidateProgramPathFragmentInputGen(Context *context,
+ GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs);
+
+bool ValidateCopyTextureCHROMIUM(Context *context,
+ GLuint sourceId,
+ GLuint destId,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+bool ValidateCopySubTextureCHROMIUM(Context *context,
+ GLuint sourceId,
+ GLuint destId,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId);
+
+bool ValidateCreateShader(Context *context, GLenum type);
+bool ValidateBufferData(ValidationContext *context,
+ GLenum target,
+ GLsizeiptr size,
+ const GLvoid *data,
+ GLenum usage);
+bool ValidateBufferSubData(ValidationContext *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr size,
+ const GLvoid *data);
+
+bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name);
+
+bool ValidateActiveTexture(ValidationContext *context, GLenum texture);
+bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader);
+bool ValidateBindAttribLocation(ValidationContext *context,
+ GLuint program,
+ GLuint index,
+ const GLchar *name);
+bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer);
+bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer);
+bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer);
+bool ValidateBlendEquation(ValidationContext *context, GLenum mode);
+bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha);
+bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor);
+bool ValidateBlendFuncSeparate(ValidationContext *context,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha);
+
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES2_H_
diff --git a/gfx/angle/src/libANGLE/validationES3.cpp b/gfx/angle/src/libANGLE/validationES3.cpp
new file mode 100755
index 000000000..a4cb71e6a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/validationES3.cpp
@@ -0,0 +1,2038 @@
+//
+// Copyright (c) 2013-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.
+//
+
+// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
+
+#include "libANGLE/validationES3.h"
+
+#include "base/numerics/safe_conversions.h"
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/FramebufferAttachment.h"
+
+using namespace angle;
+
+namespace gl
+{
+
+static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
+{
+ // 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.
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ // The type and format are valid if any supported internal format has that type and format
+ if (!ValidES3Format(format) || !ValidES3Type(type))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ // Check if this is a valid format combination to load texture data
+ if (!ValidES3FormatCombination(format, type, internalFormat))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateES3TexImageParametersBase(Context *context,
+ GLenum 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 GLvoid *pixels)
+{
+ // Validate image size
+ if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ // Verify zero border
+ if (border != 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
+ std::numeric_limits<GLsizei>::max() - xoffset < width ||
+ std::numeric_limits<GLsizei>::max() - yoffset < height ||
+ std::numeric_limits<GLsizei>::max() - zoffset < depth)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ if (!isSubImage && width != height)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_3D:
+ if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
+ static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ if (!texture)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (texture->getImmutableFormat() && !isSubImage)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Validate texture formats
+ GLenum actualInternalFormat =
+ isSubImage ? texture->getFormat(target, level).asSized() : internalformat;
+ if (isSubImage && actualInternalFormat == GL_NONE)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
+ return false;
+ }
+
+ const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
+ if (isCompressed)
+ {
+ if (!actualFormatInfo.compressed)
+ {
+ context->handleError(Error(
+ GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
+ return false;
+ }
+
+ if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (target == GL_TEXTURE_3D)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ else
+ {
+ if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
+ {
+ return false;
+ }
+
+ if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ // Validate sub image parameters
+ if (isSubImage)
+ {
+ if (isCompressed != actualFormatInfo.compressed)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (width == 0 || height == 0 || depth == 0)
+ {
+ return false;
+ }
+
+ if (xoffset < 0 || yoffset < 0 || zoffset < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ 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->handleError(Error(GL_INVALID_VALUE));
+ 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->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+
+ if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
+ imageSize))
+ {
+ return false;
+ }
+
+ // Check for pixel unpack buffer related API errors
+ gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
+ 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>(gl::GetTypeInfo(type).bytes);
+
+ if ((offset % dataBytesPerPixel) != 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
+ return false;
+ }
+ }
+
+ // ...the buffer object's data store is currently mapped.
+ if (pixelUnpackBuffer->isMapped())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Pixel unpack buffer is mapped."));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateES3TexImage2DParameters(Context *context,
+ GLenum 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 GLvoid *pixels)
+{
+ if (!ValidTexture2DDestinationTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
+ isSubImage, xoffset, yoffset, zoffset, width, height,
+ depth, border, format, type, imageSize, pixels);
+}
+
+bool ValidateES3TexImage3DParameters(Context *context,
+ GLenum 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 GLvoid *pixels)
+{
+ if (!ValidTexture3DDestinationTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return ValidateES3TexImageParametersBase(context, 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.pixelBytes > 0)
+ {
+ 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 Format &textureFormat,
+ const Format &framebufferFormat,
+ GLuint readBufferHandle)
+{
+ const auto &textureFormatInfo = *textureFormat.info;
+ const auto &framebufferFormatInfo = *framebufferFormat.info;
+
+ 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 ||
+ textureFormatInfo.componentType == GL_FLOAT) &&
+ !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+ framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
+ framebufferFormatInfo.componentType == GL_FLOAT))
+ {
+ 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 = NULL;
+ if (readBufferHandle != 0)
+ {
+ // Not the default framebuffer, therefore the read buffer must be a user-created texture or
+ // renderbuffer
+ if (framebufferFormat.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.
+ GLenum sizedInternalFormat =
+ GetSizedInternalFormat(framebufferFormatInfo.format, framebufferFormatInfo.type);
+ sourceEffectiveFormat = &GetInternalFormatInfo(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 = &GetInternalFormatInfo(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 (textureFormat.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 = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ return false;
+ }
+ }
+
+ if (textureFormat.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(ValidationContext *context,
+ GLenum 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, target, level, internalformat, isSubImage,
+ xoffset, yoffset, zoffset, x, y, width, height, border,
+ &textureFormat))
+ {
+ return false;
+ }
+ ASSERT(textureFormat.valid() || !isSubImage);
+
+ const auto &state = context->getGLState();
+ gl::Framebuffer *framebuffer = state.getReadFramebuffer();
+ GLuint readFramebufferID = framebuffer->id();
+
+ if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if (readFramebufferID != 0 && framebuffer->getSamples(context->getContextState()) != 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
+
+ if (isSubImage)
+ {
+ if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
+ readFramebufferID))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ else
+ {
+ // Use format/type from the source FBO. (Might not be perfect for all cases?)
+ const auto framebufferFormat = source->getFormat();
+ Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
+ if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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(ValidationContext *context,
+ GLenum 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->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
+ xoffset, yoffset, zoffset, x, y, width, height,
+ border);
+}
+
+bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
+ GLenum 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->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
+ xoffset, yoffset, zoffset, x, y, width, height,
+ border);
+}
+
+bool ValidateES3TexStorageParametersBase(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ if (width < 1 || height < 1 || depth < 1 || levels < 1)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ GLsizei maxDim = std::max(width, height);
+ if (target != GL_TEXTURE_2D_ARRAY)
+ {
+ maxDim = std::max(maxDim, depth);
+ }
+
+ if (levels > gl::log2(maxDim) + 1)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ {
+ if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+ static_cast<GLuint>(height) > caps.max2DTextureSize)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_CUBE_MAP:
+ {
+ if (width != height)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_3D:
+ {
+ if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
+ static_cast<GLuint>(height) > caps.max3DTextureSize ||
+ static_cast<GLuint>(depth) > caps.max3DTextureSize)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+ static_cast<GLuint>(height) > caps.max2DTextureSize ||
+ static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+
+ gl::Texture *texture = context->getTargetTexture(target);
+ if (!texture || texture->id() == 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (texture->getImmutableFormat())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+ if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (formatInfo.pixelBytes == 0)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateES3TexStorage2DParameters(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ if (!ValidTexture2DTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
+ height, depth);
+}
+
+bool ValidateES3TexStorage3DParameters(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ if (!ValidTexture3DTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
+ height, depth);
+}
+
+bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
+ return false;
+ }
+
+ return ValidateBeginQueryBase(context, target, id);
+}
+
+bool ValidateEndQuery(gl::Context *context, GLenum target)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
+ return false;
+ }
+
+ return ValidateEndQueryBase(context, target);
+}
+
+bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
+ return false;
+ }
+
+ return ValidateGetQueryivBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
+ return false;
+ }
+
+ return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (layer < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
+ {
+ return false;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+ if (texture != 0)
+ {
+ gl::Texture *tex = context->getTexture(texture);
+ ASSERT(tex);
+
+ switch (tex->getTarget())
+ {
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ if (level > gl::log2(caps.max2DTextureSize))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_3D:
+ {
+ if (level > gl::log2(caps.max3DTextureSize))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const auto &format = tex->getFormat(tex->getTarget(), level);
+ if (format.info->compressed)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height)
+{
+ if (!ValidateRenderbufferStorageParametersBase(context, 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.
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+ if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ 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->handleError(
+ Error(GL_INVALID_OPERATION,
+ "Samples must not be greater than maximum supported value for the format."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
+ return false;
+ }
+
+ bool defaultFramebuffer = false;
+
+ switch (target)
+ {
+ case GL_DRAW_FRAMEBUFFER:
+ case GL_FRAMEBUFFER:
+ defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
+ break;
+ case GL_READ_FRAMEBUFFER:
+ defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
+ return false;
+ }
+
+ return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
+}
+
+bool ValidateClearBuffer(ValidationContext *context)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (context->getGLState().getDrawFramebuffer()->checkStatus(context->getContextState()) !=
+ GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawRangeElements(Context *context,
+ GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ IndexRange *indexRange)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+ return false;
+ }
+
+ if (end < start)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "end < start"));
+ return false;
+ }
+
+ if (!ValidateDrawElements(context, mode, count, type, indices, 0, indexRange))
+ {
+ return false;
+ }
+
+ if (indexRange->end > end || indexRange->start < start)
+ {
+ // GL spec says that behavior in this case is undefined - generating an error is fine.
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Indices are out of the start, end range."));
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateGetUniformBase(context, program, location);
+}
+
+bool ValidateReadBuffer(Context *context, GLenum src)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
+
+ if (readFBO == nullptr)
+ {
+ context->handleError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
+ return false;
+ }
+
+ if (src == GL_NONE)
+ {
+ return true;
+ }
+
+ if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
+ {
+ context->handleError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
+ return false;
+ }
+
+ if (readFBO->id() == 0)
+ {
+ if (src != GL_BACK)
+ {
+ const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
+ context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
+ return false;
+ }
+ }
+ else
+ {
+ GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
+
+ if (drawBuffer >= context->getCaps().maxDrawBuffers)
+ {
+ const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
+ context->handleError(gl::Error(GL_INVALID_OPERATION, errorMsg));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateCompressedTexImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const GLvoid *data)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!ValidTextureTarget(context, target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ // Validate image size
+ if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
+ if (!formatInfo.compressed)
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
+ return false;
+ }
+
+ auto blockSizeOrErr =
+ formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
+ if (blockSizeOrErr.isError())
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ // 3D texture target validation
+ if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
+ {
+ context->handleError(
+ Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
+ return false;
+ }
+
+ // validateES3TexImageFormat sets the error code if there is an error
+ if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
+ 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
+ data))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindVertexArray(Context *context, GLuint array)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateBindVertexArrayBase(context, array);
+}
+
+bool ValidateIsVertexArray(Context *context)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramBinary(Context *context,
+ GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
+}
+
+bool ValidateGetProgramBinary(Context *context,
+ GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
+}
+
+bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+ return false;
+ }
+
+ if (GetValidProgram(context, program) == nullptr)
+ {
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+ if (value != GL_FALSE && value != GL_TRUE)
+ {
+ context->handleError(Error(
+ GL_INVALID_VALUE, "Invalid value, expected GL_FALSE or GL_TRUE: %i", value));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlitFramebuffer(Context *context,
+ 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->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
+ dstX1, dstY1, mask, filter);
+}
+
+bool ValidateClearBufferiv(ValidationContext *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *value)
+{
+ switch (buffer)
+ {
+ case GL_COLOR:
+ if (drawbuffer < 0 ||
+ static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ case GL_STENCIL:
+ if (drawbuffer != 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return ValidateClearBuffer(context);
+}
+
+bool ValidateClearBufferuiv(ValidationContext *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *value)
+{
+ switch (buffer)
+ {
+ case GL_COLOR:
+ if (drawbuffer < 0 ||
+ static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return ValidateClearBuffer(context);
+}
+
+bool ValidateClearBufferfv(ValidationContext *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *value)
+{
+ switch (buffer)
+ {
+ case GL_COLOR:
+ if (drawbuffer < 0 ||
+ static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ case GL_DEPTH:
+ if (drawbuffer != 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return ValidateClearBuffer(context);
+}
+
+bool ValidateClearBufferfi(ValidationContext *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
+{
+ switch (buffer)
+ {
+ case GL_DEPTH_STENCIL:
+ if (drawbuffer != 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return ValidateClearBuffer(context);
+}
+
+bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+ return false;
+ }
+
+ return ValidateDrawBuffersBase(context, n, bufs);
+}
+
+bool ValidateCopyTexSubImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
+ yoffset, zoffset, x, y, width, height, 0);
+}
+
+bool ValidateTexImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
+ 0, 0, width, height, depth, border, format, type, -1,
+ pixels);
+}
+
+bool ValidateTexImage3DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLvoid *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
+ 0, 0, width, height, depth, border, format, type,
+ bufSize, pixels);
+}
+
+bool ValidateTexSubImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
+ yoffset, zoffset, width, height, depth, 0, format, type,
+ -1, pixels);
+}
+
+bool ValidateTexSubImage3DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLvoid *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
+ yoffset, zoffset, width, height, depth, 0, format, type,
+ bufSize, pixels);
+}
+
+bool ValidateCompressedTexSubImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const GLvoid *data)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const InternalFormat &formatInfo = GetInternalFormatInfo(format);
+ auto blockSizeOrErr =
+ formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
+ if (blockSizeOrErr.isError())
+ {
+ context->handleError(blockSizeOrErr.getError());
+ return false;
+ }
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (!data)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
+ width, height, depth, 0, GL_NONE, GL_NONE, -1, data);
+}
+
+bool ValidateGenQueries(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
+{
+ return ValidateGenOrDeleteCountES3(context, count);
+}
+
+bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
+{
+ return ValidateGenOrDeleteCountES3(context, count);
+}
+
+bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
+{
+ if (!ValidateGenOrDeleteES3(context, 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->handleError(
+ Error(GL_INVALID_OPERATION, "Attempt to delete active transform feedback."));
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateGenOrDeleteES3(Context *context, GLint n)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+ return false;
+ }
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+ return false;
+ }
+ if (count < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "count < 0"));
+ return false;
+ }
+ return true;
+}
+
+bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+ return false;
+ }
+ switch (primitiveMode)
+ {
+ case GL_TRIANGLES:
+ case GL_LINES:
+ case GL_POINTS:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid primitive mode."));
+ return false;
+ }
+
+ TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+
+ if (transformFeedback->isActive())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Transform feedback is already active."));
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
+{
+ return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
+}
+
+bool ValidateGetBufferPointervRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLvoid **params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateUnmapBuffer(Context *context, GLenum target)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateUnmapBufferBase(context, target);
+}
+
+bool ValidateMapBufferRange(Context *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+ return false;
+ }
+
+ return ValidateMapBufferRangeBase(context, target, offset, length, access);
+}
+
+bool ValidateFlushMappedBufferRange(Context *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr length)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+ return false;
+ }
+
+ return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
+}
+
+bool ValidateIndexedStateQuery(ValidationContext *context,
+ GLenum pname,
+ GLuint index,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ GLenum nativeType;
+ unsigned int numParams;
+ if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ switch (pname)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ if (index >= caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ case GL_UNIFORM_BUFFER_START:
+ case GL_UNIFORM_BUFFER_SIZE:
+ case GL_UNIFORM_BUFFER_BINDING:
+ if (index >= caps.maxUniformBufferBindings)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+ case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
+ case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
+ if (index >= 3u)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+
+ return true;
+}
+
+bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
+{
+ if (context->getClientVersion() < ES_3_0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
+ return false;
+ }
+ return ValidateIndexedStateQuery(context, target, index, nullptr);
+}
+
+bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data)
+{
+ if (context->getClientVersion() < ES_3_0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateIndexedStateQuery(context, target, index, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
+{
+ if (context->getClientVersion() < ES_3_0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
+ return false;
+ }
+ return ValidateIndexedStateQuery(context, target, index, nullptr);
+}
+
+bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data)
+{
+ if (context->getClientVersion() < ES_3_0)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateIndexedStateQuery(context, target, index, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopyBufferSubData(ValidationContext *context,
+ GLenum readTarget,
+ GLenum writeTarget,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "CopyBufferSubData requires ES 3 or greater"));
+ return false;
+ }
+
+ if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target"));
+ return false;
+ }
+
+ Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
+ Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
+
+ if (!readBuffer || !writeBuffer)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound to target"));
+ return false;
+ }
+
+ // Verify that readBuffer and writeBuffer are not currently mapped
+ if (readBuffer->isMapped() || writeBuffer->isMapped())
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Cannot call CopyBufferSubData on a mapped buffer"));
+ 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->handleError(
+ Error(GL_INVALID_VALUE, "Integer overflow when validating copy offsets."));
+ return false;
+ }
+
+ if (readOffset < 0 || writeOffset < 0 || size < 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "readOffset, writeOffset and size must all be non-negative"));
+ return false;
+ }
+
+ if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
+ checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Buffer offset overflow in CopyBufferSubData"));
+ return false;
+ }
+
+ if (readBuffer == writeBuffer)
+ {
+ auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
+ if (!checkedOffsetDiff.IsValid())
+ {
+ // This shold not be possible.
+ UNREACHABLE();
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Integer overflow when validating same buffer copy."));
+ return false;
+ }
+
+ if (checkedOffsetDiff.ValueOrDie() < size)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/validationES3.h b/gfx/angle/src/libANGLE/validationES3.h
new file mode 100755
index 000000000..ba98c998a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/validationES3.h
@@ -0,0 +1,369 @@
+//
+// Copyright (c) 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.h: Validation functions for OpenGL ES 3.0 entry point parameters
+
+#ifndef LIBANGLE_VALIDATION_ES3_H_
+#define LIBANGLE_VALIDATION_ES3_H_
+
+#include <GLES3/gl3.h>
+
+namespace gl
+{
+class Context;
+struct IndexRange;
+class ValidationContext;
+
+bool ValidateES3TexImageParametersBase(ValidationContext *context,
+ GLenum 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 GLvoid *pixels);
+
+bool ValidateES3TexStorageParameters(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+bool ValidateES3TexImage2DParameters(Context *context,
+ GLenum 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 GLvoid *pixels);
+
+bool ValidateES3TexImage3DParameters(Context *context,
+ GLenum 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 GLvoid *pixels);
+
+bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border);
+
+bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border);
+
+bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
+ GLenum 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(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+bool ValidateES3TexStorage2DParameters(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+bool ValidateES3TexStorage3DParameters(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+bool ValidateBeginQuery(Context *context, GLenum target, GLuint id);
+
+bool ValidateEndQuery(Context *context, GLenum target);
+
+bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params);
+
+bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params);
+
+bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer);
+
+bool ValidateES3RenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height);
+
+bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
+ const GLenum *attachments);
+
+bool ValidateClearBuffer(ValidationContext *context);
+
+bool ValidateDrawRangeElements(Context *context,
+ GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ IndexRange *indexRange);
+
+bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params);
+
+bool ValidateReadBuffer(Context *context, GLenum mode);
+
+bool ValidateCompressedTexImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const GLvoid *data);
+
+bool ValidateBindVertexArray(Context *context, GLuint array);
+bool ValidateIsVertexArray(Context *context);
+
+bool ValidateProgramBinary(Context *context,
+ GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length);
+bool ValidateGetProgramBinary(Context *context,
+ GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary);
+bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value);
+bool ValidateBlitFramebuffer(Context *context,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+bool ValidateClearBufferiv(ValidationContext *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *value);
+bool ValidateClearBufferuiv(ValidationContext *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *value);
+bool ValidateClearBufferfv(ValidationContext *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *value);
+bool ValidateClearBufferfi(ValidationContext *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil);
+bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs);
+bool ValidateCopyTexSubImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+bool ValidateTexImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels);
+bool ValidateTexImage3DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLvoid *pixels);
+bool ValidateTexSubImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels);
+bool ValidateTexSubImage3DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLvoid *pixels);
+bool ValidateCompressedTexSubImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const GLvoid *data);
+
+bool ValidateGenQueries(Context *context, GLint n, GLuint *ids);
+bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *ids);
+bool ValidateGenSamplers(Context *context, GLint count, GLuint *samplers);
+bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *samplers);
+bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *ids);
+bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids);
+bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *arrays);
+bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *arrays);
+
+bool ValidateGenOrDeleteES3(Context *context, GLint n);
+bool ValidateGenOrDeleteCountES3(Context *context, GLint count);
+
+bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode);
+
+bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params);
+bool ValidateGetBufferPointervRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLvoid **params);
+bool ValidateUnmapBuffer(Context *context, GLenum target);
+bool ValidateMapBufferRange(Context *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+bool ValidateFlushMappedBufferRange(Context *context,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr length);
+
+bool ValidateIndexedStateQuery(ValidationContext *context,
+ GLenum pname,
+ GLuint index,
+ GLsizei *length);
+bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data);
+bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data);
+bool ValidateGetInteger64i_v(ValidationContext *context,
+ GLenum target,
+ GLuint index,
+ GLint64 *data);
+bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data);
+
+bool ValidateCopyBufferSubData(ValidationContext *context,
+ GLenum readTarget,
+ GLenum writeTarget,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size);
+
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES3_H_
diff --git a/gfx/angle/src/libANGLE/validationES31.cpp b/gfx/angle/src/libANGLE/validationES31.cpp
new file mode 100755
index 000000000..4cea05e47
--- /dev/null
+++ b/gfx/angle/src/libANGLE/validationES31.cpp
@@ -0,0 +1,67 @@
+//
+// Copyright (c) 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.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES3.h"
+
+using namespace angle;
+
+namespace gl
+{
+
+bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
+ return false;
+ }
+
+ if (!ValidateIndexedStateQuery(context, target, index, nullptr))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBooleani_vRobustANGLE(Context *context,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *data)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateIndexedStateQuery(context, target, index, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/libANGLE/validationES31.h b/gfx/angle/src/libANGLE/validationES31.h
new file mode 100755
index 000000000..63ca0db5b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/validationES31.h
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 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.h: Validation functions for OpenGL ES 3.1 entry point parameters
+
+#ifndef LIBANGLE_VALIDATION_ES31_H_
+#define LIBANGLE_VALIDATION_ES31_H_
+
+#include <GLES3/gl31.h>
+
+namespace gl
+{
+class Context;
+
+bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data);
+bool ValidateGetBooleani_vRobustANGLE(Context *context,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *data);
+
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES31_H_
diff --git a/gfx/angle/src/libANGLE/validationES_unittest.cpp b/gfx/angle/src/libANGLE/validationES_unittest.cpp
new file mode 100755
index 000000000..925005a6e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/validationES_unittest.cpp
@@ -0,0 +1,140 @@
+//
+// 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.
+//
+// validationES unit tests:
+// Unit tests for general ES validation functions.
+//
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "libANGLE/ContextState.h"
+#include "libANGLE/renderer/FramebufferImpl_mock.h"
+#include "libANGLE/renderer/ProgramImpl_mock.h"
+#include "libANGLE/renderer/TextureImpl_mock.h"
+#include "libANGLE/validationES.h"
+#include "tests/angle_unittests_utils.h"
+
+using namespace gl;
+using namespace rx;
+using testing::_;
+using testing::NiceMock;
+using testing::Return;
+
+namespace
+{
+
+class MockValidationContext : public ValidationContext
+{
+ public:
+ MockValidationContext(const Version &version,
+ State *state,
+ const Caps &caps,
+ const TextureCapsMap &textureCaps,
+ const Extensions &extensions,
+ const ResourceManager *resourceManager,
+ const Limitations &limitations,
+ const ResourceMap<Framebuffer> &framebufferMap,
+ bool skipValidation);
+
+ MOCK_METHOD1(handleError, void(const Error &));
+};
+
+MockValidationContext::MockValidationContext(const Version &version,
+ State *state,
+ const Caps &caps,
+ const TextureCapsMap &textureCaps,
+ const Extensions &extensions,
+ const ResourceManager *resourceManager,
+ const Limitations &limitations,
+ const ResourceMap<Framebuffer> &framebufferMap,
+ bool skipValidation)
+ : ValidationContext(version,
+ state,
+ caps,
+ textureCaps,
+ extensions,
+ resourceManager,
+ limitations,
+ framebufferMap,
+ skipValidation)
+{
+}
+
+// Test that ANGLE generates an INVALID_OPERATION when validating index data that uses a value
+// larger than MAX_ELEMENT_INDEX. Not specified in the GLES 3 spec, it's undefined behaviour,
+// but we want a test to ensure we maintain this behaviour.
+TEST(ValidationESTest, DrawElementsWithMaxIndexGivesError)
+{
+ auto framebufferImpl = MakeFramebufferMock();
+ auto programImpl = MakeProgramMock();
+
+ // TODO(jmadill): Generalize some of this code so we can re-use it for other tests.
+ NiceMock<MockGLFactory> mockFactory;
+ EXPECT_CALL(mockFactory, createFramebuffer(_)).WillOnce(Return(framebufferImpl));
+ EXPECT_CALL(mockFactory, createProgram(_)).WillOnce(Return(programImpl));
+ EXPECT_CALL(mockFactory, createVertexArray(_)).WillOnce(Return(nullptr));
+
+ State state;
+ Caps caps;
+ TextureCapsMap textureCaps;
+ Extensions extensions;
+ Limitations limitations;
+ ResourceMap<Framebuffer> framebufferMap;
+
+ // Set some basic caps.
+ caps.maxElementIndex = 100;
+ caps.maxDrawBuffers = 1;
+ caps.maxColorAttachments = 1;
+ state.initialize(caps, extensions, Version(3, 0), false, true);
+
+ NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>();
+ EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
+ EXPECT_CALL(*textureImpl, setStorage(_, _, _, _)).WillOnce(Return(Error(GL_NO_ERROR)));
+ EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
+
+ Texture *texture = new Texture(&mockFactory, 0, GL_TEXTURE_2D);
+ texture->addRef();
+ texture->setStorage(GL_TEXTURE_2D, 1, GL_RGBA8, Extents(1, 1, 0));
+
+ VertexArray *vertexArray = new VertexArray(&mockFactory, 0, 1);
+ Framebuffer *framebuffer = new Framebuffer(caps, &mockFactory, 1);
+ framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex::Make2D(0), texture);
+
+ Program *program = new Program(&mockFactory, nullptr, 1);
+
+ state.setVertexArrayBinding(vertexArray);
+ state.setDrawFramebufferBinding(framebuffer);
+ state.setProgram(program);
+
+ NiceMock<MockValidationContext> testContext(Version(3, 0), &state, caps, textureCaps,
+ extensions, nullptr, limitations, framebufferMap,
+ false);
+
+ // Set the expectation for the validation error here.
+ Error expectedError(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage);
+ EXPECT_CALL(testContext, handleError(expectedError)).Times(1);
+
+ // Call once with maximum index, and once with an excessive index.
+ GLuint indexData[] = {0, 1, static_cast<GLuint>(caps.maxElementIndex - 1),
+ 3, 4, static_cast<GLuint>(caps.maxElementIndex)};
+ IndexRange indexRange;
+ EXPECT_TRUE(ValidateDrawElements(&testContext, GL_TRIANGLES, 3, GL_UNSIGNED_INT, indexData, 1,
+ &indexRange));
+ EXPECT_FALSE(ValidateDrawElements(&testContext, GL_TRIANGLES, 6, GL_UNSIGNED_INT, indexData, 2,
+ &indexRange));
+
+ texture->release();
+
+ state.setVertexArrayBinding(nullptr);
+ state.setDrawFramebufferBinding(nullptr);
+ state.setProgram(nullptr);
+
+ SafeDelete(vertexArray);
+ SafeDelete(framebuffer);
+ SafeDelete(program);
+}
+
+} // anonymous namespace