summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libGLESv2
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2')
-rw-r--r--src/3rdparty/angle/src/libGLESv2/BinaryStream.h122
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Buffer.cpp144
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Buffer.h51
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Caps.cpp425
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Caps.h273
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Context.cpp3171
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Context.h524
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Error.cpp48
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Error.h39
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Fence.cpp168
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Fence.h41
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp1
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp640
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Framebuffer.h84
-rw-r--r--src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp230
-rw-r--r--src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h139
-rw-r--r--src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp1
-rw-r--r--src/3rdparty/angle/src/libGLESv2/HandleAllocator.h7
-rw-r--r--src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp57
-rw-r--r--src/3rdparty/angle/src/libGLESv2/ImageIndex.h41
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Program.cpp183
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Program.h46
-rw-r--r--src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp3308
-rw-r--r--src/3rdparty/angle/src/libGLESv2/ProgramBinary.h294
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Query.cpp28
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Query.h17
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp326
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Renderbuffer.h160
-rw-r--r--src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp135
-rw-r--r--src/3rdparty/angle/src/libGLESv2/ResourceManager.h56
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Sampler.cpp43
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Sampler.h60
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Shader.cpp529
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Shader.h163
-rw-r--r--src/3rdparty/angle/src/libGLESv2/State.cpp1455
-rw-r--r--src/3rdparty/angle/src/libGLESv2/State.h319
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Texture.cpp1484
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Texture.h270
-rw-r--r--src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp71
-rw-r--r--src/3rdparty/angle/src/libGLESv2/TransformFeedback.h51
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Uniform.cpp92
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Uniform.h53
-rw-r--r--src/3rdparty/angle/src/libGLESv2/VertexArray.cpp96
-rw-r--r--src/3rdparty/angle/src/libGLESv2/VertexArray.h63
-rw-r--r--src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp55
-rw-r--r--src/3rdparty/angle/src/libGLESv2/VertexAttribute.h119
-rw-r--r--src/3rdparty/angle/src/libGLESv2/angletypes.cpp195
-rw-r--r--src/3rdparty/angle/src/libGLESv2/angletypes.h168
-rw-r--r--src/3rdparty/angle/src/libGLESv2/constants.h28
-rw-r--r--src/3rdparty/angle/src/libGLESv2/formatutils.cpp629
-rw-r--r--src/3rdparty/angle/src/libGLESv2/formatutils.h106
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp10200
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2.def114
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def474
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2d.def114
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def474
-rw-r--r--src/3rdparty/angle/src/libGLESv2/main.cpp130
-rw-r--r--src/3rdparty/angle/src/libGLESv2/main.h11
-rw-r--r--src/3rdparty/angle/src/libGLESv2/mathutil.h162
-rw-r--r--src/3rdparty/angle/src/libGLESv2/precompiled.cpp9
-rw-r--r--src/3rdparty/angle/src/libGLESv2/precompiled.h87
-rw-r--r--src/3rdparty/angle/src/libGLESv2/queryconversions.cpp147
-rw-r--r--src/3rdparty/angle/src/libGLESv2/queryconversions.h17
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h34
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp40
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h44
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h21
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp528
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Image.h89
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp100
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp339
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp59
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h20
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h58
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h20
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h20
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp303
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h213
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h42
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h54
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h20
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h70
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp122
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h110
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h31
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h32
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp292
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp304
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h65
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp22
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h35
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl32
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h35
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl288
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp82
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h56
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp1144
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h104
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp164
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h38
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp26
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h51
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp)44
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h)27
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp255
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h)21
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp74
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h36
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp205
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h87
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp457
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h94
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp2260
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h320
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp51
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h61
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp38
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h32
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp307
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h)61
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp348
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h95
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp1049
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h129
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp961
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h105
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp555
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h87
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp70
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h)9
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp569
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h89
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp162
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h)12
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp)118
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h)12
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp252
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h86
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp156
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h)14
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp)205
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h)17
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp)276
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h)15
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp3266
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h346
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp)71
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h)22
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp)280
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h)6
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp1937
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h313
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h42
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp209
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h52
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp1075
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h84
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp1216
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h185
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl76
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl106
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl111
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl146
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl99
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp)231
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h)25
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp121
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h52
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp72
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h)9
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp)344
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h78
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp173
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h)12
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp144
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h)13
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp133
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h)5
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp)1774
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h342
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/ShaderCache.h)18
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp)13
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h)0
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp)107
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h)2
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp)165
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h)35
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h43
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp233
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h54
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp)58
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h)5
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp588
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h74
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp542
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h)45
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps33
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs)4
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp366
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h92
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp134
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp498
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h76
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp183
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp122
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp3736
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h373
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp667
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h120
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp440
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h74
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp688
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h95
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl42
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl29
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp78
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h42
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp135
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h79
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp207
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp125
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp113
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h356
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp530
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h91
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp500
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps39
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h191
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl266
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h2029
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp661
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h193
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl156
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp112
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h)22
-rw-r--r--src/3rdparty/angle/src/libGLESv2/utilities.cpp817
-rw-r--r--src/3rdparty/angle/src/libGLESv2/utilities.h67
-rw-r--r--src/3rdparty/angle/src/libGLESv2/validationES.cpp1920
-rw-r--r--src/3rdparty/angle/src/libGLESv2/validationES.h92
-rw-r--r--src/3rdparty/angle/src/libGLESv2/validationES2.cpp980
-rw-r--r--src/3rdparty/angle/src/libGLESv2/validationES2.h34
-rw-r--r--src/3rdparty/angle/src/libGLESv2/validationES3.cpp1281
-rw-r--r--src/3rdparty/angle/src/libGLESv2/validationES3.h44
243 files changed, 50670 insertions, 27089 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h
index 21c2f86ce8..4d7dde04e1 100644
--- a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h
+++ b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h
@@ -10,6 +10,11 @@
#define LIBGLESV2_BINARYSTREAM_H_
#include "common/angleutils.h"
+#include "common/mathutil.h"
+
+#include <cstddef>
+#include <string>
+#include <vector>
namespace gl
{
@@ -25,42 +30,49 @@ class BinaryInputStream
mLength = length;
}
- template <typename T>
- void read(T *v, size_t num)
+ // readInt will generate an error for bool types
+ template <class IntT>
+ IntT readInt()
{
- union
- {
- T dummy; // Compilation error for non-trivial types
- } dummy;
- (void) dummy;
+ int value;
+ read(&value);
+ return static_cast<IntT>(value);
+ }
- if (mError)
- {
- return;
- }
+ template <class IntT>
+ void readInt(IntT *outValue)
+ {
+ *outValue = readInt<IntT>();
+ }
- size_t length = num * sizeof(T);
+ bool readBool()
+ {
+ int value;
+ read(&value);
+ return (value > 0);
+ }
- if (mOffset + length > mLength)
- {
- mError = true;
- return;
- }
+ void readBool(bool *outValue)
+ {
+ *outValue = readBool();
+ }
- memcpy(v, mData + mOffset, length);
- mOffset += length;
+ void readBytes(unsigned char outArray[], size_t count)
+ {
+ read<unsigned char>(outArray, count);
}
- template <typename T>
- void read(T * v)
+ std::string readString()
{
- read(v, 1);
+ std::string outString;
+ readString(&outString);
+ return outString;
}
- void read(std::string *v)
+ void readString(std::string *v)
{
size_t length;
- read(&length);
+ readInt(&length);
if (mError)
{
@@ -109,6 +121,30 @@ class BinaryInputStream
size_t mOffset;
const char *mData;
size_t mLength;
+
+ template <typename T>
+ void read(T *v, size_t num)
+ {
+ META_ASSERT(std::is_fundamental<T>::value);
+
+ size_t length = num * sizeof(T);
+
+ if (mOffset + length > mLength)
+ {
+ mError = true;
+ return;
+ }
+
+ memcpy(v, mData + mOffset, length);
+ mOffset += length;
+ }
+
+ template <typename T>
+ void read(T *v)
+ {
+ read(v, 1);
+ }
+
};
class BinaryOutputStream
@@ -118,31 +154,24 @@ class BinaryOutputStream
{
}
- template <typename T>
- void write(const T *v, size_t num)
+ // writeInt also handles bool types
+ template <class IntT>
+ void writeInt(IntT param)
{
- union
- {
- T dummy; // Compilation error for non-trivial types
- } dummy;
- (void) dummy;
-
- const char *asBytes = reinterpret_cast<const char*>(v);
- mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T));
+ ASSERT(rx::IsIntegerCastSafe<int>(param));
+ int intValue = static_cast<int>(param);
+ write(&intValue, 1);
}
- template <typename T>
- void write(const T &v)
+ void writeString(const std::string &v)
{
- write(&v, 1);
+ writeInt(v.length());
+ write(v.c_str(), v.length());
}
- void write(const std::string &v)
+ void writeBytes(const unsigned char *bytes, size_t count)
{
- size_t length = v.length();
- write(length);
-
- write(v.c_str(), length);
+ write(bytes, count);
}
size_t length() const
@@ -158,6 +187,15 @@ class BinaryOutputStream
private:
DISALLOW_COPY_AND_ASSIGN(BinaryOutputStream);
std::vector<char> mData;
+
+ template <typename T>
+ void write(const T *v, size_t num)
+ {
+ META_ASSERT(std::is_fundamental<T>::value);
+ const char *asBytes = reinterpret_cast<const char*>(v);
+ mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T));
+ }
+
};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp
index c007d5d9e9..3b2a1a912a 100644
--- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp
@@ -1,6 +1,5 @@
-#include "precompiled.h"
//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -10,117 +9,120 @@
// [OpenGL ES 2.0.24] section 2.9 page 21.
#include "libGLESv2/Buffer.h"
-
-#include "libGLESv2/renderer/VertexBuffer.h"
-#include "libGLESv2/renderer/IndexBuffer.h"
-#include "libGLESv2/renderer/BufferStorage.h"
+#include "libGLESv2/renderer/BufferImpl.h"
#include "libGLESv2/renderer/Renderer.h"
namespace gl
{
-Buffer::Buffer(rx::Renderer *renderer, GLuint id) : RefCountObject(id)
+Buffer::Buffer(rx::BufferImpl *impl, GLuint id)
+ : RefCountObject(id),
+ mBuffer(impl),
+ mUsage(GL_DYNAMIC_DRAW),
+ mSize(0),
+ mAccessFlags(0),
+ mMapped(GL_FALSE),
+ mMapPointer(NULL),
+ mMapOffset(0),
+ mMapLength(0)
{
- mRenderer = renderer;
- mUsage = GL_DYNAMIC_DRAW;
-
- mBufferStorage = renderer->createBufferStorage();
- mStaticVertexBuffer = NULL;
- mStaticIndexBuffer = NULL;
- mUnmodifiedDataUse = 0;
}
Buffer::~Buffer()
{
- delete mBufferStorage;
- delete mStaticVertexBuffer;
- delete mStaticIndexBuffer;
+ SafeDelete(mBuffer);
}
-void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
+Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
{
- mBufferStorage->clear();
- mIndexRangeCache.clear();
- mBufferStorage->setData(data, size, 0);
+ gl::Error error = mBuffer->setData(data, size, usage);
+ if (error.isError())
+ {
+ return error;
+ }
+ mIndexRangeCache.clear();
mUsage = usage;
+ mSize = size;
- invalidateStaticData();
-
- if (usage == GL_STATIC_DRAW)
- {
- mStaticVertexBuffer = new rx::StaticVertexBufferInterface(mRenderer);
- mStaticIndexBuffer = new rx::StaticIndexBufferInterface(mRenderer);
- }
+ return error;
}
-void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
+Error Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
{
- mBufferStorage->setData(data, size, offset);
- mIndexRangeCache.invalidateRange(offset, size);
-
- if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0))
+ gl::Error error = mBuffer->setSubData(data, size, offset);
+ if (error.isError())
{
- invalidateStaticData();
+ return error;
}
- mUnmodifiedDataUse = 0;
-}
+ mIndexRangeCache.invalidateRange(offset, size);
-rx::BufferStorage *Buffer::getStorage() const
-{
- return mBufferStorage;
+ return error;
}
-unsigned int Buffer::size() const
+Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
{
- return mBufferStorage->getSize();
-}
+ gl::Error error = mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size);
+ if (error.isError())
+ {
+ return error;
+ }
-GLenum Buffer::usage() const
-{
- return mUsage;
-}
+ mIndexRangeCache.invalidateRange(destOffset, size);
-rx::StaticVertexBufferInterface *Buffer::getStaticVertexBuffer()
-{
- return mStaticVertexBuffer;
+ return error;
}
-rx::StaticIndexBufferInterface *Buffer::getStaticIndexBuffer()
+Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access)
{
- return mStaticIndexBuffer;
-}
+ ASSERT(!mMapped);
+ ASSERT(offset + length <= mSize);
-void Buffer::invalidateStaticData()
-{
- delete mStaticVertexBuffer;
- mStaticVertexBuffer = NULL;
+ Error error = mBuffer->map(offset, length, access, &mMapPointer);
+ if (error.isError())
+ {
+ mMapPointer = NULL;
+ return error;
+ }
- delete mStaticIndexBuffer;
- mStaticIndexBuffer = NULL;
+ mMapped = GL_TRUE;
+ mMapOffset = static_cast<GLint64>(offset);
+ mMapLength = static_cast<GLint64>(length);
+ mAccessFlags = static_cast<GLint>(access);
- mUnmodifiedDataUse = 0;
+ if ((access & GL_MAP_WRITE_BIT) > 0)
+ {
+ mIndexRangeCache.invalidateRange(offset, length);
+ }
+
+ return error;
}
-// Creates static buffers if sufficient used data has been left unmodified
-void Buffer::promoteStaticUsage(int dataSize)
+Error Buffer::unmap()
{
- if (!mStaticVertexBuffer && !mStaticIndexBuffer)
- {
- mUnmodifiedDataUse += dataSize;
+ ASSERT(mMapped);
- if (mUnmodifiedDataUse > 3 * mBufferStorage->getSize())
- {
- mStaticVertexBuffer = new rx::StaticVertexBufferInterface(mRenderer);
- mStaticIndexBuffer = new rx::StaticIndexBufferInterface(mRenderer);
- }
+ Error error = mBuffer->unmap();
+ if (error.isError())
+ {
+ return error;
}
+
+ mMapped = GL_FALSE;
+ mMapPointer = NULL;
+ mMapOffset = 0;
+ mMapLength = 0;
+ mAccessFlags = 0;
+
+ return error;
}
-rx::IndexRangeCache *Buffer::getIndexRangeCache()
+void Buffer::markTransformFeedbackUsage()
{
- return &mIndexRangeCache;
+ // TODO: Only used by the DX11 backend. Refactor to a more appropriate place.
+ mBuffer->markTransformFeedbackUsage();
+ mIndexRangeCache.clear();
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h
index 4048f4b906..35a6767502 100644
--- a/src/3rdparty/angle/src/libGLESv2/Buffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -11,6 +11,8 @@
#ifndef LIBGLESV2_BUFFER_H_
#define LIBGLESV2_BUFFER_H_
+#include "libGLESv2/Error.h"
+
#include "common/angleutils.h"
#include "common/RefCountObject.h"
#include "libGLESv2/renderer/IndexRangeCache.h"
@@ -18,9 +20,7 @@
namespace rx
{
class Renderer;
-class BufferStorage;
-class StaticIndexBufferInterface;
-class StaticVertexBufferInterface;
+class BufferImpl;
};
namespace gl
@@ -29,38 +29,45 @@ namespace gl
class Buffer : public RefCountObject
{
public:
- Buffer(rx::Renderer *renderer, GLuint id);
+ Buffer(rx::BufferImpl *impl, GLuint id);
virtual ~Buffer();
- void bufferData(const void *data, GLsizeiptr size, GLenum usage);
- void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
+ Error bufferData(const void *data, GLsizeiptr size, GLenum usage);
+ Error bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
+ Error copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
+ Error mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access);
+ Error unmap();
- GLenum usage() const;
+ GLenum getUsage() const { return mUsage; }
+ GLint getAccessFlags() const { return mAccessFlags; }
+ 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; }
- rx::BufferStorage *getStorage() const;
- unsigned int size() const;
+ rx::BufferImpl *getImplementation() const { return mBuffer; }
- rx::StaticVertexBufferInterface *getStaticVertexBuffer();
- rx::StaticIndexBufferInterface *getStaticIndexBuffer();
- void invalidateStaticData();
- void promoteStaticUsage(int dataSize);
+ void markTransformFeedbackUsage();
- rx::IndexRangeCache *getIndexRangeCache();
+ rx::IndexRangeCache *getIndexRangeCache() { return &mIndexRangeCache; }
+ const rx::IndexRangeCache *getIndexRangeCache() const { return &mIndexRangeCache; }
private:
DISALLOW_COPY_AND_ASSIGN(Buffer);
- rx::Renderer *mRenderer;
- GLenum mUsage;
+ rx::BufferImpl *mBuffer;
- rx::BufferStorage *mBufferStorage;
+ GLenum mUsage;
+ GLint64 mSize;
+ GLint mAccessFlags;
+ GLboolean mMapped;
+ GLvoid *mMapPointer;
+ GLint64 mMapOffset;
+ GLint64 mMapLength;
rx::IndexRangeCache mIndexRangeCache;
-
- rx::StaticVertexBufferInterface *mStaticVertexBuffer;
- rx::StaticIndexBufferInterface *mStaticIndexBuffer;
- unsigned int mUnmodifiedDataUse;
};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.cpp b/src/3rdparty/angle/src/libGLESv2/Caps.cpp
new file mode 100644
index 0000000000..983800c0e6
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/Caps.cpp
@@ -0,0 +1,425 @@
+//
+// 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 "libGLESv2/Caps.h"
+#include "common/debug.h"
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+#include <algorithm>
+#include <sstream>
+
+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.insert(std::make_pair(internalFormat, caps));
+}
+
+void TextureCapsMap::remove(GLenum internalFormat)
+{
+ InternalFormatToCapsMap::iterator i = mCapsMap.find(internalFormat);
+ if (i != mCapsMap.end())
+ {
+ mCapsMap.erase(i);
+ }
+}
+
+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),
+ textureHalfFloat(false),
+ textureHalfFloatLinear(false),
+ textureFloat(false),
+ textureFloatLinear(false),
+ textureRG(false),
+ textureCompressionDXT1(false),
+ textureCompressionDXT3(false),
+ textureCompressionDXT5(false),
+ depthTextures(false),
+ textureNPOT(false),
+ drawBuffers(false),
+ textureStorage(false),
+ textureFilterAnisotropic(false),
+ maxTextureAnisotropy(false),
+ occlusionQueryBoolean(false),
+ fence(false),
+ timerQuery(false),
+ robustness(false),
+ blendMinMax(false),
+ framebufferBlit(false),
+ framebufferMultisample(false),
+ instancedArrays(false),
+ packReverseRowOrder(false),
+ standardDerivatives(false),
+ shaderTextureLOD(false),
+ fragDepth(false),
+ textureUsage(false),
+ translatedShaderSource(false),
+ colorBufferFloat(false)
+{
+}
+
+static void InsertExtensionString(const std::string &extension, bool supported, std::vector<std::string> *extensionVector)
+{
+ if (supported)
+ {
+ extensionVector->push_back(extension);
+ }
+}
+
+std::vector<std::string> Extensions::getStrings() const
+{
+ std::vector<std::string> extensionStrings;
+
+ // | Extension name | Supported flag | Output vector |
+ InsertExtensionString("GL_OES_element_index_uint", elementIndexUint, &extensionStrings);
+ InsertExtensionString("GL_OES_packed_depth_stencil", packedDepthStencil, &extensionStrings);
+ InsertExtensionString("GL_OES_get_program_binary", getProgramBinary, &extensionStrings);
+ InsertExtensionString("GL_OES_rgb8_rgba8", rgb8rgba8, &extensionStrings);
+ InsertExtensionString("GL_EXT_texture_format_BGRA8888", textureFormatBGRA8888, &extensionStrings);
+ InsertExtensionString("GL_EXT_read_format_bgra", readFormatBGRA, &extensionStrings);
+ InsertExtensionString("GL_NV_pixel_buffer_object", pixelBufferObject, &extensionStrings);
+ InsertExtensionString("GL_OES_mapbuffer", mapBuffer, &extensionStrings);
+ InsertExtensionString("GL_EXT_map_buffer_range", mapBufferRange, &extensionStrings);
+ InsertExtensionString("GL_OES_texture_half_float", textureHalfFloat, &extensionStrings);
+ InsertExtensionString("GL_OES_texture_half_float_linear", textureHalfFloatLinear, &extensionStrings);
+ InsertExtensionString("GL_OES_texture_float", textureFloat, &extensionStrings);
+ InsertExtensionString("GL_OES_texture_float_linear", textureFloatLinear, &extensionStrings);
+ InsertExtensionString("GL_EXT_texture_rg", textureRG, &extensionStrings);
+ InsertExtensionString("GL_EXT_texture_compression_dxt1", textureCompressionDXT1, &extensionStrings);
+ InsertExtensionString("GL_ANGLE_texture_compression_dxt3", textureCompressionDXT3, &extensionStrings);
+ InsertExtensionString("GL_ANGLE_texture_compression_dxt5", textureCompressionDXT5, &extensionStrings);
+ InsertExtensionString("GL_EXT_sRGB", sRGB, &extensionStrings);
+ InsertExtensionString("GL_ANGLE_depth_texture", depthTextures, &extensionStrings);
+ InsertExtensionString("GL_EXT_texture_storage", textureStorage, &extensionStrings);
+ InsertExtensionString("GL_OES_texture_npot", textureNPOT, &extensionStrings);
+ InsertExtensionString("GL_EXT_draw_buffers", drawBuffers, &extensionStrings);
+ InsertExtensionString("GL_EXT_texture_filter_anisotropic", textureFilterAnisotropic, &extensionStrings);
+ InsertExtensionString("GL_EXT_occlusion_query_boolean", occlusionQueryBoolean, &extensionStrings);
+ InsertExtensionString("GL_NV_fence", fence, &extensionStrings);
+ InsertExtensionString("GL_ANGLE_timer_query", timerQuery, &extensionStrings);
+ InsertExtensionString("GL_EXT_robustness", robustness, &extensionStrings);
+ InsertExtensionString("GL_EXT_blend_minmax", blendMinMax, &extensionStrings);
+ InsertExtensionString("GL_ANGLE_framebuffer_blit", framebufferBlit, &extensionStrings);
+ InsertExtensionString("GL_ANGLE_framebuffer_multisample", framebufferMultisample, &extensionStrings);
+ InsertExtensionString("GL_ANGLE_instanced_arrays", instancedArrays, &extensionStrings);
+ InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings);
+ InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings);
+ InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings);
+ InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings);
+ InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings);
+ InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings);
+ InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings);
+
+ return extensionStrings;
+}
+
+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;
+}
+
+// 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_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 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 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_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_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);
+}
+
+void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
+{
+ rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps);
+ textureFormatBGRA8888 = DetermineBGRA8TextureSupport(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);
+ sRGB = DetermineSRGBTextureSupport(textureCaps);
+ depthTextures = DetermineDepthTextureSupport(textureCaps);
+ colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps);
+}
+
+Caps::Caps()
+ : maxElementIndex(0),
+ max3DTextureSize(0),
+ max2DTextureSize(0),
+ maxArrayTextureLayers(0),
+ maxLODBias(0),
+ maxCubeMapTextureSize(0),
+ maxRenderbufferSize(0),
+ maxDrawBuffers(0),
+ maxColorAttachments(0),
+ maxViewportWidth(0),
+ maxViewportHeight(0),
+ minAliasedPointSize(0),
+ maxAliasedPointSize(0),
+ minAliasedLineWidth(0),
+ // Table 6.29
+ maxElementsIndices(0),
+ maxElementsVertices(0),
+ maxServerWaitTimeout(0),
+ // Table 6.31
+ maxVertexAttributes(0),
+ maxVertexUniformComponents(0),
+ maxVertexUniformVectors(0),
+ maxVertexUniformBlocks(0),
+ maxVertexOutputComponents(0),
+ maxVertexTextureImageUnits(0),
+ // Table 6.32
+ maxFragmentUniformComponents(0),
+ maxFragmentUniformVectors(0),
+ maxFragmentUniformBlocks(0),
+ maxFragmentInputComponents(0),
+ maxTextureImageUnits(0),
+ minProgramTexelOffset(0),
+ maxProgramTexelOffset(0),
+
+ maxUniformBufferBindings(0),
+ maxUniformBlockSize(0),
+ uniformBufferOffsetAlignment(0),
+ maxCombinedUniformBlocks(0),
+ maxCombinedVertexUniformComponents(0),
+ maxCombinedFragmentUniformComponents(0),
+ maxVaryingComponents(0),
+ maxVaryingVectors(0),
+ maxCombinedTextureImageUnits(0),
+
+ maxTransformFeedbackInterleavedComponents(0),
+ maxTransformFeedbackSeparateAttributes(0),
+ maxTransformFeedbackSeparateComponents(0)
+{
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.h b/src/3rdparty/angle/src/libGLESv2/Caps.h
new file mode 100644
index 0000000000..a00e554176
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/Caps.h
@@ -0,0 +1,273 @@
+#ifndef LIBGLESV2_CAPS_H
+#define LIBGLESV2_CAPS_H
+
+//
+// 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 "angle_gl.h"
+
+#include <set>
+#include <unordered_map>
+#include <vector>
+#include <string>
+
+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;
+
+ 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::unordered_map<GLenum, TextureCaps>::const_iterator const_iterator;
+
+ void insert(GLenum internalFormat, const TextureCaps &caps);
+ void remove(GLenum internalFormat);
+
+ const TextureCaps &get(GLenum internalFormat) const;
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ size_t size() const;
+
+ private:
+ typedef std::unordered_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_rgb8_rgba8
+ // GL_EXT_texture_format_BGRA8888
+ // 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_EXT_sRGB
+ // GL_ANGLE_depth_texture
+ // GL_EXT_color_buffer_float
+ 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_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_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_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_robustness
+ bool robustness;
+
+ // GL_EXT_blend_minmax
+ bool blendMinMax;
+
+ // GL_ANGLE_framebuffer_blit
+ bool framebufferBlit;
+
+ // GL_ANGLE_framebuffer_multisample
+ bool framebufferMultisample;
+ GLuint maxSamples;
+
+ // 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_frag_depth
+ bool fragDepth;
+
+ // GL_ANGLE_texture_usage
+ bool textureUsage;
+
+ // GL_ANGLE_translated_shader_source
+ bool translatedShaderSource;
+
+ // ES3 Extension support
+
+ // GL_EXT_color_buffer_float
+ bool colorBufferFloat;
+};
+
+struct Caps
+{
+ Caps();
+
+ // Table 6.28, implementation dependent values
+ GLuint64 maxElementIndex;
+ GLuint max3DTextureSize;
+ GLuint max2DTextureSize;
+ GLuint maxArrayTextureLayers;
+ GLfloat maxLODBias;
+ GLuint maxCubeMapTextureSize;
+ GLuint maxRenderbufferSize;
+ GLuint maxDrawBuffers;
+ GLuint maxColorAttachments;
+ GLuint maxViewportWidth;
+ GLuint maxViewportHeight;
+ GLfloat minAliasedPointSize;
+ GLfloat maxAliasedPointSize;
+ GLfloat minAliasedLineWidth;
+ GLfloat maxAliasedLineWidth;
+
+ // Table 6.29, implementation dependent values (cont.)
+ GLuint maxElementsIndices;
+ GLuint maxElementsVertices;
+ std::vector<GLenum> compressedTextureFormats;
+ std::vector<GLenum> programBinaryFormats;
+ std::vector<GLenum> shaderBinaryFormats;
+ GLuint64 maxServerWaitTimeout;
+
+ // Table 6.31, implementation dependent vertex shader limits
+ GLuint maxVertexAttributes;
+ GLuint maxVertexUniformComponents;
+ GLuint maxVertexUniformVectors;
+ GLuint maxVertexUniformBlocks;
+ GLuint maxVertexOutputComponents;
+ GLuint maxVertexTextureImageUnits;
+
+ // Table 6.32, implementation dependent fragment shader limits
+ GLuint maxFragmentUniformComponents;
+ GLuint maxFragmentUniformVectors;
+ GLuint maxFragmentUniformBlocks;
+ GLuint maxFragmentInputComponents;
+ GLuint maxTextureImageUnits;
+ GLint minProgramTexelOffset;
+ GLint maxProgramTexelOffset;
+
+ // Table 6.33, implementation dependent aggregate shader limits
+ GLuint maxUniformBufferBindings;
+ GLuint64 maxUniformBlockSize;
+ GLuint uniformBufferOffsetAlignment;
+ GLuint maxCombinedUniformBlocks;
+ GLuint64 maxCombinedVertexUniformComponents;
+ GLuint64 maxCombinedFragmentUniformComponents;
+ GLuint maxVaryingComponents;
+ GLuint maxVaryingVectors;
+ GLuint maxCombinedTextureImageUnits;
+
+ // Table 6.34, implementation dependent transform feedback limits
+ GLuint maxTransformFeedbackInterleavedComponents;
+ GLuint maxTransformFeedbackSeparateAttributes;
+ GLuint maxTransformFeedbackSeparateComponents;
+};
+
+}
+
+#endif // LIBGLESV2_CAPS_H
diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp
index e651785aed..5342de1331 100644
--- a/src/3rdparty/angle/src/libGLESv2/Context.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp
@@ -1,6 +1,5 @@
-#include "precompiled.h"
//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -11,116 +10,45 @@
#include "libGLESv2/Context.h"
#include "libGLESv2/main.h"
-#include "libGLESv2/utilities.h"
+#include "common/utilities.h"
+#include "common/platform.h"
+#include "libGLESv2/formatutils.h"
#include "libGLESv2/Buffer.h"
#include "libGLESv2/Fence.h"
#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
#include "libGLESv2/Renderbuffer.h"
#include "libGLESv2/Program.h"
#include "libGLESv2/ProgramBinary.h"
#include "libGLESv2/Query.h"
#include "libGLESv2/Texture.h"
#include "libGLESv2/ResourceManager.h"
-#include "libGLESv2/renderer/IndexDataManager.h"
-#include "libGLESv2/renderer/RenderTarget.h"
+#include "libGLESv2/renderer/d3d/IndexDataManager.h"
#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/VertexArray.h"
+#include "libGLESv2/Sampler.h"
+#include "libGLESv2/validationES.h"
+#include "libGLESv2/TransformFeedback.h"
#include "libEGL/Surface.h"
-#undef near
-#undef far
+#include <sstream>
+#include <iterator>
namespace gl
{
-static const char* makeStaticString(const std::string& str)
-{
- static std::set<std::string> strings;
- std::set<std::string>::iterator it = strings.find(str);
- if (it != strings.end())
- return it->c_str();
-
- return strings.insert(str).first->c_str();
-}
-Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) : mRenderer(renderer)
+Context::Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
+ : mRenderer(renderer)
{
ASSERT(robustAccess == false); // Unimplemented
- mFenceHandleAllocator.setBaseHandle(0);
-
- setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
- mState.depthClearValue = 1.0f;
- mState.stencilClearValue = 0;
-
- mState.rasterizer.cullFace = false;
- mState.rasterizer.cullMode = GL_BACK;
- mState.rasterizer.frontFace = GL_CCW;
- mState.rasterizer.polygonOffsetFill = false;
- mState.rasterizer.polygonOffsetFactor = 0.0f;
- mState.rasterizer.polygonOffsetUnits = 0.0f;
- mState.rasterizer.pointDrawMode = false;
- mState.rasterizer.multiSample = false;
- mState.scissorTest = false;
- mState.scissor.x = 0;
- mState.scissor.y = 0;
- mState.scissor.width = 0;
- mState.scissor.height = 0;
-
- mState.blend.blend = false;
- mState.blend.sourceBlendRGB = GL_ONE;
- mState.blend.sourceBlendAlpha = GL_ONE;
- mState.blend.destBlendRGB = GL_ZERO;
- mState.blend.destBlendAlpha = GL_ZERO;
- mState.blend.blendEquationRGB = GL_FUNC_ADD;
- mState.blend.blendEquationAlpha = GL_FUNC_ADD;
- mState.blend.sampleAlphaToCoverage = false;
- mState.blend.dither = true;
-
- mState.blendColor.red = 0;
- mState.blendColor.green = 0;
- mState.blendColor.blue = 0;
- mState.blendColor.alpha = 0;
-
- mState.depthStencil.depthTest = false;
- mState.depthStencil.depthFunc = GL_LESS;
- mState.depthStencil.depthMask = true;
- mState.depthStencil.stencilTest = false;
- mState.depthStencil.stencilFunc = GL_ALWAYS;
- mState.depthStencil.stencilMask = -1;
- mState.depthStencil.stencilWritemask = -1;
- mState.depthStencil.stencilBackFunc = GL_ALWAYS;
- mState.depthStencil.stencilBackMask = - 1;
- mState.depthStencil.stencilBackWritemask = -1;
- mState.depthStencil.stencilFail = GL_KEEP;
- mState.depthStencil.stencilPassDepthFail = GL_KEEP;
- mState.depthStencil.stencilPassDepthPass = GL_KEEP;
- mState.depthStencil.stencilBackFail = GL_KEEP;
- mState.depthStencil.stencilBackPassDepthFail = GL_KEEP;
- mState.depthStencil.stencilBackPassDepthPass = GL_KEEP;
-
- mState.stencilRef = 0;
- mState.stencilBackRef = 0;
-
- mState.sampleCoverage = false;
- mState.sampleCoverageValue = 1.0f;
- mState.sampleCoverageInvert = false;
- mState.generateMipmapHint = GL_DONT_CARE;
- mState.fragmentShaderDerivativeHint = GL_DONT_CARE;
-
- mState.lineWidth = 1.0f;
-
- mState.viewport.x = 0;
- mState.viewport.y = 0;
- mState.viewport.width = 0;
- mState.viewport.height = 0;
- mState.zNear = 0.0f;
- mState.zFar = 1.0f;
-
- mState.blend.colorMaskRed = true;
- mState.blend.colorMaskGreen = true;
- mState.blend.colorMaskBlue = true;
- mState.blend.colorMaskAlpha = true;
+ initCaps(clientVersion);
+ mState.initialize(mCaps, clientVersion);
+
+ mClientVersion = clientVersion;
+
+ mFenceNVHandleAllocator.setBaseHandle(0);
if (shareContext != NULL)
{
@@ -138,33 +66,53 @@ Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool n
// In order that access to these initial textures not be lost, they are treated as texture
// objects all of whose names are 0.
- mTexture2DZero.set(new Texture2D(mRenderer, 0));
- mTextureCubeMapZero.set(new TextureCubeMap(mRenderer, 0));
+ mZeroTextures[GL_TEXTURE_2D].set(new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0));
+ bindTexture(GL_TEXTURE_2D, 0);
- mState.activeSampler = 0;
+ mZeroTextures[GL_TEXTURE_CUBE_MAP].set(new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0));
+ bindTexture(GL_TEXTURE_CUBE_MAP, 0);
+
+ if (mClientVersion >= 3)
+ {
+ // TODO: These could also be enabled via extension
+ mZeroTextures[GL_TEXTURE_3D].set(new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0));
+ bindTexture(GL_TEXTURE_3D, 0);
+
+ mZeroTextures[GL_TEXTURE_2D_ARRAY].set(new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0));
+ bindTexture(GL_TEXTURE_2D_ARRAY, 0);
+ }
+
+ bindVertexArray(0);
bindArrayBuffer(0);
bindElementArrayBuffer(0);
- bindTextureCubeMap(0);
- bindTexture2D(0);
+
bindReadFramebuffer(0);
bindDrawFramebuffer(0);
bindRenderbuffer(0);
- mState.currentProgram = 0;
- mCurrentProgramBinary.set(NULL);
+ bindGenericUniformBuffer(0);
+ for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++)
+ {
+ bindIndexedUniformBuffer(0, i, 0, -1);
+ }
- mState.packAlignment = 4;
- mState.unpackAlignment = 4;
- mState.packReverseRowOrder = false;
+ bindGenericTransformFeedbackBuffer(0);
+ for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
+ {
+ bindIndexedTransformFeedbackBuffer(0, i, 0, -1);
+ }
- mExtensionString = NULL;
- mRendererString = NULL;
+ bindCopyReadBuffer(0);
+ bindCopyWriteBuffer(0);
+ bindPixelPackBuffer(0);
+ bindPixelUnpackBuffer(0);
- mInvalidEnum = false;
- mInvalidValue = false;
- mInvalidOperation = false;
- mOutOfMemory = false;
- mInvalidFramebufferOperation = false;
+ // [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
+ mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0));
+ bindTransformFeedback(0);
mHasBeenCurrent = false;
mContextLost = false;
@@ -172,36 +120,31 @@ Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool n
mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
mRobustAccess = robustAccess;
- mSupportsBGRATextures = false;
- mSupportsDXT1Textures = false;
- mSupportsDXT3Textures = false;
- mSupportsDXT5Textures = false;
- mSupportsEventQueries = false;
- mSupportsOcclusionQueries = false;
- mNumCompressedTextureFormats = 0;
+ mState.setContext(this);
}
Context::~Context()
{
- if (mState.currentProgram != 0)
+ GLuint currentProgram = mState.getCurrentProgramId();
+ if (currentProgram != 0)
{
- Program *programObject = mResourceManager->getProgram(mState.currentProgram);
+ Program *programObject = mResourceManager->getProgram(currentProgram);
if (programObject)
{
programObject->release();
}
- mState.currentProgram = 0;
+ currentProgram = 0;
}
- mCurrentProgramBinary.set(NULL);
+ mState.setCurrentProgram(0, NULL);
while (!mFramebufferMap.empty())
{
deleteFramebuffer(mFramebufferMap.begin()->first);
}
- while (!mFenceMap.empty())
+ while (!mFenceNVMap.empty())
{
- deleteFence(mFenceMap.begin()->first);
+ deleteFenceNV(mFenceNVMap.begin()->first);
}
while (!mQueryMap.empty())
@@ -209,35 +152,28 @@ Context::~Context()
deleteQuery(mQueryMap.begin()->first);
}
- for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
+ while (!mVertexArrayMap.empty())
{
- for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
- {
- mState.samplerTexture[type][sampler].set(NULL);
- }
+ deleteVertexArray(mVertexArrayMap.begin()->first);
}
- for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
+ mTransformFeedbackZero.set(NULL);
+ while (!mTransformFeedbackMap.empty())
{
- mIncompleteTextures[type].set(NULL);
+ deleteTransformFeedback(mTransformFeedbackMap.begin()->first);
}
- for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ for (TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); i++)
{
- mState.vertexAttribute[i].mBoundBuffer.set(NULL);
+ i->second.set(NULL);
}
+ mIncompleteTextures.clear();
- for (int i = 0; i < QUERY_TYPE_COUNT; i++)
+ for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++)
{
- mState.activeQuery[i].set(NULL);
+ i->second.set(NULL);
}
-
- mState.arrayBuffer.set(NULL);
- mState.elementArrayBuffer.set(NULL);
- mState.renderbuffer.set(NULL);
-
- mTexture2DZero.set(NULL);
- mTextureCubeMapZero.set(NULL);
+ mZeroTextures.clear();
mResourceManager->release();
}
@@ -246,62 +182,11 @@ void Context::makeCurrent(egl::Surface *surface)
{
if (!mHasBeenCurrent)
{
- mMajorShaderModel = mRenderer->getMajorShaderModel();
- mMaximumPointSize = mRenderer->getMaxPointSize();
- mSupportsVertexTexture = mRenderer->getVertexTextureSupport();
- mSupportsNonPower2Texture = mRenderer->getNonPower2TextureSupport();
- mSupportsInstancing = mRenderer->getInstancingSupport();
-
- mMaxViewportDimension = mRenderer->getMaxViewportDimension();
- mMaxTextureDimension = std::min(std::min(mRenderer->getMaxTextureWidth(), mRenderer->getMaxTextureHeight()),
- (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
- mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
- mMaxRenderbufferDimension = mMaxTextureDimension;
- mMaxTextureLevel = log2(mMaxTextureDimension) + 1;
- mMaxTextureAnisotropy = mRenderer->getTextureMaxAnisotropy();
- TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d, MaxTextureAnisotropy=%f",
- mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel, mMaxTextureAnisotropy);
-
- mSupportsEventQueries = mRenderer->getEventQuerySupport();
- mSupportsOcclusionQueries = mRenderer->getOcclusionQuerySupport();
- mSupportsBGRATextures = mRenderer->getBGRATextureSupport();
- mSupportsDXT1Textures = mRenderer->getDXT1TextureSupport();
- mSupportsDXT3Textures = mRenderer->getDXT3TextureSupport();
- mSupportsDXT5Textures = mRenderer->getDXT5TextureSupport();
- mSupportsFloat32Textures = mRenderer->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures);
- mSupportsFloat16Textures = mRenderer->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures);
- mSupportsLuminanceTextures = mRenderer->getLuminanceTextureSupport();
- mSupportsLuminanceAlphaTextures = mRenderer->getLuminanceAlphaTextureSupport();
- mSupportsDepthTextures = mRenderer->getDepthTextureSupport();
- mSupportsTextureFilterAnisotropy = mRenderer->getTextureFilterAnisotropySupport();
- mSupports32bitIndices = mRenderer->get32BitIndexSupport();
-
- mNumCompressedTextureFormats = 0;
- if (supportsDXT1Textures())
- {
- mNumCompressedTextureFormats += 2;
- }
- if (supportsDXT3Textures())
- {
- mNumCompressedTextureFormats += 1;
- }
- if (supportsDXT5Textures())
- {
- mNumCompressedTextureFormats += 1;
- }
-
- initExtensionString();
initRendererString();
+ initExtensionStrings();
- mState.viewport.x = 0;
- mState.viewport.y = 0;
- mState.viewport.width = surface->getWidth();
- mState.viewport.height = surface->getHeight();
-
- mState.scissor.x = 0;
- mState.scissor.y = 0;
- mState.scissor.width = surface->getWidth();
- mState.scissor.height = surface->getHeight();
+ mState.setViewportParams(0, 0, surface->getWidth(), surface->getHeight());
+ mState.setScissorParams(0, 0, surface->getWidth(), surface->getHeight());
mHasBeenCurrent = true;
}
@@ -314,6 +199,9 @@ void Context::makeCurrent(egl::Surface *surface)
Framebuffer *framebufferZero = new DefaultFramebuffer(mRenderer, colorbufferZero, depthStencilbufferZero);
setFramebufferZero(framebufferZero);
+
+ // Store the current client version in the renderer
+ mRenderer->setCurrentClientVersion(mClientVersion);
}
// NOTE: this function should not assume that this context is current!
@@ -329,608 +217,425 @@ bool Context::isContextLost()
return mContextLost;
}
-void Context::setClearColor(float red, float green, float blue, float alpha)
+GLuint Context::createBuffer()
{
- mState.colorClearValue.red = red;
- mState.colorClearValue.green = green;
- mState.colorClearValue.blue = blue;
- mState.colorClearValue.alpha = alpha;
+ return mResourceManager->createBuffer();
}
-void Context::setClearDepth(float depth)
+GLuint Context::createProgram()
{
- mState.depthClearValue = depth;
+ return mResourceManager->createProgram();
}
-void Context::setClearStencil(int stencil)
+GLuint Context::createShader(GLenum type)
{
- mState.stencilClearValue = stencil;
+ return mResourceManager->createShader(type);
}
-void Context::setCullFace(bool enabled)
+GLuint Context::createTexture()
{
- mState.rasterizer.cullFace = enabled;
+ return mResourceManager->createTexture();
}
-bool Context::isCullFaceEnabled() const
+GLuint Context::createRenderbuffer()
{
- return mState.rasterizer.cullFace;
+ return mResourceManager->createRenderbuffer();
}
-void Context::setCullMode(GLenum mode)
+GLsync Context::createFenceSync(GLenum condition)
{
- mState.rasterizer.cullMode = mode;
-}
+ GLuint handle = mResourceManager->createFenceSync();
-void Context::setFrontFace(GLenum front)
-{
- mState.rasterizer.frontFace = front;
-}
+ gl::FenceSync *fenceSync = mResourceManager->getFenceSync(handle);
+ ASSERT(fenceSync);
-void Context::setDepthTest(bool enabled)
-{
- mState.depthStencil.depthTest = enabled;
-}
+ fenceSync->set(condition);
-bool Context::isDepthTestEnabled() const
-{
- return mState.depthStencil.depthTest;
+ return reinterpret_cast<GLsync>(handle);
}
-void Context::setDepthFunc(GLenum depthFunc)
+GLuint Context::createVertexArray()
{
- mState.depthStencil.depthFunc = depthFunc;
-}
+ GLuint handle = mVertexArrayHandleAllocator.allocate();
-void Context::setDepthRange(float zNear, float zFar)
-{
- mState.zNear = zNear;
- mState.zFar = zFar;
+ // Although the spec states VAO state is not initialized until the object is bound,
+ // we create it immediately. The resulting behaviour is transparent to the application,
+ // since it's not currently possible to access the state until the object is bound.
+ VertexArray *vertexArray = new VertexArray(mRenderer->createVertexArray(), handle, MAX_VERTEX_ATTRIBS);
+ mVertexArrayMap[handle] = vertexArray;
+ return handle;
}
-void Context::setBlend(bool enabled)
+GLuint Context::createSampler()
{
- mState.blend.blend = enabled;
+ return mResourceManager->createSampler();
}
-bool Context::isBlendEnabled() const
+GLuint Context::createTransformFeedback()
{
- return mState.blend.blend;
+ GLuint handle = mTransformFeedbackAllocator.allocate();
+ TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle);
+ transformFeedback->addRef();
+ mTransformFeedbackMap[handle] = transformFeedback;
+ return handle;
}
-void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
+// Returns an unused framebuffer name
+GLuint Context::createFramebuffer()
{
- mState.blend.sourceBlendRGB = sourceRGB;
- mState.blend.destBlendRGB = destRGB;
- mState.blend.sourceBlendAlpha = sourceAlpha;
- mState.blend.destBlendAlpha = destAlpha;
-}
+ GLuint handle = mFramebufferHandleAllocator.allocate();
-void Context::setBlendColor(float red, float green, float blue, float alpha)
-{
- mState.blendColor.red = red;
- mState.blendColor.green = green;
- mState.blendColor.blue = blue;
- mState.blendColor.alpha = alpha;
-}
+ mFramebufferMap[handle] = NULL;
-void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
-{
- mState.blend.blendEquationRGB = rgbEquation;
- mState.blend.blendEquationAlpha = alphaEquation;
+ return handle;
}
-void Context::setStencilTest(bool enabled)
+GLuint Context::createFenceNV()
{
- mState.depthStencil.stencilTest = enabled;
-}
+ GLuint handle = mFenceNVHandleAllocator.allocate();
-bool Context::isStencilTestEnabled() const
-{
- return mState.depthStencil.stencilTest;
-}
+ mFenceNVMap[handle] = new FenceNV(mRenderer);
-void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
-{
- mState.depthStencil.stencilFunc = stencilFunc;
- mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
- mState.depthStencil.stencilMask = stencilMask;
+ return handle;
}
-void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
+// Returns an unused query name
+GLuint Context::createQuery()
{
- mState.depthStencil.stencilBackFunc = stencilBackFunc;
- mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
- mState.depthStencil.stencilBackMask = stencilBackMask;
-}
+ GLuint handle = mQueryHandleAllocator.allocate();
-void Context::setStencilWritemask(GLuint stencilWritemask)
-{
- mState.depthStencil.stencilWritemask = stencilWritemask;
-}
+ mQueryMap[handle] = NULL;
-void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
-{
- mState.depthStencil.stencilBackWritemask = stencilBackWritemask;
+ return handle;
}
-void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
+void Context::deleteBuffer(GLuint buffer)
{
- mState.depthStencil.stencilFail = stencilFail;
- mState.depthStencil.stencilPassDepthFail = stencilPassDepthFail;
- mState.depthStencil.stencilPassDepthPass = stencilPassDepthPass;
-}
+ if (mResourceManager->getBuffer(buffer))
+ {
+ detachBuffer(buffer);
+ }
-void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
-{
- mState.depthStencil.stencilBackFail = stencilBackFail;
- mState.depthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail;
- mState.depthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass;
+ mResourceManager->deleteBuffer(buffer);
}
-void Context::setPolygonOffsetFill(bool enabled)
+void Context::deleteShader(GLuint shader)
{
- mState.rasterizer.polygonOffsetFill = enabled;
+ mResourceManager->deleteShader(shader);
}
-bool Context::isPolygonOffsetFillEnabled() const
+void Context::deleteProgram(GLuint program)
{
- return mState.rasterizer.polygonOffsetFill;
+ mResourceManager->deleteProgram(program);
}
-void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
+void Context::deleteTexture(GLuint texture)
{
- // An application can pass NaN values here, so handle this gracefully
- mState.rasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor;
- mState.rasterizer.polygonOffsetUnits = units != units ? 0.0f : units;
-}
+ if (mResourceManager->getTexture(texture))
+ {
+ detachTexture(texture);
+ }
-void Context::setSampleAlphaToCoverage(bool enabled)
-{
- mState.blend.sampleAlphaToCoverage = enabled;
+ mResourceManager->deleteTexture(texture);
}
-bool Context::isSampleAlphaToCoverageEnabled() const
+void Context::deleteRenderbuffer(GLuint renderbuffer)
{
- return mState.blend.sampleAlphaToCoverage;
-}
+ if (mResourceManager->getRenderbuffer(renderbuffer))
+ {
+ detachRenderbuffer(renderbuffer);
+ }
-void Context::setSampleCoverage(bool enabled)
-{
- mState.sampleCoverage = enabled;
+ mResourceManager->deleteRenderbuffer(renderbuffer);
}
-bool Context::isSampleCoverageEnabled() const
+void Context::deleteFenceSync(GLsync fenceSync)
{
- return mState.sampleCoverage;
+ // 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(uintptr_t(fenceSync));
}
-void Context::setSampleCoverageParams(GLclampf value, bool invert)
+void Context::deleteVertexArray(GLuint vertexArray)
{
- mState.sampleCoverageValue = value;
- mState.sampleCoverageInvert = invert;
-}
+ auto vertexArrayObject = mVertexArrayMap.find(vertexArray);
-void Context::setScissorTest(bool enabled)
-{
- mState.scissorTest = enabled;
-}
+ if (vertexArrayObject != mVertexArrayMap.end())
+ {
+ detachVertexArray(vertexArray);
-bool Context::isScissorTestEnabled() const
-{
- return mState.scissorTest;
+ mVertexArrayHandleAllocator.release(vertexArrayObject->first);
+ delete vertexArrayObject->second;
+ mVertexArrayMap.erase(vertexArrayObject);
+ }
}
-void Context::setDither(bool enabled)
+void Context::deleteSampler(GLuint sampler)
{
- mState.blend.dither = enabled;
-}
+ if (mResourceManager->getSampler(sampler))
+ {
+ detachSampler(sampler);
+ }
-bool Context::isDitherEnabled() const
-{
- return mState.blend.dither;
+ mResourceManager->deleteSampler(sampler);
}
-void Context::setLineWidth(GLfloat width)
+void Context::deleteTransformFeedback(GLuint transformFeedback)
{
- mState.lineWidth = width;
+ TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(transformFeedback);
+ if (iter != mTransformFeedbackMap.end())
+ {
+ detachTransformFeedback(transformFeedback);
+ mTransformFeedbackAllocator.release(transformFeedback);
+ iter->second->release();
+ mTransformFeedbackMap.erase(iter);
+ }
}
-void Context::setGenerateMipmapHint(GLenum hint)
+void Context::deleteFramebuffer(GLuint framebuffer)
{
- mState.generateMipmapHint = hint;
-}
+ FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
-void Context::setFragmentShaderDerivativeHint(GLenum hint)
-{
- mState.fragmentShaderDerivativeHint = 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.
-}
+ if (framebufferObject != mFramebufferMap.end())
+ {
+ detachFramebuffer(framebuffer);
-void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
-{
- mState.viewport.x = x;
- mState.viewport.y = y;
- mState.viewport.width = width;
- mState.viewport.height = height;
+ mFramebufferHandleAllocator.release(framebufferObject->first);
+ delete framebufferObject->second;
+ mFramebufferMap.erase(framebufferObject);
+ }
}
-void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
+void Context::deleteFenceNV(GLuint fence)
{
- mState.scissor.x = x;
- mState.scissor.y = y;
- mState.scissor.width = width;
- mState.scissor.height = height;
+ FenceNVMap::iterator fenceObject = mFenceNVMap.find(fence);
+
+ if (fenceObject != mFenceNVMap.end())
+ {
+ mFenceNVHandleAllocator.release(fenceObject->first);
+ delete fenceObject->second;
+ mFenceNVMap.erase(fenceObject);
+ }
}
-void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
+void Context::deleteQuery(GLuint query)
{
- mState.blend.colorMaskRed = red;
- mState.blend.colorMaskGreen = green;
- mState.blend.colorMaskBlue = blue;
- mState.blend.colorMaskAlpha = alpha;
+ QueryMap::iterator queryObject = mQueryMap.find(query);
+ if (queryObject != mQueryMap.end())
+ {
+ mQueryHandleAllocator.release(queryObject->first);
+ if (queryObject->second)
+ {
+ queryObject->second->release();
+ }
+ mQueryMap.erase(queryObject);
+ }
}
-void Context::setDepthMask(bool mask)
+Buffer *Context::getBuffer(GLuint handle)
{
- mState.depthStencil.depthMask = mask;
+ return mResourceManager->getBuffer(handle);
}
-void Context::setActiveSampler(unsigned int active)
+Shader *Context::getShader(GLuint handle) const
{
- mState.activeSampler = active;
+ return mResourceManager->getShader(handle);
}
-GLuint Context::getReadFramebufferHandle() const
+Program *Context::getProgram(GLuint handle) const
{
- return mState.readFramebuffer;
+ return mResourceManager->getProgram(handle);
}
-GLuint Context::getDrawFramebufferHandle() const
+Texture *Context::getTexture(GLuint handle) const
{
- return mState.drawFramebuffer;
+ return mResourceManager->getTexture(handle);
}
-GLuint Context::getRenderbufferHandle() const
+Renderbuffer *Context::getRenderbuffer(GLuint handle)
{
- return mState.renderbuffer.id();
+ return mResourceManager->getRenderbuffer(handle);
}
-GLuint Context::getArrayBufferHandle() const
+FenceSync *Context::getFenceSync(GLsync handle) const
{
- return mState.arrayBuffer.id();
+ return mResourceManager->getFenceSync(uintptr_t(handle));
}
-GLuint Context::getActiveQuery(GLenum target) const
+VertexArray *Context::getVertexArray(GLuint handle) const
{
- Query *queryObject = NULL;
-
- switch (target)
- {
- case GL_ANY_SAMPLES_PASSED_EXT:
- queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED].get();
- break;
- case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
- queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE].get();
- break;
- default:
- ASSERT(false);
- }
+ auto vertexArray = mVertexArrayMap.find(handle);
- if (queryObject)
+ if (vertexArray == mVertexArrayMap.end())
{
- return queryObject->id();
+ return NULL;
}
else
{
- return 0;
+ return vertexArray->second;
}
}
-void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
-{
- mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
-}
-
-const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)
-{
- return mState.vertexAttribute[attribNum];
-}
-
-void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
- GLsizei stride, const void *pointer)
-{
- mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);
- mState.vertexAttribute[attribNum].mSize = size;
- mState.vertexAttribute[attribNum].mType = type;
- mState.vertexAttribute[attribNum].mNormalized = normalized;
- mState.vertexAttribute[attribNum].mStride = stride;
- mState.vertexAttribute[attribNum].mPointer = pointer;
-}
-
-const void *Context::getVertexAttribPointer(unsigned int attribNum) const
-{
- return mState.vertexAttribute[attribNum].mPointer;
-}
-
-void Context::setPackAlignment(GLint alignment)
-{
- mState.packAlignment = alignment;
-}
-
-GLint Context::getPackAlignment() const
-{
- return mState.packAlignment;
-}
-
-void Context::setUnpackAlignment(GLint alignment)
-{
- mState.unpackAlignment = alignment;
-}
-
-GLint Context::getUnpackAlignment() const
-{
- return mState.unpackAlignment;
-}
-
-void Context::setPackReverseRowOrder(bool reverseRowOrder)
-{
- mState.packReverseRowOrder = reverseRowOrder;
-}
-
-bool Context::getPackReverseRowOrder() const
-{
- return mState.packReverseRowOrder;
-}
-
-GLuint Context::createBuffer()
-{
- return mResourceManager->createBuffer();
-}
-
-GLuint Context::createProgram()
-{
- return mResourceManager->createProgram();
-}
-
-GLuint Context::createShader(GLenum type)
-{
- return mResourceManager->createShader(type);
-}
-
-GLuint Context::createTexture()
+Sampler *Context::getSampler(GLuint handle) const
{
- return mResourceManager->createTexture();
+ return mResourceManager->getSampler(handle);
}
-GLuint Context::createRenderbuffer()
+TransformFeedback *Context::getTransformFeedback(GLuint handle) const
{
- return mResourceManager->createRenderbuffer();
+ if (handle == 0)
+ {
+ return mTransformFeedbackZero.get();
+ }
+ else
+ {
+ TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(handle);
+ return (iter != mTransformFeedbackMap.end()) ? iter->second : NULL;
+ }
}
-// Returns an unused framebuffer name
-GLuint Context::createFramebuffer()
+bool Context::isSampler(GLuint samplerName) const
{
- GLuint handle = mFramebufferHandleAllocator.allocate();
-
- mFramebufferMap[handle] = NULL;
-
- return handle;
+ return mResourceManager->isSampler(samplerName);
}
-GLuint Context::createFence()
+void Context::bindArrayBuffer(unsigned int buffer)
{
- GLuint handle = mFenceHandleAllocator.allocate();
-
- mFenceMap[handle] = new Fence(mRenderer);
+ mResourceManager->checkBufferAllocation(buffer);
- return handle;
+ mState.setArrayBufferBinding(getBuffer(buffer));
}
-// Returns an unused query name
-GLuint Context::createQuery()
+void Context::bindElementArrayBuffer(unsigned int buffer)
{
- GLuint handle = mQueryHandleAllocator.allocate();
-
- mQueryMap[handle] = NULL;
-
- return handle;
-}
+ mResourceManager->checkBufferAllocation(buffer);
-void Context::deleteBuffer(GLuint buffer)
-{
- if (mResourceManager->getBuffer(buffer))
- {
- detachBuffer(buffer);
- }
-
- mResourceManager->deleteBuffer(buffer);
+ mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer));
}
-void Context::deleteShader(GLuint shader)
+void Context::bindTexture(GLenum target, GLuint texture)
{
- mResourceManager->deleteShader(shader);
-}
+ mResourceManager->checkTextureAllocation(texture, target);
-void Context::deleteProgram(GLuint program)
-{
- mResourceManager->deleteProgram(program);
+ mState.setSamplerTexture(target, getTexture(texture));
}
-void Context::deleteTexture(GLuint texture)
+void Context::bindReadFramebuffer(GLuint framebuffer)
{
- if (mResourceManager->getTexture(texture))
+ if (!getFramebuffer(framebuffer))
{
- detachTexture(texture);
+ mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer);
}
- mResourceManager->deleteTexture(texture);
+ mState.setReadFramebufferBinding(getFramebuffer(framebuffer));
}
-void Context::deleteRenderbuffer(GLuint renderbuffer)
+void Context::bindDrawFramebuffer(GLuint framebuffer)
{
- if (mResourceManager->getRenderbuffer(renderbuffer))
+ if (!getFramebuffer(framebuffer))
{
- detachRenderbuffer(renderbuffer);
+ mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer);
}
-
- mResourceManager->deleteRenderbuffer(renderbuffer);
-}
-
-void Context::deleteFramebuffer(GLuint framebuffer)
-{
- FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
-
- if (framebufferObject != mFramebufferMap.end())
- {
- detachFramebuffer(framebuffer);
- mFramebufferHandleAllocator.release(framebufferObject->first);
- delete framebufferObject->second;
- mFramebufferMap.erase(framebufferObject);
- }
+ mState.setDrawFramebufferBinding(getFramebuffer(framebuffer));
}
-void Context::deleteFence(GLuint fence)
+void Context::bindRenderbuffer(GLuint renderbuffer)
{
- FenceMap::iterator fenceObject = mFenceMap.find(fence);
+ mResourceManager->checkRenderbufferAllocation(renderbuffer);
- if (fenceObject != mFenceMap.end())
- {
- mFenceHandleAllocator.release(fenceObject->first);
- delete fenceObject->second;
- mFenceMap.erase(fenceObject);
- }
+ mState.setRenderbufferBinding(getRenderbuffer(renderbuffer));
}
-void Context::deleteQuery(GLuint query)
+void Context::bindVertexArray(GLuint vertexArray)
{
- QueryMap::iterator queryObject = mQueryMap.find(query);
- if (queryObject != mQueryMap.end())
+ if (!getVertexArray(vertexArray))
{
- mQueryHandleAllocator.release(queryObject->first);
- if (queryObject->second)
- {
- queryObject->second->release();
- }
- mQueryMap.erase(queryObject);
+ VertexArray *vertexArrayObject = new VertexArray(mRenderer->createVertexArray(), vertexArray, MAX_VERTEX_ATTRIBS);
+ mVertexArrayMap[vertexArray] = vertexArrayObject;
}
-}
-
-Buffer *Context::getBuffer(GLuint handle)
-{
- return mResourceManager->getBuffer(handle);
-}
-Shader *Context::getShader(GLuint handle)
-{
- return mResourceManager->getShader(handle);
+ mState.setVertexArrayBinding(getVertexArray(vertexArray));
}
-Program *Context::getProgram(GLuint handle)
+void Context::bindSampler(GLuint textureUnit, GLuint sampler)
{
- return mResourceManager->getProgram(handle);
-}
+ ASSERT(textureUnit < mCaps.maxCombinedTextureImageUnits);
+ mResourceManager->checkSamplerAllocation(sampler);
-Texture *Context::getTexture(GLuint handle)
-{
- return mResourceManager->getTexture(handle);
+ mState.setSamplerBinding(textureUnit, getSampler(sampler));
}
-Renderbuffer *Context::getRenderbuffer(GLuint handle)
+void Context::bindGenericUniformBuffer(GLuint buffer)
{
- return mResourceManager->getRenderbuffer(handle);
-}
+ mResourceManager->checkBufferAllocation(buffer);
-Framebuffer *Context::getReadFramebuffer()
-{
- return getFramebuffer(mState.readFramebuffer);
+ mState.setGenericUniformBufferBinding(getBuffer(buffer));
}
-Framebuffer *Context::getDrawFramebuffer()
-{
- return mBoundDrawFramebuffer;
-}
-
-void Context::bindArrayBuffer(unsigned int buffer)
+void Context::bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size)
{
mResourceManager->checkBufferAllocation(buffer);
- mState.arrayBuffer.set(getBuffer(buffer));
+ mState.setIndexedUniformBufferBinding(index, getBuffer(buffer), offset, size);
}
-void Context::bindElementArrayBuffer(unsigned int buffer)
+void Context::bindGenericTransformFeedbackBuffer(GLuint buffer)
{
mResourceManager->checkBufferAllocation(buffer);
- mState.elementArrayBuffer.set(getBuffer(buffer));
+ mState.setGenericTransformFeedbackBufferBinding(getBuffer(buffer));
}
-void Context::bindTexture2D(GLuint texture)
+void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size)
{
- mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
+ mResourceManager->checkBufferAllocation(buffer);
- mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));
+ mState.setIndexedTransformFeedbackBufferBinding(index, getBuffer(buffer), offset, size);
}
-void Context::bindTextureCubeMap(GLuint texture)
+void Context::bindCopyReadBuffer(GLuint buffer)
{
- mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);
+ mResourceManager->checkBufferAllocation(buffer);
- mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));
+ mState.setCopyReadBufferBinding(getBuffer(buffer));
}
-void Context::bindReadFramebuffer(GLuint framebuffer)
+void Context::bindCopyWriteBuffer(GLuint buffer)
{
- if (!getFramebuffer(framebuffer))
- {
- mFramebufferMap[framebuffer] = new Framebuffer(mRenderer);
- }
+ mResourceManager->checkBufferAllocation(buffer);
- mState.readFramebuffer = framebuffer;
+ mState.setCopyWriteBufferBinding(getBuffer(buffer));
}
-void Context::bindDrawFramebuffer(GLuint framebuffer)
+void Context::bindPixelPackBuffer(GLuint buffer)
{
- if (!getFramebuffer(framebuffer))
- {
- mFramebufferMap[framebuffer] = new Framebuffer(mRenderer);
- }
-
- mState.drawFramebuffer = framebuffer;
+ mResourceManager->checkBufferAllocation(buffer);
- mBoundDrawFramebuffer = getFramebuffer(framebuffer);
+ mState.setPixelPackBufferBinding(getBuffer(buffer));
}
-void Context::bindRenderbuffer(GLuint renderbuffer)
+void Context::bindPixelUnpackBuffer(GLuint buffer)
{
- mResourceManager->checkRenderbufferAllocation(renderbuffer);
+ mResourceManager->checkBufferAllocation(buffer);
- mState.renderbuffer.set(getRenderbuffer(renderbuffer));
+ mState.setPixelUnpackBufferBinding(getBuffer(buffer));
}
void Context::useProgram(GLuint program)
{
- GLuint priorProgram = mState.currentProgram;
- mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
+ GLuint priorProgramId = mState.getCurrentProgramId();
+ Program *priorProgram = mResourceManager->getProgram(priorProgramId);
- if (priorProgram != program)
+ if (priorProgramId != program)
{
- Program *newProgram = mResourceManager->getProgram(program);
- Program *oldProgram = mResourceManager->getProgram(priorProgram);
- mCurrentProgramBinary.set(NULL);
+ mState.setCurrentProgram(program, mResourceManager->getProgram(program));
- if (newProgram)
- {
- newProgram->addRef();
- mCurrentProgramBinary.set(newProgram->getProgramBinary());
- }
-
- if (oldProgram)
+ if (priorProgram)
{
- oldProgram->release();
+ priorProgram->release();
}
}
}
@@ -939,163 +644,116 @@ void Context::linkProgram(GLuint program)
{
Program *programObject = mResourceManager->getProgram(program);
- bool linked = programObject->link();
+ bool linked = programObject->link(getCaps());
// if the current program was relinked successfully we
// need to install the new executables
- if (linked && program == mState.currentProgram)
+ if (linked && program == mState.getCurrentProgramId())
{
- mCurrentProgramBinary.set(programObject->getProgramBinary());
+ mState.setCurrentProgramBinary(programObject->getProgramBinary());
}
}
-void Context::setProgramBinary(GLuint program, const void *binary, GLint length)
+void Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length)
{
Program *programObject = mResourceManager->getProgram(program);
- bool loaded = programObject->setProgramBinary(binary, length);
+ bool loaded = programObject->setProgramBinary(binaryFormat, binary, length);
// if the current program was reloaded successfully we
// need to install the new executables
- if (loaded && program == mState.currentProgram)
+ if (loaded && program == mState.getCurrentProgramId())
{
- mCurrentProgramBinary.set(programObject->getProgramBinary());
+ mState.setCurrentProgramBinary(programObject->getProgramBinary());
}
}
-void Context::beginQuery(GLenum target, GLuint query)
+void Context::bindTransformFeedback(GLuint transformFeedback)
{
- // 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.
+ mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback));
+}
- // 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.
- for (int i = 0; i < QUERY_TYPE_COUNT; i++)
- {
- if (mState.activeQuery[i].get() != NULL)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- }
+Error Context::beginQuery(GLenum target, GLuint query)
+{
+ Query *queryObject = getQuery(query, true, target);
+ ASSERT(queryObject);
- QueryType qType;
- switch (target)
+ // begin query
+ Error error = queryObject->begin();
+ if (error.isError())
{
- case GL_ANY_SAMPLES_PASSED_EXT:
- qType = QUERY_ANY_SAMPLES_PASSED;
- break;
- case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
- qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
- break;
- default:
- ASSERT(false);
- return;
+ return error;
}
- Query *queryObject = getQuery(query, true, target);
+ // set query as active for specified target only if begin succeeded
+ mState.setActiveQuery(target, queryObject);
- // check that name was obtained with glGenQueries
- if (!queryObject)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ return Error(GL_NO_ERROR);
+}
- // check for type mismatch
- if (queryObject->getType() != target)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+Error Context::endQuery(GLenum target)
+{
+ Query *queryObject = mState.getActiveQuery(target);
+ ASSERT(queryObject);
- // set query as active for specified target
- mState.activeQuery[qType].set(queryObject);
+ gl::Error error = queryObject->end();
- // begin query
- queryObject->begin();
+ // Always unbind the query, even if there was an error. This may delete the query object.
+ mState.setActiveQuery(target, NULL);
+
+ return error;
}
-void Context::endQuery(GLenum target)
+void Context::setFramebufferZero(Framebuffer *buffer)
{
- QueryType qType;
-
- switch (target)
+ // First, check to see if the old default framebuffer
+ // was set for draw or read framebuffer, and change
+ // the bindings to point to the new one before deleting it.
+ if (mState.getDrawFramebuffer()->id() == 0)
{
- case GL_ANY_SAMPLES_PASSED_EXT:
- qType = QUERY_ANY_SAMPLES_PASSED;
- break;
- case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
- qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
- break;
- default:
- ASSERT(false);
- return;
+ mState.setDrawFramebufferBinding(buffer);
}
- Query *queryObject = mState.activeQuery[qType].get();
-
- if (queryObject == NULL)
+ if (mState.getReadFramebuffer()->id() == 0)
{
- return gl::error(GL_INVALID_OPERATION);
+ mState.setReadFramebufferBinding(buffer);
}
- queryObject->end();
-
- mState.activeQuery[qType].set(NULL);
-}
-
-void Context::setFramebufferZero(Framebuffer *buffer)
-{
delete mFramebufferMap[0];
mFramebufferMap[0] = buffer;
- if (mState.drawFramebuffer == 0)
- {
- mBoundDrawFramebuffer = buffer;
- }
}
void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
{
+ ASSERT(getTextureCaps().get(internalformat).renderable);
+
RenderbufferStorage *renderbuffer = NULL;
- switch (internalformat)
+
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
+ if (formatInfo.depthBits > 0 && formatInfo.stencilBits > 0)
+ {
+ renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples);
+ }
+ else if (formatInfo.depthBits > 0)
{
- case GL_DEPTH_COMPONENT16:
renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples);
- break;
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGB565:
- case GL_RGB8_OES:
- case GL_RGBA8_OES:
- case GL_BGRA8_EXT:
- renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples);
- break;
- case GL_STENCIL_INDEX8:
+ }
+ else if (formatInfo.stencilBits > 0)
+ {
renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples);
- break;
- case GL_DEPTH24_STENCIL8_OES:
- renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples);
- break;
- default:
- UNREACHABLE(); return;
+ }
+ else
+ {
+ renderbuffer = new gl::Colorbuffer(mRenderer, width, height, internalformat, samples);
}
- Renderbuffer *renderbufferObject = mState.renderbuffer.get();
- renderbufferObject->setStorage(renderbuffer);
+ mState.getCurrentRenderbuffer()->setStorage(renderbuffer);
}
-Framebuffer *Context::getFramebuffer(unsigned int handle)
+Framebuffer *Context::getFramebuffer(unsigned int handle) const
{
- FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
+ FramebufferMap::const_iterator framebuffer = mFramebufferMap.find(handle);
if (framebuffer == mFramebufferMap.end())
{
@@ -1107,11 +765,11 @@ Framebuffer *Context::getFramebuffer(unsigned int handle)
}
}
-Fence *Context::getFence(unsigned int handle)
+FenceNV *Context::getFenceNV(unsigned int handle)
{
- FenceMap::iterator fence = mFenceMap.find(handle);
+ FenceNVMap::iterator fence = mFenceNVMap.find(handle);
- if (fence == mFenceMap.end())
+ if (fence == mFenceNVMap.end())
{
return NULL;
}
@@ -1133,397 +791,225 @@ Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
{
if (!query->second && create)
{
- query->second = new Query(mRenderer, type, handle);
+ query->second = new Query(mRenderer->createQuery(type), handle);
query->second->addRef();
}
return query->second;
}
}
-Buffer *Context::getArrayBuffer()
+Texture *Context::getTargetTexture(GLenum target) const
{
- return mState.arrayBuffer.get();
+ if (!ValidTextureTarget(this, target))
+ {
+ return NULL;
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D: return getTexture2D();
+ case GL_TEXTURE_CUBE_MAP: return getTextureCubeMap();
+ case GL_TEXTURE_3D: return getTexture3D();
+ case GL_TEXTURE_2D_ARRAY: return getTexture2DArray();
+ default: return NULL;
+ }
}
-Buffer *Context::getElementArrayBuffer()
+Texture2D *Context::getTexture2D() const
{
- return mState.elementArrayBuffer.get();
+ return static_cast<Texture2D*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D));
}
-ProgramBinary *Context::getCurrentProgramBinary()
+TextureCubeMap *Context::getTextureCubeMap() const
{
- return mCurrentProgramBinary.get();
+ return static_cast<TextureCubeMap*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_CUBE_MAP));
}
-Texture2D *Context::getTexture2D()
+Texture3D *Context::getTexture3D() const
{
- return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));
+ return static_cast<Texture3D*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_3D));
}
-TextureCubeMap *Context::getTextureCubeMap()
+Texture2DArray *Context::getTexture2DArray() const
{
- return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));
+ return static_cast<Texture2DArray*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D_ARRAY));
}
-Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)
+Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const
{
- GLuint texid = mState.samplerTexture[type][sampler].id();
-
- if (texid == 0) // Special case: 0 refers to different initial textures based on the target
+ if (mState.getSamplerTextureId(sampler, type) == 0)
{
- switch (type)
- {
- default: UNREACHABLE();
- case TEXTURE_2D: return mTexture2DZero.get();
- case TEXTURE_CUBE: return mTextureCubeMapZero.get();
- }
+ return mZeroTextures.at(type).get();
+ }
+ else
+ {
+ return mState.getSamplerTexture(sampler, type);
}
-
- return mState.samplerTexture[type][sampler].get();
}
-bool Context::getBooleanv(GLenum pname, GLboolean *params)
+void Context::getBooleanv(GLenum pname, GLboolean *params)
{
switch (pname)
{
case GL_SHADER_COMPILER: *params = GL_TRUE; break;
- case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
- case GL_DEPTH_WRITEMASK: *params = mState.depthStencil.depthMask; break;
- case GL_COLOR_WRITEMASK:
- params[0] = mState.blend.colorMaskRed;
- params[1] = mState.blend.colorMaskGreen;
- params[2] = mState.blend.colorMaskBlue;
- params[3] = mState.blend.colorMaskAlpha;
- break;
- case GL_CULL_FACE: *params = mState.rasterizer.cullFace; break;
- case GL_POLYGON_OFFSET_FILL: *params = mState.rasterizer.polygonOffsetFill; break;
- case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.blend.sampleAlphaToCoverage; break;
- case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break;
- case GL_SCISSOR_TEST: *params = mState.scissorTest; break;
- case GL_STENCIL_TEST: *params = mState.depthStencil.stencilTest; break;
- case GL_DEPTH_TEST: *params = mState.depthStencil.depthTest; break;
- case GL_BLEND: *params = mState.blend.blend; break;
- case GL_DITHER: *params = mState.blend.dither; break;
case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break;
default:
- return false;
+ mState.getBooleanv(pname, params);
+ break;
}
-
- return true;
}
-bool Context::getFloatv(GLenum pname, GLfloat *params)
+void Context::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.
+ // Queries about context capabilities and maximums are answered by Context.
+ // Queries about current GL state values are answered by State.
switch (pname)
{
- case GL_LINE_WIDTH: *params = mState.lineWidth; break;
- case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
- case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
- case GL_POLYGON_OFFSET_FACTOR: *params = mState.rasterizer.polygonOffsetFactor; break;
- case GL_POLYGON_OFFSET_UNITS: *params = mState.rasterizer.polygonOffsetUnits; break;
case GL_ALIASED_LINE_WIDTH_RANGE:
- params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
- params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
+ params[0] = mCaps.minAliasedLineWidth;
+ params[1] = mCaps.maxAliasedLineWidth;
break;
case GL_ALIASED_POINT_SIZE_RANGE:
- params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
- params[1] = getMaximumPointSize();
- break;
- case GL_DEPTH_RANGE:
- params[0] = mState.zNear;
- params[1] = mState.zFar;
- break;
- case GL_COLOR_CLEAR_VALUE:
- params[0] = mState.colorClearValue.red;
- params[1] = mState.colorClearValue.green;
- params[2] = mState.colorClearValue.blue;
- params[3] = mState.colorClearValue.alpha;
- break;
- case GL_BLEND_COLOR:
- params[0] = mState.blendColor.red;
- params[1] = mState.blendColor.green;
- params[2] = mState.blendColor.blue;
- params[3] = mState.blendColor.alpha;
+ params[0] = mCaps.minAliasedPointSize;
+ params[1] = mCaps.maxAliasedPointSize;
break;
case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
- if (!supportsTextureFilterAnisotropy())
- {
- return false;
- }
- *params = mMaxTextureAnisotropy;
+ ASSERT(mExtensions.textureFilterAnisotropic);
+ *params = mExtensions.maxTextureAnisotropy;
break;
default:
- return false;
+ mState.getFloatv(pname, params);
+ break;
}
-
- return true;
}
-bool Context::getIntegerv(GLenum pname, GLint *params)
+void Context::getIntegerv(GLenum pname, GLint *params)
{
- if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
- {
- unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT);
-
- if (colorAttachment >= mRenderer->getMaxRenderTargets())
- {
- // return true to stop further operation in the parent call
- return gl::error(GL_INVALID_OPERATION, true);
- }
-
- Framebuffer *framebuffer = getDrawFramebuffer();
+ // Queries about context capabilities and maximums are answered by Context.
+ // Queries about current GL state values are answered by State.
- *params = framebuffer->getDrawBufferState(colorAttachment);
- return true;
- }
-
- // 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
- // Context::getFloatv.
switch (pname)
{
- case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
- case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mRenderer->getMaxVertexUniformVectors(); break;
- case GL_MAX_VARYING_VECTORS: *params = mRenderer->getMaxVaryingVectors(); break;
- case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxCombinedTextureImageUnits(); break;
- case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxVertexTextureImageUnits(); break;
- case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
- case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mRenderer->getMaxFragmentUniformVectors(); break;
- case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break;
- case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mRenderer->getMaxRenderTargets(); break;
- case GL_MAX_DRAW_BUFFERS_EXT: *params = mRenderer->getMaxRenderTargets(); break;
- case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
- case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
- case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break;
- case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break;
- //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
- case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break;
- case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break;
- case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break;
- case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
- case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
- case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mState.packReverseRowOrder; break;
- case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
- case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
- case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break;
- case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break;
- case GL_STENCIL_FUNC: *params = mState.depthStencil.stencilFunc; break;
- case GL_STENCIL_REF: *params = mState.stencilRef; break;
- case GL_STENCIL_VALUE_MASK: *params = mState.depthStencil.stencilMask; break;
- case GL_STENCIL_BACK_FUNC: *params = mState.depthStencil.stencilBackFunc; break;
- case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
- case GL_STENCIL_BACK_VALUE_MASK: *params = mState.depthStencil.stencilBackMask; break;
- case GL_STENCIL_FAIL: *params = mState.depthStencil.stencilFail; break;
- case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilPassDepthFail; break;
- case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilPassDepthPass; break;
- case GL_STENCIL_BACK_FAIL: *params = mState.depthStencil.stencilBackFail; break;
- case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilBackPassDepthFail; break;
- case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilBackPassDepthPass; break;
- case GL_DEPTH_FUNC: *params = mState.depthStencil.depthFunc; break;
- case GL_BLEND_SRC_RGB: *params = mState.blend.sourceBlendRGB; break;
- case GL_BLEND_SRC_ALPHA: *params = mState.blend.sourceBlendAlpha; break;
- case GL_BLEND_DST_RGB: *params = mState.blend.destBlendRGB; break;
- case GL_BLEND_DST_ALPHA: *params = mState.blend.destBlendAlpha; break;
- case GL_BLEND_EQUATION_RGB: *params = mState.blend.blendEquationRGB; break;
- case GL_BLEND_EQUATION_ALPHA: *params = mState.blend.blendEquationAlpha; break;
- case GL_STENCIL_WRITEMASK: *params = mState.depthStencil.stencilWritemask; break;
- case GL_STENCIL_BACK_WRITEMASK: *params = mState.depthStencil.stencilBackWritemask; break;
- case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
- case GL_SUBPIXEL_BITS: *params = 4; break;
- case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break;
- case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break;
- case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
- params[0] = mNumCompressedTextureFormats;
- break;
- case GL_MAX_SAMPLES_ANGLE:
- {
- GLsizei maxSamples = getMaxSupportedSamples();
- if (maxSamples != 0)
- {
- *params = maxSamples;
- }
- else
- {
- return false;
- }
-
- break;
- }
- case GL_SAMPLE_BUFFERS:
- case GL_SAMPLES:
- {
- gl::Framebuffer *framebuffer = getDrawFramebuffer();
- if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
- {
- switch (pname)
- {
- case GL_SAMPLE_BUFFERS:
- if (framebuffer->getSamples() != 0)
- {
- *params = 1;
- }
- else
- {
- *params = 0;
- }
- break;
- case GL_SAMPLES:
- *params = framebuffer->getSamples();
- break;
- }
- }
- else
- {
- *params = 0;
- }
- }
- break;
+ 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.maxFragmentInputComponents; 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_MAJOR_VERSION: *params = mClientVersion; break;
+ case GL_MINOR_VERSION: *params = 0; 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 = mCaps.compressedTextureFormats.size(); break;
+ case GL_MAX_SAMPLES_ANGLE: *params = mExtensions.maxSamples; break;
case GL_IMPLEMENTATION_COLOR_READ_TYPE:
case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
{
- GLenum format, type;
- if (getCurrentReadFormatType(&format, &type))
- {
- if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT)
- *params = format;
- else
- *params = type;
- }
+ GLenum internalFormat, format, type;
+ getCurrentReadFormatType(&internalFormat, &format, &type);
+ if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT)
+ *params = format;
+ else
+ *params = type;
}
break;
case GL_MAX_VIEWPORT_DIMS:
{
- params[0] = mMaxViewportDimension;
- params[1] = mMaxViewportDimension;
+ params[0] = mCaps.maxViewportWidth;
+ params[1] = mCaps.maxViewportHeight;
}
break;
case GL_COMPRESSED_TEXTURE_FORMATS:
- {
- if (supportsDXT1Textures())
- {
- *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
- *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
- }
- if (supportsDXT3Textures())
- {
- *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
- }
- if (supportsDXT5Textures())
- {
- *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
- }
- }
+ std::copy(mCaps.compressedTextureFormats.begin(), mCaps.compressedTextureFormats.end(), params);
break;
- case GL_VIEWPORT:
- params[0] = mState.viewport.x;
- params[1] = mState.viewport.y;
- params[2] = mState.viewport.width;
- params[3] = mState.viewport.height;
+ case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+ *params = mResetStrategy;
break;
- case GL_SCISSOR_BOX:
- params[0] = mState.scissor.x;
- params[1] = mState.scissor.y;
- params[2] = mState.scissor.width;
- params[3] = mState.scissor.height;
+ case GL_NUM_SHADER_BINARY_FORMATS:
+ *params = mCaps.shaderBinaryFormats.size();
break;
- case GL_CULL_FACE_MODE: *params = mState.rasterizer.cullMode; break;
- case GL_FRONT_FACE: *params = mState.rasterizer.frontFace; break;
- case GL_RED_BITS:
- case GL_GREEN_BITS:
- case GL_BLUE_BITS:
- case GL_ALPHA_BITS:
- {
- gl::Framebuffer *framebuffer = getDrawFramebuffer();
- gl::Renderbuffer *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;
- }
- }
+ case GL_SHADER_BINARY_FORMATS:
+ std::copy(mCaps.shaderBinaryFormats.begin(), mCaps.shaderBinaryFormats.end(), params);
break;
- case GL_DEPTH_BITS:
- {
- gl::Framebuffer *framebuffer = getDrawFramebuffer();
- gl::Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
-
- if (depthbuffer)
- {
- *params = depthbuffer->getDepthSize();
- }
- else
- {
- *params = 0;
- }
- }
+ case GL_NUM_PROGRAM_BINARY_FORMATS:
+ *params = mCaps.programBinaryFormats.size();
break;
- case GL_STENCIL_BITS:
- {
- gl::Framebuffer *framebuffer = getDrawFramebuffer();
- gl::Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
-
- if (stencilbuffer)
- {
- *params = stencilbuffer->getStencilSize();
- }
- else
- {
- *params = 0;
- }
- }
+ case GL_PROGRAM_BINARY_FORMATS:
+ std::copy(mCaps.programBinaryFormats.begin(), mCaps.programBinaryFormats.end(), params);
break;
- case GL_TEXTURE_BINDING_2D:
- {
- if (mState.activeSampler > mRenderer->getMaxCombinedTextureImageUnits() - 1)
- {
- gl::error(GL_INVALID_OPERATION);
- return false;
- }
-
- *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id();
- }
+ case GL_NUM_EXTENSIONS:
+ *params = static_cast<GLint>(mExtensionStrings.size());
break;
- case GL_TEXTURE_BINDING_CUBE_MAP:
- {
- if (mState.activeSampler > mRenderer->getMaxCombinedTextureImageUnits() - 1)
- {
- gl::error(GL_INVALID_OPERATION);
- return false;
- }
+ default:
+ mState.getIntegerv(pname, params);
+ break;
+ }
+}
- *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();
- }
+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_RESET_NOTIFICATION_STRATEGY_EXT:
- *params = mResetStrategy;
+ case GL_MAX_UNIFORM_BLOCK_SIZE:
+ *params = mCaps.maxUniformBlockSize;
break;
- case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
- *params = 1;
+ case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
+ *params = mCaps.maxCombinedVertexUniformComponents;
break;
- case GL_PROGRAM_BINARY_FORMATS_OES:
- *params = GL_PROGRAM_BINARY_ANGLE;
+ case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
+ *params = mCaps.maxCombinedFragmentUniformComponents;
+ break;
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ *params = mCaps.maxServerWaitTimeout;
break;
default:
- return false;
+ UNREACHABLE();
+ break;
}
+}
+
+bool Context::getIndexedIntegerv(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.
+ // Indexed integer queries all refer to current state, so this function is a
+ // mere passthrough.
+ return mState.getIndexedIntegerv(target, index, data);
+}
- return true;
+bool Context::getIndexedInteger64v(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.
+ // Indexed integer queries all refer to current state, so this function is a
+ // mere passthrough.
+ return mState.getIndexedInteger64v(target, index, data);
}
bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
@@ -1538,7 +1024,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
// 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
+ // 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.
@@ -1547,15 +1033,21 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
case GL_COMPRESSED_TEXTURE_FORMATS:
{
*type = GL_INT;
- *numParams = mNumCompressedTextureFormats;
+ *numParams = mCaps.compressedTextureFormats.size();
}
- break;
+ return true;
+ case GL_PROGRAM_BINARY_FORMATS_OES:
+ {
+ *type = GL_INT;
+ *numParams = mCaps.programBinaryFormats.size();
+ }
+ return true;
case GL_SHADER_BINARY_FORMATS:
{
*type = GL_INT;
- *numParams = 0;
+ *numParams = mCaps.shaderBinaryFormats.size();
}
- break;
+ return true;
case GL_MAX_VERTEX_ATTRIBS:
case GL_MAX_VERTEX_UNIFORM_VECTORS:
case GL_MAX_VARYING_VECTORS:
@@ -1569,7 +1061,9 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
case GL_NUM_SHADER_BINARY_FORMATS:
case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
case GL_ARRAY_BUFFER_BINDING:
- case GL_FRAMEBUFFER_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:
@@ -1620,15 +1114,14 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
case GL_TEXTURE_BINDING_CUBE_MAP:
case GL_RESET_NOTIFICATION_STRATEGY_EXT:
case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
- case GL_PROGRAM_BINARY_FORMATS_OES:
{
*type = GL_INT;
*numParams = 1;
}
- break;
+ return true;
case GL_MAX_SAMPLES_ANGLE:
{
- if (getMaxSupportedSamples() != 0)
+ if (mExtensions.framebufferMultisample)
{
*type = GL_INT;
*numParams = 1;
@@ -1638,20 +1131,34 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
return false;
}
}
- break;
+ return true;
+ case GL_PIXEL_PACK_BUFFER_BINDING:
+ case GL_PIXEL_UNPACK_BUFFER_BINDING:
+ {
+ if (mExtensions.pixelBufferObject)
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ return true;
case GL_MAX_VIEWPORT_DIMS:
{
*type = GL_INT;
*numParams = 2;
}
- break;
+ return true;
case GL_VIEWPORT:
case GL_SCISSOR_BOX:
{
*type = GL_INT;
*numParams = 4;
}
- break;
+ return true;
case GL_SHADER_COMPILER:
case GL_SAMPLE_COVERAGE_INVERT:
case GL_DEPTH_WRITEMASK:
@@ -1669,13 +1176,13 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
*type = GL_BOOL;
*numParams = 1;
}
- break;
+ return true;
case GL_COLOR_WRITEMASK:
{
*type = GL_BOOL;
*numParams = 4;
}
- break;
+ return true;
case GL_POLYGON_OFFSET_FACTOR:
case GL_POLYGON_OFFSET_UNITS:
case GL_SAMPLE_COVERAGE_VALUE:
@@ -1685,7 +1192,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
*type = GL_FLOAT;
*numParams = 1;
}
- break;
+ return true;
case GL_ALIASED_LINE_WIDTH_RANGE:
case GL_ALIASED_POINT_SIZE_RANGE:
case GL_DEPTH_RANGE:
@@ -1693,76 +1200,169 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
*type = GL_FLOAT;
*numParams = 2;
}
- break;
+ return true;
case GL_COLOR_CLEAR_VALUE:
case GL_BLEND_COLOR:
{
*type = GL_FLOAT;
*numParams = 4;
}
- break;
+ return true;
case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
- if (!supportsTextureFilterAnisotropy())
+ if (!mExtensions.maxTextureAnisotropy)
{
return false;
}
*type = GL_FLOAT;
*numParams = 1;
- break;
- default:
+ return true;
+ }
+
+ if (mClientVersion < 3)
+ {
return false;
}
- return true;
+ // 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_COPY_READ_BUFFER_BINDING:
+ case GL_COPY_WRITE_BUFFER_BINDING:
+ 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_VARYING_COMPONENTS:
+ case GL_VERTEX_ARRAY_BINDING:
+ case GL_MAX_VERTEX_UNIFORM_COMPONENTS:
+ case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
+ 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:
+ {
+ *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:
+ {
+ *type = GL_BOOL;
+ *numParams = 1;
+ }
+ return true;
+ }
+
+ return false;
}
-// Applies the render target surface, depth stencil surface, viewport rectangle and
-// scissor rectangle to the renderer
-bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport)
+bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams)
{
- Framebuffer *framebufferObject = getDrawFramebuffer();
+ if (mClientVersion < 3)
+ {
+ return false;
+ }
- if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ switch (target)
{
- return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
+ 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;
+ }
}
- mRenderer->applyRenderTarget(framebufferObject);
+ return false;
+}
- if (!mRenderer->setViewport(mState.viewport, mState.zNear, mState.zFar, drawMode, mState.rasterizer.frontFace,
- ignoreViewport))
+// Applies the render target surface, depth stencil surface, viewport rectangle and
+// scissor rectangle to the renderer
+Error Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport)
+{
+ Framebuffer *framebufferObject = mState.getDrawFramebuffer();
+ ASSERT(framebufferObject && framebufferObject->completeness() == GL_FRAMEBUFFER_COMPLETE);
+
+ gl::Error error = mRenderer->applyRenderTarget(framebufferObject);
+ if (error.isError())
{
- return false;
+ return error;
}
- mRenderer->setScissorRectangle(mState.scissor, mState.scissorTest);
+ float nearZ, farZ;
+ mState.getDepthRange(&nearZ, &farZ);
+ mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace,
+ ignoreViewport);
- return true;
+ mRenderer->setScissorRectangle(mState.getScissor(), mState.isScissorTestEnabled());
+
+ return gl::Error(GL_NO_ERROR);
}
// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
-void Context::applyState(GLenum drawMode)
+Error Context::applyState(GLenum drawMode)
{
- Framebuffer *framebufferObject = getDrawFramebuffer();
+ Framebuffer *framebufferObject = mState.getDrawFramebuffer();
int samples = framebufferObject->getSamples();
- mState.rasterizer.pointDrawMode = (drawMode == GL_POINTS);
- mState.rasterizer.multiSample = (samples != 0);
- mRenderer->setRasterizerState(mState.rasterizer);
+ RasterizerState rasterizer = mState.getRasterizerState();
+ rasterizer.pointDrawMode = (drawMode == GL_POINTS);
+ rasterizer.multiSample = (samples != 0);
+
+ Error error = mRenderer->setRasterizerState(rasterizer);
+ if (error.isError())
+ {
+ return error;
+ }
unsigned int mask = 0;
- if (mState.sampleCoverage)
+ if (mState.isSampleCoverageEnabled())
{
- if (mState.sampleCoverageValue != 0)
+ GLclampf coverageValue;
+ bool coverageInvert = false;
+ mState.getSampleCoverageParams(&coverageValue, &coverageInvert);
+ if (coverageValue != 0)
{
-
float threshold = 0.5f;
for (int i = 0; i < samples; ++i)
{
mask <<= 1;
- if ((i + 1) * mState.sampleCoverageValue >= threshold)
+ if ((i + 1) * coverageValue >= threshold)
{
threshold += 1.0f;
mask |= 1;
@@ -1770,7 +1370,7 @@ void Context::applyState(GLenum drawMode)
}
}
- if (mState.sampleCoverageInvert)
+ if (coverageInvert)
{
mask = ~mask;
}
@@ -1779,279 +1379,524 @@ void Context::applyState(GLenum drawMode)
{
mask = 0xFFFFFFFF;
}
- mRenderer->setBlendState(framebufferObject, mState.blend, mState.blendColor, mask);
+ error = mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(),
+ rasterizer.frontFace == GL_CCW);
+ if (error.isError())
+ {
+ return error;
+ }
- mRenderer->setDepthStencilState(mState.depthStencil, mState.stencilRef, mState.stencilBackRef,
- mState.rasterizer.frontFace == GL_CCW);
+ return Error(GL_NO_ERROR);
}
// Applies the shaders and shader constants to the Direct3D 9 device
-void Context::applyShaders()
+Error Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive)
{
- ProgramBinary *programBinary = getCurrentProgramBinary();
+ const VertexAttribute *vertexAttributes = mState.getVertexArray()->getVertexAttributes();
- mRenderer->applyShaders(programBinary);
-
- programBinary->applyUniforms();
+ VertexFormat inputLayout[MAX_VERTEX_ATTRIBS];
+ VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.getVertexAttribCurrentValues());
+
+ const Framebuffer *fbo = mState.getDrawFramebuffer();
+
+ Error error = mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return programBinary->applyUniforms();
}
-// Applies the textures and sampler states to the Direct3D 9 device
-void Context::applyTextures()
+Error Context::generateSwizzles(ProgramBinary *programBinary, SamplerType type)
{
- applyTextures(SAMPLER_PIXEL);
+ size_t samplerRange = programBinary->getUsedSamplerRange(type);
- if (mSupportsVertexTexture)
+ for (size_t i = 0; i < samplerRange; i++)
{
- applyTextures(SAMPLER_VERTEX);
+ GLenum textureType = programBinary->getSamplerTextureType(type, i);
+ GLint textureUnit = programBinary->getSamplerMapping(type, i, getCaps());
+ if (textureUnit != -1)
+ {
+ Texture* texture = getSamplerTexture(textureUnit, textureType);
+ if (texture->getSamplerState().swizzleRequired())
+ {
+ Error error = mRenderer->generateSwizzle(texture);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
}
+
+ return Error(GL_NO_ERROR);
}
-// For each Direct3D 9 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).
-void Context::applyTextures(SamplerType type)
+Error Context::generateSwizzles(ProgramBinary *programBinary)
{
- ProgramBinary *programBinary = getCurrentProgramBinary();
+ Error error = generateSwizzles(programBinary, SAMPLER_VERTEX);
+ if (error.isError())
+ {
+ return error;
+ }
- FramebufferTextureSerialSet boundFramebufferTextures = getBoundFramebufferTextureSerials();
+ error = generateSwizzles(programBinary, SAMPLER_PIXEL);
+ if (error.isError())
+ {
+ return error;
+ }
- // Range of Direct3D samplers of given sampler type
- int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : mRenderer->getMaxVertexTextureImageUnits();
- int samplerRange = programBinary->getUsedSamplerRange(type);
+ return Error(GL_NO_ERROR);
+}
- for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
+// 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).
+Error Context::applyTextures(ProgramBinary *programBinary, SamplerType shaderType,
+ const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount)
+{
+ size_t samplerRange = programBinary->getUsedSamplerRange(shaderType);
+ for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
{
- int textureUnit = programBinary->getSamplerMapping(type, samplerIndex); // OpenGL texture image unit index
-
+ GLenum textureType = programBinary->getSamplerTextureType(shaderType, samplerIndex);
+ GLint textureUnit = programBinary->getSamplerMapping(shaderType, samplerIndex, getCaps());
if (textureUnit != -1)
{
- TextureType textureType = programBinary->getSamplerTextureType(type, samplerIndex);
- Texture *texture = getSamplerTexture(textureUnit, textureType);
+ SamplerState sampler;
+ Texture* texture = getSamplerTexture(textureUnit, textureType);
+ texture->getSamplerStateWithNativeOffset(&sampler);
- if (texture->isSamplerComplete() &&
- boundFramebufferTextures.find(texture->getTextureSerial()) == boundFramebufferTextures.end())
+ Sampler *samplerObject = mState.getSampler(textureUnit);
+ if (samplerObject)
{
- SamplerState samplerState;
- texture->getSamplerState(&samplerState);
- mRenderer->setSamplerState(type, samplerIndex, samplerState);
+ samplerObject->getState(&sampler);
+ }
- mRenderer->setTexture(type, samplerIndex, texture);
+ // TODO: std::binary_search may become unavailable using older versions of GCC
+ if (texture->isSamplerComplete(sampler, mTextureCaps, mExtensions, mClientVersion) &&
+ !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial()))
+ {
+ Error error = mRenderer->setSamplerState(shaderType, samplerIndex, sampler);
+ if (error.isError())
+ {
+ return error;
+ }
- texture->resetDirty();
+ error = mRenderer->setTexture(shaderType, samplerIndex, texture);
+ if (error.isError())
+ {
+ return error;
+ }
}
else
{
- mRenderer->setTexture(type, samplerIndex, getIncompleteTexture(textureType));
+ // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture.
+ Texture *incompleteTexture = getIncompleteTexture(textureType);
+ gl::Error error = mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture);
+ if (error.isError())
+ {
+ return error;
+ }
}
}
else
{
- mRenderer->setTexture(type, samplerIndex, NULL);
+ // No texture bound to this slot even though it is used by the shader, bind a NULL texture
+ Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL);
+ if (error.isError())
+ {
+ return error;
+ }
}
}
- for (int samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
+ // Set all the remaining textures to NULL
+ size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? mCaps.maxTextureImageUnits
+ : mCaps.maxVertexTextureImageUnits;
+ for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
{
- mRenderer->setTexture(type, samplerIndex, NULL);
+ Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL);
+ if (error.isError())
+ {
+ return error;
+ }
}
+
+ return Error(GL_NO_ERROR);
}
-void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
+Error Context::applyTextures(ProgramBinary *programBinary)
{
- Framebuffer *framebuffer = getReadFramebuffer();
+ FramebufferTextureSerialArray framebufferSerials;
+ size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&framebufferSerials);
- if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ Error error = applyTextures(programBinary, SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount);
+ if (error.isError())
{
- return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
+ return error;
}
- if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
+ error = applyTextures(programBinary, SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount);
+ if (error.isError())
{
- return gl::error(GL_INVALID_OPERATION);
+ return error;
}
- GLsizei outputPitch = ComputePitch(width, ConvertSizedInternalFormat(format, type), getPackAlignment());
- // sized query sanity check
- if (bufSize)
+ return Error(GL_NO_ERROR);
+}
+
+Error Context::applyUniformBuffers()
+{
+ Program *programObject = getProgram(mState.getCurrentProgramId());
+ ProgramBinary *programBinary = programObject->getProgramBinary();
+
+ std::vector<Buffer*> boundBuffers;
+
+ for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++)
{
- int requiredSize = outputPitch * height;
- if (requiredSize > *bufSize)
+ GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex);
+
+ if (mState.getIndexedUniformBuffer(blockBinding)->id() == 0)
+ {
+ // undefined behaviour
+ return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer.");
+ }
+ else
{
- return gl::error(GL_INVALID_OPERATION);
+ Buffer *uniformBuffer = mState.getIndexedUniformBuffer(blockBinding);
+ ASSERT(uniformBuffer);
+ boundBuffers.push_back(uniformBuffer);
}
}
- mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, getPackReverseRowOrder(), getPackAlignment(), pixels);
+ return programBinary->applyUniformBuffers(boundBuffers, getCaps());
}
-void Context::clear(GLbitfield mask)
+bool Context::applyTransformFeedbackBuffers()
{
- Framebuffer *framebufferObject = getDrawFramebuffer();
+ TransformFeedback *curTransformFeedback = mState.getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
+ {
+ Buffer *transformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
+ GLintptr transformFeedbackOffsets[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
+ for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
+ {
+ transformFeedbackBuffers[i] = mState.getIndexedTransformFeedbackBuffer(i);
+ transformFeedbackOffsets[i] = mState.getIndexedTransformFeedbackBufferOffset(i);
+ }
+ mRenderer->applyTransformFeedbackBuffers(transformFeedbackBuffers, transformFeedbackOffsets);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
- if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
+void Context::markTransformFeedbackUsage()
+{
+ for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
{
- return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
+ Buffer *buffer = mState.getIndexedTransformFeedbackBuffer(i);
+ if (buffer)
+ {
+ buffer->markTransformFeedbackUsage();
+ }
}
+}
- DWORD flags = 0;
- GLbitfield finalMask = 0;
+Error Context::clear(GLbitfield mask)
+{
+ if (mState.isRasterizerDiscardEnabled())
+ {
+ return Error(GL_NO_ERROR);
+ }
+
+ ClearParameters clearParams = mState.getClearParameters(mask);
+
+ applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport
+
+ return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+}
- if (mask & GL_COLOR_BUFFER_BIT)
+Error Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values)
+{
+ if (mState.isRasterizerDiscardEnabled())
{
- mask &= ~GL_COLOR_BUFFER_BIT;
+ return Error(GL_NO_ERROR);
+ }
+
+ // glClearBufferfv can be called to clear the color buffer or depth buffer
+ ClearParameters clearParams = mState.getClearParameters(0);
- if (framebufferObject->hasEnabledColorAttachment())
+ if (buffer == GL_COLOR)
+ {
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
{
- finalMask |= GL_COLOR_BUFFER_BIT;
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
}
+ clearParams.colorFClearValue = ColorF(values[0], values[1], values[2], values[3]);
+ clearParams.colorClearType = GL_FLOAT;
}
- if (mask & GL_DEPTH_BUFFER_BIT)
+ if (buffer == GL_DEPTH)
{
- mask &= ~GL_DEPTH_BUFFER_BIT;
- if (mState.depthStencil.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
- {
- finalMask |= GL_DEPTH_BUFFER_BIT;
- }
+ clearParams.clearDepth = true;
+ clearParams.depthClearValue = values[0];
}
- if (mask & GL_STENCIL_BUFFER_BIT)
+ applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport
+
+ return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+}
+
+Error Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values)
+{
+ if (mState.isRasterizerDiscardEnabled())
{
- mask &= ~GL_STENCIL_BUFFER_BIT;
- if (framebufferObject->getStencilbufferType() != GL_NONE)
- {
- rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
- if (!depthStencil)
- {
- ERR("Depth stencil pointer unexpectedly null.");
- return;
- }
+ return Error(GL_NO_ERROR);
+ }
- if (GetStencilSize(depthStencil->getActualFormat()) > 0)
- {
- finalMask |= GL_STENCIL_BUFFER_BIT;
- }
+ // glClearBufferuv can only be called to clear a color buffer
+ ClearParameters clearParams = mState.getClearParameters(0);
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorUIClearValue = ColorUI(values[0], values[1], values[2], values[3]);
+ clearParams.colorClearType = GL_UNSIGNED_INT;
+
+ applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport
+
+ return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+}
+
+Error Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values)
+{
+ if (mState.isRasterizerDiscardEnabled())
+ {
+ return Error(GL_NO_ERROR);
+ }
+
+ // glClearBufferfv can be called to clear the color buffer or stencil buffer
+ ClearParameters clearParams = mState.getClearParameters(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 = ColorI(values[0], values[1], values[2], values[3]);
+ clearParams.colorClearType = GL_INT;
}
- if (mask != 0)
+ if (buffer == GL_STENCIL)
{
- return gl::error(GL_INVALID_VALUE);
+ clearParams.clearStencil = true;
+ clearParams.stencilClearValue = values[1];
}
- if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport
+ applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport
+
+ return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+}
+
+Error Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil)
+{
+ if (mState.isRasterizerDiscardEnabled())
{
- return;
+ return Error(GL_NO_ERROR);
}
- ClearParameters clearParams;
- clearParams.mask = finalMask;
- clearParams.colorClearValue = mState.colorClearValue;
- clearParams.colorMaskRed = mState.blend.colorMaskRed;
- clearParams.colorMaskGreen = mState.blend.colorMaskGreen;
- clearParams.colorMaskBlue = mState.blend.colorMaskBlue;
- clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha;
- clearParams.depthClearValue = mState.depthClearValue;
- clearParams.stencilClearValue = mState.stencilClearValue;
- clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask;
+ // glClearBufferfi can only be called to clear a depth stencil buffer
+ ClearParameters clearParams = mState.getClearParameters(0);
+ clearParams.clearDepth = true;
+ clearParams.depthClearValue = depth;
+ clearParams.clearStencil = true;
+ clearParams.stencilClearValue = stencil;
+
+ applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport
- mRenderer->clear(clearParams, framebufferObject);
+ return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
}
-void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
+Error Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
{
- if (!mState.currentProgram)
+ Framebuffer *framebuffer = mState.getReadFramebuffer();
+
+ GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
+ const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat);
+ GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, mState.getPackAlignment());
+
+ return mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(),
+ reinterpret_cast<uint8_t*>(pixels));
+}
+
+Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
+{
+ ASSERT(mState.getCurrentProgramId() != 0);
+
+ ProgramBinary *programBinary = mState.getCurrentProgramBinary();
+ programBinary->updateSamplerMapping();
+
+ Error error = generateSwizzles(programBinary);
+ if (error.isError())
{
- return gl::error(GL_INVALID_OPERATION);
+ return error;
}
if (!mRenderer->applyPrimitiveType(mode, count))
{
- return;
+ return Error(GL_NO_ERROR);
+ }
+
+ error = applyRenderTarget(mode, false);
+ if (error.isError())
+ {
+ return error;
}
- if (!applyRenderTarget(mode, false))
+ error = applyState(mode);
+ if (error.isError())
{
- return;
+ return error;
}
- applyState(mode);
+ error = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances);
+ if (error.isError())
+ {
+ return error;
+ }
- ProgramBinary *programBinary = getCurrentProgramBinary();
+ bool transformFeedbackActive = applyTransformFeedbackBuffers();
- GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, first, count, instances);
- if (err != GL_NO_ERROR)
+ error = applyShaders(programBinary, transformFeedbackActive);
+ if (error.isError())
{
- return gl::error(err);
+ return error;
}
- applyShaders();
- applyTextures();
+ error = applyTextures(programBinary);
+ if (error.isError())
+ {
+ return error;
+ }
- if (!programBinary->validateSamplers(NULL))
+ error = applyUniformBuffers();
+ if (error.isError())
{
- return gl::error(GL_INVALID_OPERATION);
+ return error;
}
if (!skipDraw(mode))
{
- mRenderer->drawArrays(mode, count, instances);
+ error = mRenderer->drawArrays(mode, count, instances, transformFeedbackActive);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (transformFeedbackActive)
+ {
+ markTransformFeedbackUsage();
+ }
}
+
+ return gl::Error(GL_NO_ERROR);
}
-void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances)
+Error Context::drawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLsizei instances,
+ const rx::RangeUI &indexRange)
{
- if (!mState.currentProgram)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ ASSERT(mState.getCurrentProgramId() != 0);
+
+ ProgramBinary *programBinary = mState.getCurrentProgramBinary();
+ programBinary->updateSamplerMapping();
- if (!indices && !mState.elementArrayBuffer)
+ Error error = generateSwizzles(programBinary);
+ if (error.isError())
{
- return gl::error(GL_INVALID_OPERATION);
+ return error;
}
-
+
if (!mRenderer->applyPrimitiveType(mode, count))
{
- return;
+ return Error(GL_NO_ERROR);
}
- if (!applyRenderTarget(mode, false))
+ error = applyRenderTarget(mode, false);
+ if (error.isError())
{
- return;
+ return error;
}
- applyState(mode);
+ error = applyState(mode);
+ if (error.isError())
+ {
+ return error;
+ }
+ VertexArray *vao = mState.getVertexArray();
rx::TranslatedIndexData indexInfo;
- GLenum err = mRenderer->applyIndexBuffer(indices, mState.elementArrayBuffer.get(), count, mode, type, &indexInfo);
- if (err != GL_NO_ERROR)
+ indexInfo.indexRange = indexRange;
+ error = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo);
+ if (error.isError())
{
- return gl::error(err);
+ return error;
}
- ProgramBinary *programBinary = getCurrentProgramBinary();
+ GLsizei vertexCount = indexInfo.indexRange.length() + 1;
+ error = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(),
+ mState.getVertexAttribCurrentValues(),
+ indexInfo.indexRange.start, vertexCount, instances);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ bool transformFeedbackActive = applyTransformFeedbackBuffers();
+ // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation
+ // layer.
+ ASSERT(!transformFeedbackActive);
- GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
- err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, indexInfo.minIndex, vertexCount, instances);
- if (err != GL_NO_ERROR)
+ error = applyShaders(programBinary, transformFeedbackActive);
+ if (error.isError())
{
- return gl::error(err);
+ return error;
}
- applyShaders();
- applyTextures();
+ error = applyTextures(programBinary);
+ if (error.isError())
+ {
+ return error;
+ }
- if (!programBinary->validateSamplers(NULL))
+ error = applyUniformBuffers();
+ if (error.isError())
{
- return gl::error(GL_INVALID_OPERATION);
+ return error;
}
if (!skipDraw(mode))
{
- mRenderer->drawElements(mode, count, type, indices, mState.elementArrayBuffer.get(), indexInfo, instances);
+ error = mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances);
+ if (error.isError())
+ {
+ return error;
+ }
}
+
+ return Error(GL_NO_ERROR);
}
// Implements glFlush when block is false, glFinish when block is true
@@ -2060,71 +1905,28 @@ void Context::sync(bool block)
mRenderer->sync(block);
}
-void Context::recordInvalidEnum()
+void Context::recordError(const Error &error)
{
- mInvalidEnum = true;
-}
-
-void Context::recordInvalidValue()
-{
- mInvalidValue = true;
-}
-
-void Context::recordInvalidOperation()
-{
- mInvalidOperation = true;
-}
-
-void Context::recordOutOfMemory()
-{
- mOutOfMemory = true;
-}
-
-void Context::recordInvalidFramebufferOperation()
-{
- mInvalidFramebufferOperation = true;
+ if (error.isError())
+ {
+ mErrors.insert(error.getCode());
+ }
}
// 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 (mInvalidEnum)
- {
- mInvalidEnum = false;
-
- return GL_INVALID_ENUM;
- }
-
- if (mInvalidValue)
+ if (mErrors.empty())
{
- mInvalidValue = false;
-
- return GL_INVALID_VALUE;
+ return GL_NO_ERROR;
}
-
- if (mInvalidOperation)
- {
- mInvalidOperation = false;
-
- return GL_INVALID_OPERATION;
- }
-
- if (mOutOfMemory)
- {
- mOutOfMemory = false;
-
- return GL_OUT_OF_MEMORY;
- }
-
- if (mInvalidFramebufferOperation)
+ else
{
- mInvalidFramebufferOperation = false;
-
- return GL_INVALID_FRAMEBUFFER_OPERATION;
+ GLenum error = *mErrors.begin();
+ mErrors.erase(mErrors.begin());
+ return error;
}
-
- return GL_NO_ERROR;
}
GLenum Context::getResetStatus()
@@ -2147,7 +1949,7 @@ GLenum Context::getResetStatus()
mResetStatus = GL_NO_ERROR;
}
}
-
+
return status;
}
@@ -2156,244 +1958,85 @@ bool Context::isResetNotificationEnabled()
return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
}
-int Context::getMajorShaderModel() const
-{
- return mMajorShaderModel;
-}
-
-float Context::getMaximumPointSize() const
-{
- return mMaximumPointSize;
-}
-
-unsigned int Context::getMaximumCombinedTextureImageUnits() const
-{
- return mRenderer->getMaxCombinedTextureImageUnits();
-}
-
-int Context::getMaxSupportedSamples() const
-{
- return mRenderer->getMaxSupportedSamples();
-}
-
-unsigned int Context::getMaximumRenderTargets() const
-{
- return mRenderer->getMaxRenderTargets();
-}
-
-bool Context::supportsEventQueries() const
-{
- return mSupportsEventQueries;
-}
-
-bool Context::supportsOcclusionQueries() const
+int Context::getClientVersion() const
{
- return mSupportsOcclusionQueries;
+ return mClientVersion;
}
-bool Context::supportsBGRATextures() const
+const Caps &Context::getCaps() const
{
- return mSupportsBGRATextures;
+ return mCaps;
}
-bool Context::supportsDXT1Textures() const
+const TextureCapsMap &Context::getTextureCaps() const
{
- return mSupportsDXT1Textures;
+ return mTextureCaps;
}
-bool Context::supportsDXT3Textures() const
+const Extensions &Context::getExtensions() const
{
- return mSupportsDXT3Textures;
+ return mExtensions;
}
-bool Context::supportsDXT5Textures() const
+void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type)
{
- return mSupportsDXT5Textures;
-}
-
-bool Context::supportsFloat32Textures() const
-{
- return mSupportsFloat32Textures;
-}
-
-bool Context::supportsFloat32LinearFilter() const
-{
- return mSupportsFloat32LinearFilter;
-}
-
-bool Context::supportsFloat32RenderableTextures() const
-{
- return mSupportsFloat32RenderableTextures;
-}
-
-bool Context::supportsFloat16Textures() const
-{
- return mSupportsFloat16Textures;
-}
-
-bool Context::supportsFloat16LinearFilter() const
-{
- return mSupportsFloat16LinearFilter;
-}
-
-bool Context::supportsFloat16RenderableTextures() const
-{
- return mSupportsFloat16RenderableTextures;
-}
+ Framebuffer *framebuffer = mState.getReadFramebuffer();
+ ASSERT(framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE);
-int Context::getMaximumRenderbufferDimension() const
-{
- return mMaxRenderbufferDimension;
-}
+ FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
+ ASSERT(attachment);
-int Context::getMaximumTextureDimension() const
-{
- return mMaxTextureDimension;
-}
+ GLenum actualFormat = attachment->getActualFormat();
+ const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualFormat);
-int Context::getMaximumCubeTextureDimension() const
-{
- return mMaxCubeTextureDimension;
+ *internalFormat = actualFormat;
+ *format = actualFormatInfo.format;
+ *type = actualFormatInfo.type;
}
-int Context::getMaximumTextureLevel() const
-{
- return mMaxTextureLevel;
-}
-
-bool Context::supportsLuminanceTextures() const
-{
- return mSupportsLuminanceTextures;
-}
-
-bool Context::supportsLuminanceAlphaTextures() const
-{
- return mSupportsLuminanceAlphaTextures;
-}
-
-bool Context::supportsDepthTextures() const
-{
- return mSupportsDepthTextures;
-}
-
-bool Context::supports32bitIndices() const
-{
- return mSupports32bitIndices;
-}
-
-bool Context::supportsNonPower2Texture() const
-{
- return mSupportsNonPower2Texture;
-}
-
-bool Context::supportsInstancing() const
-{
- return mSupportsInstancing;
-}
-
-bool Context::supportsTextureFilterAnisotropy() const
-{
- return mSupportsTextureFilterAnisotropy;
-}
-
-float Context::getTextureMaxAnisotropy() const
-{
- return mMaxTextureAnisotropy;
-}
-
-bool Context::getCurrentReadFormatType(GLenum *format, GLenum *type)
+void Context::detachTexture(GLuint texture)
{
- Framebuffer *framebuffer = getReadFramebuffer();
- if (!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
- {
- return gl::error(GL_INVALID_OPERATION, false);
- }
-
- Renderbuffer *renderbuffer = framebuffer->getReadColorbuffer();
- if (!renderbuffer)
- {
- return gl::error(GL_INVALID_OPERATION, false);
- }
-
- *format = gl::ExtractFormat(renderbuffer->getActualFormat());
- *type = gl::ExtractType(renderbuffer->getActualFormat());
-
- return true;
+ // Simple pass-through to State's detachTexture method, as textures do not require
+ // allocation map management either here or in the resource manager at detach time.
+ // Zero textures are held by the Context, and we don't attempt to request them from
+ // the State.
+ mState.detachTexture(texture);
}
void Context::detachBuffer(GLuint buffer)
{
+ // Buffer detachment is handled by Context, because the buffer must also be
+ // attached from any VAOs in existence, and Context holds the VAO map.
+
// [OpenGL ES 2.0.24] section 2.9 page 22:
// If a buffer object is deleted while it is bound, all bindings to that object in the current context
// (i.e. in the thread that called Delete-Buffers) are reset to zero.
- if (mState.arrayBuffer.id() == buffer)
- {
- mState.arrayBuffer.set(NULL);
- }
-
- if (mState.elementArrayBuffer.id() == buffer)
- {
- mState.elementArrayBuffer.set(NULL);
- }
+ mState.removeArrayBufferBinding(buffer);
- for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
+ // mark as freed among the vertex array objects
+ for (auto vaoIt = mVertexArrayMap.begin(); vaoIt != mVertexArrayMap.end(); vaoIt++)
{
- if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
- {
- mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
- }
- }
-}
-
-void Context::detachTexture(GLuint texture)
-{
- // [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 (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
- {
- for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
- {
- if (mState.samplerTexture[type][sampler].id() == texture)
- {
- mState.samplerTexture[type][sampler].set(NULL);
- }
- }
- }
-
- // [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 FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
- // image was attached in the currently bound framebuffer.
-
- Framebuffer *readFramebuffer = getReadFramebuffer();
- Framebuffer *drawFramebuffer = getDrawFramebuffer();
-
- if (readFramebuffer)
- {
- readFramebuffer->detachTexture(texture);
- }
-
- if (drawFramebuffer && drawFramebuffer != readFramebuffer)
- {
- drawFramebuffer->detachTexture(texture);
+ vaoIt->second->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 (mState.readFramebuffer == framebuffer)
+ if (mState.removeReadFramebufferBinding(framebuffer))
{
bindReadFramebuffer(0);
}
- if (mState.drawFramebuffer == framebuffer)
+ if (mState.removeDrawFramebufferBinding(framebuffer))
{
bindDrawFramebuffer(0);
}
@@ -2401,76 +2044,94 @@ void Context::detachFramebuffer(GLuint framebuffer)
void Context::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 (mState.renderbuffer.id() == renderbuffer)
- {
- bindRenderbuffer(0);
- }
-
- // [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.
+ mState.detachRenderbuffer(renderbuffer);
+}
- Framebuffer *readFramebuffer = getReadFramebuffer();
- Framebuffer *drawFramebuffer = getDrawFramebuffer();
+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.
- if (readFramebuffer)
+ // [OpenGL ES 3.0.2] section 2.10 page 43:
+ // If a vertex array object that is currently bound is deleted, the binding
+ // for that object reverts to zero and the default vertex array becomes current.
+ if (mState.removeVertexArrayBinding(vertexArray))
{
- readFramebuffer->detachRenderbuffer(renderbuffer);
+ bindVertexArray(0);
}
+}
- if (drawFramebuffer && drawFramebuffer != readFramebuffer)
- {
- drawFramebuffer->detachRenderbuffer(renderbuffer);
- }
+void Context::detachTransformFeedback(GLuint transformFeedback)
+{
+ mState.detachTransformFeedback(transformFeedback);
}
-Texture *Context::getIncompleteTexture(TextureType type)
+void Context::detachSampler(GLuint sampler)
{
- Texture *t = mIncompleteTextures[type].get();
+ mState.detachSampler(sampler);
+}
- if (t == NULL)
+Texture *Context::getIncompleteTexture(GLenum type)
+{
+ if (mIncompleteTextures.find(type) == mIncompleteTextures.end())
{
- static const GLubyte color[] = { 0, 0, 0, 255 };
+ const GLubyte color[] = { 0, 0, 0, 255 };
+ const PixelUnpackState incompleteUnpackState(1);
+ Texture* t = NULL;
switch (type)
{
default:
UNREACHABLE();
// default falls through to TEXTURE_2D
- case TEXTURE_2D:
+ case GL_TEXTURE_2D:
{
- Texture2D *incomplete2d = new Texture2D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID);
- incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), Texture::INCOMPLETE_TEXTURE_ID);
+ incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
t = incomplete2d;
}
break;
- case TEXTURE_CUBE:
+ case GL_TEXTURE_CUBE_MAP:
{
- TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer, Texture::INCOMPLETE_TEXTURE_ID);
+ TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), Texture::INCOMPLETE_TEXTURE_ID);
- incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
- incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
- incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
- incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
- incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
- incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+ incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+ incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+ incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+ incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+ incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
t = incompleteCube;
}
break;
+
+ case GL_TEXTURE_3D:
+ {
+ Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), Texture::INCOMPLETE_TEXTURE_ID);
+ incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+
+ t = incomplete3d;
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), Texture::INCOMPLETE_TEXTURE_ID);
+ incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+
+ t = incomplete2darray;
+ }
+ break;
}
mIncompleteTextures[type].set(t);
}
- return t;
+ return mIncompleteTextures[type].get();
}
bool Context::skipDraw(GLenum drawMode)
@@ -2480,9 +2141,9 @@ bool Context::skipDraw(GLenum drawMode)
// 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 (!getCurrentProgramBinary()->usesPointSize())
+ if (!mState.getCurrentProgramBinary()->usesPointSize())
{
- // This is stictly speaking not an error, but developers should be
+ // This is stictly speaking not an error, but developers should be
// notified of risking undefined behavior.
ERR("Point rendering without writing to gl_PointSize.");
@@ -2491,7 +2152,7 @@ bool Context::skipDraw(GLenum drawMode)
}
else if (IsTriangleMode(drawMode))
{
- if (mState.rasterizer.cullFace && mState.rasterizer.cullMode == GL_FRONT_AND_BACK)
+ if (mState.getRasterizerState().cullFace && mState.getRasterizerState().cullMode == GL_FRONT_AND_BACK)
{
return true;
}
@@ -2500,148 +2161,97 @@ bool Context::skipDraw(GLenum drawMode)
return false;
}
-void Context::setVertexAttrib(GLuint index, const GLfloat *values)
-{
- ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
-
- mState.vertexAttribute[index].mCurrentValue[0] = values[0];
- mState.vertexAttribute[index].mCurrentValue[1] = values[1];
- mState.vertexAttribute[index].mCurrentValue[2] = values[2];
- mState.vertexAttribute[index].mCurrentValue[3] = values[3];
-}
-
void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
{
- ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
-
- mState.vertexAttribute[index].mDivisor = divisor;
+ mState.getVertexArray()->setVertexAttribDivisor(index, divisor);
}
-// keep list sorted in following order
-// OES extensions
-// EXT extensions
-// Vendor extensions
-void Context::initExtensionString()
+void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param)
{
- std::string extensionString = "";
+ mResourceManager->checkSamplerAllocation(sampler);
- // OES extensions
- if (supports32bitIndices())
- {
- extensionString += "GL_OES_element_index_uint ";
- }
+ Sampler *samplerObject = getSampler(sampler);
+ ASSERT(samplerObject);
- extensionString += "GL_OES_packed_depth_stencil ";
- extensionString += "GL_OES_get_program_binary ";
- extensionString += "GL_OES_rgb8_rgba8 ";
- if (mRenderer->getDerivativeInstructionSupport())
- {
- extensionString += "GL_OES_standard_derivatives ";
- }
-
- if (supportsFloat16Textures())
- {
- extensionString += "GL_OES_texture_half_float ";
- }
- if (supportsFloat16LinearFilter())
- {
- extensionString += "GL_OES_texture_half_float_linear ";
- }
- if (supportsFloat32Textures())
- {
- extensionString += "GL_OES_texture_float ";
- }
- if (supportsFloat32LinearFilter())
- {
- extensionString += "GL_OES_texture_float_linear ";
- }
-
- if (supportsNonPower2Texture())
- {
- extensionString += "GL_OES_texture_npot ";
- }
-
- // Multi-vendor (EXT) extensions
- if (supportsOcclusionQueries())
- {
- extensionString += "GL_EXT_occlusion_query_boolean ";
- }
-
- extensionString += "GL_EXT_read_format_bgra ";
- extensionString += "GL_EXT_robustness ";
-
- if (supportsDXT1Textures())
- {
- extensionString += "GL_EXT_texture_compression_dxt1 ";
- }
-
- if (supportsTextureFilterAnisotropy())
- {
- extensionString += "GL_EXT_texture_filter_anisotropic ";
- }
-
- if (supportsBGRATextures())
- {
- extensionString += "GL_EXT_texture_format_BGRA8888 ";
- }
-
- if (mRenderer->getMaxRenderTargets() > 1)
+ switch (pname)
{
- extensionString += "GL_EXT_draw_buffers ";
+ case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast<GLenum>(param)); break;
+ case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast<GLenum>(param)); break;
+ case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast<GLenum>(param)); break;
+ case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast<GLenum>(param)); break;
+ case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast<GLenum>(param)); break;
+ case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(static_cast<GLfloat>(param)); break;
+ case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(static_cast<GLfloat>(param)); break;
+ case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(static_cast<GLenum>(param)); break;
+ case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(static_cast<GLenum>(param)); break;
+ default: UNREACHABLE(); break;
}
+}
- extensionString += "GL_EXT_texture_storage ";
- extensionString += "GL_EXT_frag_depth ";
+void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
+{
+ mResourceManager->checkSamplerAllocation(sampler);
- // ANGLE-specific extensions
- if (supportsDepthTextures())
- {
- extensionString += "GL_ANGLE_depth_texture ";
- }
+ Sampler *samplerObject = getSampler(sampler);
+ ASSERT(samplerObject);
- extensionString += "GL_ANGLE_framebuffer_blit ";
- if (getMaxSupportedSamples() != 0)
+ switch (pname)
{
- extensionString += "GL_ANGLE_framebuffer_multisample ";
+ case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(uiround<GLenum>(param)); break;
+ case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(uiround<GLenum>(param)); break;
+ case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(uiround<GLenum>(param)); break;
+ case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(uiround<GLenum>(param)); break;
+ case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(uiround<GLenum>(param)); break;
+ case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break;
+ case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break;
+ case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(uiround<GLenum>(param)); break;
+ case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(uiround<GLenum>(param)); break;
+ default: UNREACHABLE(); break;
}
+}
- if (supportsInstancing())
- {
- extensionString += "GL_ANGLE_instanced_arrays ";
- }
+GLint Context::getSamplerParameteri(GLuint sampler, GLenum pname)
+{
+ mResourceManager->checkSamplerAllocation(sampler);
- extensionString += "GL_ANGLE_pack_reverse_row_order ";
+ Sampler *samplerObject = getSampler(sampler);
+ ASSERT(samplerObject);
- if (supportsDXT3Textures())
- {
- extensionString += "GL_ANGLE_texture_compression_dxt3 ";
- }
- if (supportsDXT5Textures())
+ switch (pname)
{
- extensionString += "GL_ANGLE_texture_compression_dxt5 ";
+ case GL_TEXTURE_MIN_FILTER: return static_cast<GLint>(samplerObject->getMinFilter());
+ case GL_TEXTURE_MAG_FILTER: return static_cast<GLint>(samplerObject->getMagFilter());
+ case GL_TEXTURE_WRAP_S: return static_cast<GLint>(samplerObject->getWrapS());
+ case GL_TEXTURE_WRAP_T: return static_cast<GLint>(samplerObject->getWrapT());
+ case GL_TEXTURE_WRAP_R: return static_cast<GLint>(samplerObject->getWrapR());
+ case GL_TEXTURE_MIN_LOD: return uiround<GLint>(samplerObject->getMinLod());
+ case GL_TEXTURE_MAX_LOD: return uiround<GLint>(samplerObject->getMaxLod());
+ case GL_TEXTURE_COMPARE_MODE: return static_cast<GLint>(samplerObject->getComparisonMode());
+ case GL_TEXTURE_COMPARE_FUNC: return static_cast<GLint>(samplerObject->getComparisonFunc());
+ default: UNREACHABLE(); return 0;
}
+}
- extensionString += "GL_ANGLE_texture_usage ";
- extensionString += "GL_ANGLE_translated_shader_source ";
+GLfloat Context::getSamplerParameterf(GLuint sampler, GLenum pname)
+{
+ mResourceManager->checkSamplerAllocation(sampler);
- // Other vendor-specific extensions
- if (supportsEventQueries())
- {
- extensionString += "GL_NV_fence ";
- }
+ Sampler *samplerObject = getSampler(sampler);
+ ASSERT(samplerObject);
- std::string::size_type end = extensionString.find_last_not_of(' ');
- if (end != std::string::npos)
+ switch (pname)
{
- extensionString.resize(end+1);
+ case GL_TEXTURE_MIN_FILTER: return static_cast<GLfloat>(samplerObject->getMinFilter());
+ case GL_TEXTURE_MAG_FILTER: return static_cast<GLfloat>(samplerObject->getMagFilter());
+ case GL_TEXTURE_WRAP_S: return static_cast<GLfloat>(samplerObject->getWrapS());
+ case GL_TEXTURE_WRAP_T: return static_cast<GLfloat>(samplerObject->getWrapT());
+ case GL_TEXTURE_WRAP_R: return static_cast<GLfloat>(samplerObject->getWrapR());
+ case GL_TEXTURE_MIN_LOD: return samplerObject->getMinLod();
+ case GL_TEXTURE_MAX_LOD: return samplerObject->getMaxLod();
+ case GL_TEXTURE_COMPARE_MODE: return static_cast<GLfloat>(samplerObject->getComparisonMode());
+ case GL_TEXTURE_COMPARE_FUNC: return static_cast<GLfloat>(samplerObject->getComparisonFunc());
+ default: UNREACHABLE(); return 0;
}
-
- mExtensionString = makeStaticString(extensionString);
-}
-
-const char *Context::getExtensionString() const
-{
- return mExtensionString;
}
void Context::initRendererString()
@@ -2651,329 +2261,168 @@ void Context::initRendererString()
rendererString << mRenderer->getRendererDescription();
rendererString << ")";
- mRendererString = makeStaticString(rendererString.str());
+ mRendererString = MakeStaticString(rendererString.str());
}
-const char *Context::getRendererString() const
+const std::string &Context::getRendererString() const
{
return mRendererString;
}
-Context::FramebufferTextureSerialSet Context::getBoundFramebufferTextureSerials()
+void Context::initExtensionStrings()
{
- FramebufferTextureSerialSet set;
+ mExtensionStrings = mExtensions.getStrings();
- Framebuffer *drawFramebuffer = getDrawFramebuffer();
- for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
- {
- Renderbuffer *renderBuffer = drawFramebuffer->getColorbuffer(i);
- if (renderBuffer && renderBuffer->getTextureSerial() != 0)
- {
- set.insert(renderBuffer->getTextureSerial());
- }
- }
-
- Renderbuffer *depthStencilBuffer = drawFramebuffer->getDepthOrStencilbuffer();
- if (depthStencilBuffer && depthStencilBuffer->getTextureSerial() != 0)
- {
- set.insert(depthStencilBuffer->getTextureSerial());
- }
-
- return set;
+ std::ostringstream combinedStringStream;
+ std::copy(mExtensionStrings.begin(), mExtensionStrings.end(), std::ostream_iterator<std::string>(combinedStringStream, " "));
+ mExtensionString = combinedStringStream.str();
}
-void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask)
+const std::string &Context::getExtensionString() const
{
- Framebuffer *readFramebuffer = getReadFramebuffer();
- Framebuffer *drawFramebuffer = getDrawFramebuffer();
-
- if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
- !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
- {
- return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
- }
-
- if (drawFramebuffer->getSamples() != 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
- Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
+ return mExtensionString;
+}
- if (drawColorBuffer == NULL)
- {
- ERR("Draw buffers formats don't match, which is not supported in this implementation of BlitFramebufferANGLE");
- return gl::error(GL_INVALID_OPERATION);
- }
+const std::string &Context::getExtensionString(size_t idx) const
+{
+ return mExtensionStrings[idx];
+}
- int readBufferWidth = readColorBuffer->getWidth();
- int readBufferHeight = readColorBuffer->getHeight();
- int drawBufferWidth = drawColorBuffer->getWidth();
- int drawBufferHeight = drawColorBuffer->getHeight();
+size_t Context::getExtensionStringCount() const
+{
+ return mExtensionStrings.size();
+}
- Rectangle sourceRect;
- Rectangle destRect;
+size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray)
+{
+ size_t serialCount = 0;
- if (srcX0 < srcX1)
- {
- sourceRect.x = srcX0;
- destRect.x = dstX0;
- sourceRect.width = srcX1 - srcX0;
- destRect.width = dstX1 - dstX0;
- }
- else
+ Framebuffer *drawFramebuffer = mState.getDrawFramebuffer();
+ for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
{
- sourceRect.x = srcX1;
- destRect.x = dstX1;
- sourceRect.width = srcX0 - srcX1;
- destRect.width = dstX0 - dstX1;
+ FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i);
+ if (attachment && attachment->isTexture())
+ {
+ Texture *texture = attachment->getTexture();
+ (*outSerialArray)[serialCount++] = texture->getTextureSerial();
+ }
}
- if (srcY0 < srcY1)
- {
- sourceRect.height = srcY1 - srcY0;
- destRect.height = dstY1 - dstY0;
- sourceRect.y = srcY0;
- destRect.y = dstY0;
- }
- else
+ FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer();
+ if (depthStencilAttachment && depthStencilAttachment->isTexture())
{
- sourceRect.height = srcY0 - srcY1;
- destRect.height = dstY0 - srcY1;
- sourceRect.y = srcY1;
- destRect.y = dstY1;
+ Texture *depthStencilTexture = depthStencilAttachment->getTexture();
+ (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial();
}
- Rectangle sourceScissoredRect = sourceRect;
- Rectangle destScissoredRect = destRect;
-
- if (mState.scissorTest)
- {
- // Only write to parts of the destination framebuffer which pass the scissor test.
- if (destRect.x < mState.scissor.x)
- {
- int xDiff = mState.scissor.x - destRect.x;
- destScissoredRect.x = mState.scissor.x;
- destScissoredRect.width -= xDiff;
- sourceScissoredRect.x += xDiff;
- sourceScissoredRect.width -= xDiff;
+ std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount);
- }
-
- if (destRect.x + destRect.width > mState.scissor.x + mState.scissor.width)
- {
- int xDiff = (destRect.x + destRect.width) - (mState.scissor.x + mState.scissor.width);
- destScissoredRect.width -= xDiff;
- sourceScissoredRect.width -= xDiff;
- }
-
- if (destRect.y < mState.scissor.y)
- {
- int yDiff = mState.scissor.y - destRect.y;
- destScissoredRect.y = mState.scissor.y;
- destScissoredRect.height -= yDiff;
- sourceScissoredRect.y += yDiff;
- sourceScissoredRect.height -= yDiff;
- }
+ return serialCount;
+}
- if (destRect.y + destRect.height > mState.scissor.y + mState.scissor.height)
- {
- int yDiff = (destRect.y + destRect.height) - (mState.scissor.y + mState.scissor.height);
- destScissoredRect.height -= yDiff;
- sourceScissoredRect.height -= yDiff;
- }
- }
+void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ Framebuffer *readFramebuffer = mState.getReadFramebuffer();
+ Framebuffer *drawFramebuffer = mState.getDrawFramebuffer();
bool blitRenderTarget = false;
- bool blitDepthStencil = false;
-
- Rectangle sourceTrimmedRect = sourceScissoredRect;
- Rectangle destTrimmedRect = destScissoredRect;
-
- // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of
- // the actual draw and read surfaces.
- if (sourceTrimmedRect.x < 0)
+ bool blitDepth = false;
+ bool blitStencil = false;
+ if ((mask & GL_COLOR_BUFFER_BIT) && readFramebuffer->getReadColorbuffer() && drawFramebuffer->getFirstColorbuffer())
{
- int xDiff = 0 - sourceTrimmedRect.x;
- sourceTrimmedRect.x = 0;
- sourceTrimmedRect.width -= xDiff;
- destTrimmedRect.x += xDiff;
- destTrimmedRect.width -= xDiff;
+ blitRenderTarget = true;
}
-
- if (sourceTrimmedRect.x + sourceTrimmedRect.width > readBufferWidth)
+ if ((mask & GL_STENCIL_BUFFER_BIT) && readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
{
- int xDiff = (sourceTrimmedRect.x + sourceTrimmedRect.width) - readBufferWidth;
- sourceTrimmedRect.width -= xDiff;
- destTrimmedRect.width -= xDiff;
+ blitStencil = true;
}
-
- if (sourceTrimmedRect.y < 0)
+ if ((mask & GL_DEPTH_BUFFER_BIT) && readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
{
- int yDiff = 0 - sourceTrimmedRect.y;
- sourceTrimmedRect.y = 0;
- sourceTrimmedRect.height -= yDiff;
- destTrimmedRect.y += yDiff;
- destTrimmedRect.height -= yDiff;
+ blitDepth = true;
}
- if (sourceTrimmedRect.y + sourceTrimmedRect.height > readBufferHeight)
+ Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
+ Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
+ if (blitRenderTarget || blitDepth || blitStencil)
{
- int yDiff = (sourceTrimmedRect.y + sourceTrimmedRect.height) - readBufferHeight;
- sourceTrimmedRect.height -= yDiff;
- destTrimmedRect.height -= yDiff;
+ const Rectangle *scissor = mState.isScissorTestEnabled() ? &mState.getScissor() : NULL;
+ mRenderer->blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor,
+ blitRenderTarget, blitDepth, blitStencil, filter);
}
+}
- if (destTrimmedRect.x < 0)
- {
- int xDiff = 0 - destTrimmedRect.x;
- destTrimmedRect.x = 0;
- destTrimmedRect.width -= xDiff;
- sourceTrimmedRect.x += xDiff;
- sourceTrimmedRect.width -= xDiff;
- }
+void Context::releaseShaderCompiler()
+{
+ mRenderer->releaseShaderCompiler();
+}
- if (destTrimmedRect.x + destTrimmedRect.width > drawBufferWidth)
- {
- int xDiff = (destTrimmedRect.x + destTrimmedRect.width) - drawBufferWidth;
- destTrimmedRect.width -= xDiff;
- sourceTrimmedRect.width -= xDiff;
- }
+void Context::initCaps(GLuint clientVersion)
+{
+ mCaps = mRenderer->getRendererCaps();
- if (destTrimmedRect.y < 0)
- {
- int yDiff = 0 - destTrimmedRect.y;
- destTrimmedRect.y = 0;
- destTrimmedRect.height -= yDiff;
- sourceTrimmedRect.y += yDiff;
- sourceTrimmedRect.height -= yDiff;
- }
+ mExtensions = mRenderer->getRendererExtensions();
- if (destTrimmedRect.y + destTrimmedRect.height > drawBufferHeight)
+ if (clientVersion < 3)
{
- int yDiff = (destTrimmedRect.y + destTrimmedRect.height) - drawBufferHeight;
- destTrimmedRect.height -= yDiff;
- sourceTrimmedRect.height -= yDiff;
+ // Disable ES3+ extensions
+ mExtensions.colorBufferFloat = false;
}
- bool partialBufferCopy = false;
- if (sourceTrimmedRect.height < readBufferHeight ||
- sourceTrimmedRect.width < readBufferWidth ||
- destTrimmedRect.height < drawBufferHeight ||
- destTrimmedRect.width < drawBufferWidth ||
- sourceTrimmedRect.y != 0 || destTrimmedRect.y != 0 || sourceTrimmedRect.x != 0 || destTrimmedRect.x != 0)
+ if (clientVersion > 2)
{
- partialBufferCopy = true;
+ // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts
+ //mExtensions.sRGB = false;
}
- if (mask & GL_COLOR_BUFFER_BIT)
- {
- const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
- const bool validReadType = (readColorbufferType == GL_TEXTURE_2D) || (readColorbufferType == GL_RENDERBUFFER);
- bool validDrawType = true;
- bool validDrawFormat = true;
-
- for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
- {
- if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
- drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
- {
- validDrawType = false;
- }
+ // 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);
- if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
- {
- validDrawFormat = false;
- }
- }
- }
+ mCaps.maxFragmentInputComponents = std::min<GLuint>(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
- if (!validReadType || !validDrawType || !validDrawFormat)
- {
- ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
- return gl::error(GL_INVALID_OPERATION);
- }
-
- if (partialBufferCopy && readFramebuffer->getSamples() != 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- blitRenderTarget = true;
-
- }
+ GLuint maxSamples = 0;
+ mCaps.compressedTextureFormats.clear();
- if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
+ const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps();
+ for (TextureCapsMap::const_iterator i = rendererFormats.begin(); i != rendererFormats.end(); i++)
{
- Renderbuffer *readDSBuffer = NULL;
- Renderbuffer *drawDSBuffer = NULL;
+ GLenum format = i->first;
+ TextureCaps formatCaps = i->second;
- // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
- // both a depth and stencil buffer, it will be the same buffer.
+ const InternalFormat &formatInfo = GetInternalFormatInfo(format);
- if (mask & GL_DEPTH_BUFFER_BIT)
- {
- if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
- {
- if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
- readFramebuffer->getDepthbuffer()->getActualFormat() != drawFramebuffer->getDepthbuffer()->getActualFormat())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ // Update the format caps based on the client version and extensions
+ formatCaps.texturable = formatInfo.textureSupport(clientVersion, mExtensions);
+ formatCaps.renderable = formatInfo.renderSupport(clientVersion, mExtensions);
+ formatCaps.filterable = formatInfo.filterSupport(clientVersion, mExtensions);
- blitDepthStencil = true;
- readDSBuffer = readFramebuffer->getDepthbuffer();
- drawDSBuffer = drawFramebuffer->getDepthbuffer();
- }
- }
-
- if (mask & GL_STENCIL_BUFFER_BIT)
+ // OpenGL ES does not support multisampling with integer formats
+ if (!formatInfo.renderSupport || formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT)
{
- if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
- {
- if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
- readFramebuffer->getStencilbuffer()->getActualFormat() != drawFramebuffer->getStencilbuffer()->getActualFormat())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- blitDepthStencil = true;
- readDSBuffer = readFramebuffer->getStencilbuffer();
- drawDSBuffer = drawFramebuffer->getStencilbuffer();
- }
+ formatCaps.sampleCounts.clear();
}
+ maxSamples = std::max(maxSamples, formatCaps.getMaxSamples());
- if (partialBufferCopy)
+ if (formatCaps.texturable && formatInfo.compressed)
{
- ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
- return gl::error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted
+ mCaps.compressedTextureFormats.push_back(format);
}
- if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) ||
- (readDSBuffer && readDSBuffer->getSamples() != 0))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ mTextureCaps.insert(format, formatCaps);
}
- if (blitRenderTarget || blitDepthStencil)
- {
- mRenderer->blitRect(readFramebuffer, sourceTrimmedRect, drawFramebuffer, destTrimmedRect, blitRenderTarget, blitDepthStencil);
- }
+ mExtensions.maxSamples = maxSamples;
}
}
extern "C"
{
-gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
+gl::Context *glCreateContext(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
{
- return new gl::Context(shareContext, renderer, notifyResets, robustAccess);
+ return new gl::Context(clientVersion, shareContext, renderer, notifyResets, robustAccess);
}
void glDestroyContext(gl::Context *context)
diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h
index 3dc95e3b95..1b888aec83 100644
--- a/src/3rdparty/angle/src/libGLESv2/Context.h
+++ b/src/3rdparty/angle/src/libGLESv2/Context.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -10,26 +10,23 @@
#ifndef LIBGLESV2_CONTEXT_H_
#define LIBGLESV2_CONTEXT_H_
-#define GL_APICALL
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#define EGLAPI
-#include <EGL/egl.h>
-
-#include <string>
-#include <map>
-#include <set>
-#ifdef _MSC_VER
-#include <hash_map>
-#else
-#include <unordered_map>
-#endif
-
#include "common/angleutils.h"
#include "common/RefCountObject.h"
+#include "libGLESv2/Caps.h"
+#include "libGLESv2/Error.h"
#include "libGLESv2/HandleAllocator.h"
#include "libGLESv2/angletypes.h"
#include "libGLESv2/Constants.h"
+#include "libGLESv2/VertexAttribute.h"
+#include "libGLESv2/State.h"
+
+#include "angle_gl.h"
+
+#include <string>
+#include <set>
+#include <map>
+#include <unordered_map>
+#include <array>
namespace rx
{
@@ -49,6 +46,8 @@ class ProgramBinary;
class Texture;
class Texture2D;
class TextureCubeMap;
+class Texture3D;
+class Texture2DArray;
class Framebuffer;
class Renderbuffer;
class RenderbufferStorage;
@@ -56,222 +55,28 @@ class Colorbuffer;
class Depthbuffer;
class Stencilbuffer;
class DepthStencilbuffer;
-class Fence;
+class FenceNV;
+class FenceSync;
class Query;
class ResourceManager;
class Buffer;
-
-enum QueryType
-{
- QUERY_ANY_SAMPLES_PASSED,
- QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE,
-
- QUERY_TYPE_COUNT
-};
-
-// Helper structure describing a single vertex attribute
-class VertexAttribute
-{
- public:
- VertexAttribute() : mType(GL_FLOAT), mSize(4), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false), mDivisor(0)
- {
- mCurrentValue[0] = 0.0f;
- mCurrentValue[1] = 0.0f;
- mCurrentValue[2] = 0.0f;
- mCurrentValue[3] = 1.0f;
- }
-
- int typeSize() const
- {
- switch (mType)
- {
- case GL_BYTE: return mSize * sizeof(GLbyte);
- case GL_UNSIGNED_BYTE: return mSize * sizeof(GLubyte);
- case GL_SHORT: return mSize * sizeof(GLshort);
- case GL_UNSIGNED_SHORT: return mSize * sizeof(GLushort);
- case GL_FIXED: return mSize * sizeof(GLfixed);
- case GL_FLOAT: return mSize * sizeof(GLfloat);
- default: UNREACHABLE(); return mSize * sizeof(GLfloat);
- }
- }
-
- GLsizei stride() const
- {
- return mStride ? mStride : typeSize();
- }
-
- // From glVertexAttribPointer
- GLenum mType;
- GLint mSize;
- bool mNormalized;
- GLsizei mStride; // 0 means natural stride
-
- union
- {
- const void *mPointer;
- intptr_t mOffset;
- };
-
- BindingPointer<Buffer> mBoundBuffer; // Captured when glVertexAttribPointer is called.
-
- bool mArrayEnabled; // From glEnable/DisableVertexAttribArray
- float mCurrentValue[4]; // From glVertexAttrib
- unsigned int mDivisor;
-};
-
-// Helper structure to store all raw state
-struct State
-{
- Color colorClearValue;
- GLclampf depthClearValue;
- int stencilClearValue;
-
- RasterizerState rasterizer;
- bool scissorTest;
- Rectangle scissor;
-
- BlendState blend;
- Color blendColor;
- bool sampleCoverage;
- GLclampf sampleCoverageValue;
- bool sampleCoverageInvert;
-
- DepthStencilState depthStencil;
- GLint stencilRef;
- GLint stencilBackRef;
-
- GLfloat lineWidth;
-
- GLenum generateMipmapHint;
- GLenum fragmentShaderDerivativeHint;
-
- Rectangle viewport;
- float zNear;
- float zFar;
-
- unsigned int activeSampler; // Active texture unit selector - GL_TEXTURE0
- BindingPointer<Buffer> arrayBuffer;
- BindingPointer<Buffer> elementArrayBuffer;
- GLuint readFramebuffer;
- GLuint drawFramebuffer;
- BindingPointer<Renderbuffer> renderbuffer;
- GLuint currentProgram;
-
- VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS];
- BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
- BindingPointer<Query> activeQuery[QUERY_TYPE_COUNT];
-
- GLint unpackAlignment;
- GLint packAlignment;
- bool packReverseRowOrder;
-};
+struct VertexAttribute;
+class VertexArray;
+class Sampler;
+class TransformFeedback;
class Context
{
public:
- Context(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
+ Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
- ~Context();
+ virtual ~Context();
void makeCurrent(egl::Surface *surface);
virtual void markContextLost();
bool isContextLost();
- // State manipulation
- void setClearColor(float red, float green, float blue, float alpha);
-
- void setClearDepth(float depth);
-
- void setClearStencil(int stencil);
-
- void setCullFace(bool enabled);
- bool isCullFaceEnabled() const;
-
- void setCullMode(GLenum mode);
-
- void setFrontFace(GLenum front);
-
- void setDepthTest(bool enabled);
- bool isDepthTestEnabled() const;
-
- void setDepthFunc(GLenum depthFunc);
-
- void setDepthRange(float zNear, float zFar);
-
- void setBlend(bool enabled);
- bool isBlendEnabled() const;
-
- 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);
-
- void setStencilTest(bool enabled);
- bool isStencilTestEnabled() const;
-
- 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);
-
- void setPolygonOffsetFill(bool enabled);
- bool isPolygonOffsetFillEnabled() const;
-
- void setPolygonOffsetParams(GLfloat factor, GLfloat units);
-
- void setSampleAlphaToCoverage(bool enabled);
- bool isSampleAlphaToCoverageEnabled() const;
-
- void setSampleCoverage(bool enabled);
- bool isSampleCoverageEnabled() const;
-
- void setSampleCoverageParams(GLclampf value, bool invert);
-
- void setScissorTest(bool enabled);
- bool isScissorTestEnabled() const;
-
- void setDither(bool enabled);
- bool isDitherEnabled() const;
-
- void setLineWidth(GLfloat width);
-
- void setGenerateMipmapHint(GLenum hint);
- void setFragmentShaderDerivativeHint(GLenum hint);
-
- void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
-
- void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height);
-
- void setColorMask(bool red, bool green, bool blue, bool alpha);
- void setDepthMask(bool mask);
-
- void setActiveSampler(unsigned int active);
-
- GLuint getReadFramebufferHandle() const;
- GLuint getDrawFramebufferHandle() const;
- GLuint getRenderbufferHandle() const;
-
- GLuint getArrayBufferHandle() const;
-
- GLuint getActiveQuery(GLenum target) const;
-
- void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);
- const VertexAttribute &getVertexAttribState(unsigned int attribNum);
- void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type,
- bool normalized, GLsizei stride, const void *pointer);
- const void *getVertexAttribPointer(unsigned int attribNum) const;
-
- void setUnpackAlignment(GLint alignment);
- GLint getUnpackAlignment() const;
-
- void setPackAlignment(GLint alignment);
- GLint getPackAlignment() const;
-
- void setPackReverseRowOrder(bool reverseRowOrder);
- bool getPackReverseRowOrder() const;
-
// These create and destroy methods are merely pass-throughs to
// ResourceManager, which owns these object types
GLuint createBuffer();
@@ -279,189 +84,227 @@ class Context
GLuint createProgram();
GLuint createTexture();
GLuint createRenderbuffer();
+ GLuint createSampler();
+ GLuint createTransformFeedback();
+ GLsync createFenceSync(GLenum condition);
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);
// Framebuffers are owned by the Context, so these methods do not pass through
GLuint createFramebuffer();
void deleteFramebuffer(GLuint framebuffer);
- // Fences are owned by the Context.
- GLuint createFence();
- void deleteFence(GLuint fence);
+ // 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 buffer);
void bindElementArrayBuffer(GLuint buffer);
- void bindTexture2D(GLuint texture);
- void bindTextureCubeMap(GLuint texture);
+ void bindTexture(GLenum target, GLuint texture);
void bindReadFramebuffer(GLuint framebuffer);
void bindDrawFramebuffer(GLuint framebuffer);
void bindRenderbuffer(GLuint renderbuffer);
+ void bindVertexArray(GLuint vertexArray);
+ void bindSampler(GLuint textureUnit, GLuint sampler);
+ void bindGenericUniformBuffer(GLuint buffer);
+ void bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size);
+ void bindGenericTransformFeedbackBuffer(GLuint buffer);
+ void bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size);
+ void bindCopyReadBuffer(GLuint buffer);
+ void bindCopyWriteBuffer(GLuint buffer);
+ void bindPixelPackBuffer(GLuint buffer);
+ void bindPixelUnpackBuffer(GLuint buffer);
void useProgram(GLuint program);
void linkProgram(GLuint program);
- void setProgramBinary(GLuint program, const void *binary, GLint length);
+ void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
+ void bindTransformFeedback(GLuint transformFeedback);
- void beginQuery(GLenum target, GLuint query);
- void endQuery(GLenum target);
+ Error beginQuery(GLenum target, GLuint query);
+ Error endQuery(GLenum target);
void setFramebufferZero(Framebuffer *framebuffer);
void setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
- void setVertexAttrib(GLuint index, const GLfloat *values);
void setVertexAttribDivisor(GLuint index, GLuint divisor);
+ void samplerParameteri(GLuint sampler, GLenum pname, GLint param);
+ void samplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
+ GLint getSamplerParameteri(GLuint sampler, GLenum pname);
+ GLfloat getSamplerParameterf(GLuint sampler, GLenum pname);
+
Buffer *getBuffer(GLuint handle);
- Fence *getFence(GLuint handle);
- Shader *getShader(GLuint handle);
- Program *getProgram(GLuint handle);
- Texture *getTexture(GLuint handle);
- Framebuffer *getFramebuffer(GLuint handle);
+ FenceNV *getFenceNV(GLuint handle);
+ FenceSync *getFenceSync(GLsync handle) const;
+ Shader *getShader(GLuint handle) const;
+ Program *getProgram(GLuint handle) const;
+ Texture *getTexture(GLuint handle) const;
+ Framebuffer *getFramebuffer(GLuint handle) const;
Renderbuffer *getRenderbuffer(GLuint handle);
+ VertexArray *getVertexArray(GLuint handle) const;
+ Sampler *getSampler(GLuint handle) const;
Query *getQuery(GLuint handle, bool create, GLenum type);
+ TransformFeedback *getTransformFeedback(GLuint handle) const;
- Buffer *getArrayBuffer();
- Buffer *getElementArrayBuffer();
- ProgramBinary *getCurrentProgramBinary();
- Texture2D *getTexture2D();
- TextureCubeMap *getTextureCubeMap();
- Texture *getSamplerTexture(unsigned int sampler, TextureType type);
- Framebuffer *getReadFramebuffer();
- Framebuffer *getDrawFramebuffer();
+ Texture *getTargetTexture(GLenum target) const;
+ Texture2D *getTexture2D() const;
+ TextureCubeMap *getTextureCubeMap() const;
+ Texture3D *getTexture3D() const;
+ Texture2DArray *getTexture2DArray() const;
- bool getFloatv(GLenum pname, GLfloat *params);
- bool getIntegerv(GLenum pname, GLint *params);
- bool getBooleanv(GLenum pname, GLboolean *params);
+ Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
- bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
+ bool isSampler(GLuint samplerName) const;
- void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
- void clear(GLbitfield mask);
- void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
- void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances);
+ void getBooleanv(GLenum pname, GLboolean *params);
+ void getFloatv(GLenum pname, GLfloat *params);
+ void getIntegerv(GLenum pname, GLint *params);
+ void getInteger64v(GLenum pname, GLint64 *params);
+
+ bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data);
+ bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data);
+
+ bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
+ bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams);
+
+ Error clear(GLbitfield mask);
+ Error clearBufferfv(GLenum buffer, int drawbuffer, const float *values);
+ Error clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values);
+ Error clearBufferiv(GLenum buffer, int drawbuffer, const int *values);
+ Error clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil);
+
+ Error readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
+ Error drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
+ Error drawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLsizei instances,
+ const rx::RangeUI &indexRange);
void sync(bool block); // flush/finish
- void recordInvalidEnum();
- void recordInvalidValue();
- void recordInvalidOperation();
- void recordOutOfMemory();
- void recordInvalidFramebufferOperation();
+ void recordError(const Error &error);
GLenum getError();
GLenum getResetStatus();
virtual bool isResetNotificationEnabled();
- int getMajorShaderModel() const;
- float getMaximumPointSize() const;
- unsigned int getMaximumCombinedTextureImageUnits() const;
- int getMaximumRenderbufferDimension() const;
- int getMaximumTextureDimension() const;
- int getMaximumCubeTextureDimension() const;
- int getMaximumTextureLevel() const;
- unsigned int getMaximumRenderTargets() const;
- GLsizei getMaxSupportedSamples() const;
- const char *getExtensionString() const;
- const char *getRendererString() const;
- bool supportsEventQueries() const;
- bool supportsOcclusionQueries() const;
- bool supportsBGRATextures() const;
- bool supportsDXT1Textures() const;
- bool supportsDXT3Textures() const;
- bool supportsDXT5Textures() const;
- bool supportsFloat32Textures() const;
- bool supportsFloat32LinearFilter() const;
- bool supportsFloat32RenderableTextures() const;
- bool supportsFloat16Textures() const;
- bool supportsFloat16LinearFilter() const;
- bool supportsFloat16RenderableTextures() const;
- bool supportsLuminanceTextures() const;
- bool supportsLuminanceAlphaTextures() const;
- bool supportsDepthTextures() const;
- bool supports32bitIndices() const;
- bool supportsNonPower2Texture() const;
- bool supportsInstancing() const;
- bool supportsTextureFilterAnisotropy() const;
-
- bool getCurrentReadFormatType(GLenum *format, GLenum *type);
-
- float getTextureMaxAnisotropy() const;
-
- void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask);
+ virtual int getClientVersion() const;
+
+ const Caps &getCaps() const;
+ const TextureCapsMap &getTextureCaps() const;
+ const Extensions &getExtensions() const;
+
+ const std::string &getRendererString() const;
+
+ const std::string &getExtensionString() const;
+ const std::string &getExtensionString(size_t idx) const;
+ size_t getExtensionStringCount() const;
+
+ void getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type);
+
+ void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter);
rx::Renderer *getRenderer() { return mRenderer; }
+ State &getState() { return mState; }
+ const State &getState() const { return mState; }
+
+ void releaseShaderCompiler();
+
private:
DISALLOW_COPY_AND_ASSIGN(Context);
- bool applyRenderTarget(GLenum drawMode, bool ignoreViewport);
- void applyState(GLenum drawMode);
- void applyShaders();
- void applyTextures();
- void applyTextures(SamplerType type);
+ // TODO: std::array may become unavailable using older versions of GCC
+ typedef std::array<unsigned int, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureSerialArray;
+
+ Error applyRenderTarget(GLenum drawMode, bool ignoreViewport);
+ Error applyState(GLenum drawMode);
+ Error applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive);
+ Error applyTextures(ProgramBinary *programBinary, SamplerType shaderType, const FramebufferTextureSerialArray &framebufferSerials,
+ size_t framebufferSerialCount);
+ Error applyTextures(ProgramBinary *programBinary);
+ Error applyUniformBuffers();
+ bool applyTransformFeedbackBuffers();
+ void markTransformFeedbackUsage();
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);
+
+ Error generateSwizzles(ProgramBinary *programBinary, SamplerType type);
+ Error generateSwizzles(ProgramBinary *programBinary);
- Texture *getIncompleteTexture(TextureType type);
+ Texture *getIncompleteTexture(GLenum type);
bool skipDraw(GLenum drawMode);
- void initExtensionString();
void initRendererString();
+ void initExtensionStrings();
- typedef std::set<unsigned> FramebufferTextureSerialSet;
- FramebufferTextureSerialSet getBoundFramebufferTextureSerials();
+ size_t getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray);
- rx::Renderer *const mRenderer;
+ void initCaps(GLuint clientVersion);
+ // Caps to use for validation
+ Caps mCaps;
+ TextureCapsMap mTextureCaps;
+ Extensions mExtensions;
+
+ rx::Renderer *const mRenderer;
State mState;
- BindingPointer<Texture2D> mTexture2DZero;
- BindingPointer<TextureCubeMap> mTextureCubeMapZero;
+ int mClientVersion;
-#ifndef HASH_MAP
-# ifdef _MSC_VER
-# define HASH_MAP stdext::hash_map
-# else
-# define HASH_MAP std::unordered_map
-# endif
-#endif
+ typedef std::map< GLenum, BindingPointer<Texture> > TextureMap;
+ TextureMap mZeroTextures;
+ TextureMap mIncompleteTextures;
- typedef HASH_MAP<GLuint, Framebuffer*> FramebufferMap;
+ typedef std::unordered_map<GLuint, Framebuffer*> FramebufferMap;
FramebufferMap mFramebufferMap;
HandleAllocator mFramebufferHandleAllocator;
- typedef HASH_MAP<GLuint, Fence*> FenceMap;
- FenceMap mFenceMap;
- HandleAllocator mFenceHandleAllocator;
+ typedef std::unordered_map<GLuint, FenceNV*> FenceNVMap;
+ FenceNVMap mFenceNVMap;
+ HandleAllocator mFenceNVHandleAllocator;
- typedef HASH_MAP<GLuint, Query*> QueryMap;
+ typedef std::unordered_map<GLuint, Query*> QueryMap;
QueryMap mQueryMap;
HandleAllocator mQueryHandleAllocator;
- const char *mExtensionString;
- const char *mRendererString;
-
- BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT];
+ typedef std::unordered_map<GLuint, VertexArray*> VertexArrayMap;
+ VertexArrayMap mVertexArrayMap;
+ HandleAllocator mVertexArrayHandleAllocator;
+
+ BindingPointer<TransformFeedback> mTransformFeedbackZero;
+ typedef std::unordered_map<GLuint, TransformFeedback*> TransformFeedbackMap;
+ TransformFeedbackMap mTransformFeedbackMap;
+ HandleAllocator mTransformFeedbackAllocator;
+
+ std::string mRendererString;
+ std::string mExtensionString;
+ std::vector<std::string> mExtensionStrings;
// Recorded errors
- bool mInvalidEnum;
- bool mInvalidValue;
- bool mInvalidOperation;
- bool mOutOfMemory;
- bool mInvalidFramebufferOperation;
+ typedef std::set<GLenum> ErrorSet;
+ ErrorSet mErrors;
// Current/lost context flags
bool mHasBeenCurrent;
@@ -470,39 +313,6 @@ class Context
GLenum mResetStrategy;
bool mRobustAccess;
- BindingPointer<ProgramBinary> mCurrentProgramBinary;
- Framebuffer *mBoundDrawFramebuffer;
-
- int mMajorShaderModel;
- float mMaximumPointSize;
- bool mSupportsVertexTexture;
- bool mSupportsNonPower2Texture;
- bool mSupportsInstancing;
- int mMaxViewportDimension;
- int mMaxRenderbufferDimension;
- int mMaxTextureDimension;
- int mMaxCubeTextureDimension;
- int mMaxTextureLevel;
- float mMaxTextureAnisotropy;
- bool mSupportsEventQueries;
- bool mSupportsOcclusionQueries;
- bool mSupportsBGRATextures;
- bool mSupportsDXT1Textures;
- bool mSupportsDXT3Textures;
- bool mSupportsDXT5Textures;
- bool mSupportsFloat32Textures;
- bool mSupportsFloat32LinearFilter;
- bool mSupportsFloat32RenderableTextures;
- bool mSupportsFloat16Textures;
- bool mSupportsFloat16LinearFilter;
- bool mSupportsFloat16RenderableTextures;
- bool mSupportsLuminanceTextures;
- bool mSupportsLuminanceAlphaTextures;
- bool mSupportsDepthTextures;
- bool mSupports32bitIndices;
- bool mSupportsTextureFilterAnisotropy;
- int mNumCompressedTextureFormats;
-
ResourceManager *mResourceManager;
};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Error.cpp b/src/3rdparty/angle/src/libGLESv2/Error.cpp
new file mode 100644
index 0000000000..cc7d17eb37
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/Error.cpp
@@ -0,0 +1,48 @@
+//
+// 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 gl::Error class which encapsulates an OpenGL error
+// and optional error message.
+
+#include "libGLESv2/Error.h"
+
+#include "common/angleutils.h"
+
+#include <cstdarg>
+
+namespace gl
+{
+
+Error::Error(GLenum errorCode)
+ : mCode(errorCode),
+ mMessage()
+{
+}
+
+Error::Error(GLenum errorCode, const char *msg, ...)
+ : mCode(errorCode),
+ mMessage()
+{
+ va_list vararg;
+ va_start(vararg, msg);
+ mMessage = FormatString(msg, vararg);
+ va_end(vararg);
+}
+
+Error::Error(const Error &other)
+ : mCode(other.mCode),
+ mMessage(other.mMessage)
+{
+}
+
+Error &Error::operator=(const Error &other)
+{
+ mCode = other.mCode;
+ mMessage = other.mMessage;
+ return *this;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Error.h b/src/3rdparty/angle/src/libGLESv2/Error.h
new file mode 100644
index 0000000000..b70b5a531c
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/Error.h
@@ -0,0 +1,39 @@
+//
+// 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 gl::Error class which encapsulates an OpenGL error
+// and optional error message.
+
+#ifndef LIBGLESV2_ERROR_H_
+#define LIBGLESV2_ERROR_H_
+
+#include "angle_gl.h"
+
+#include <string>
+
+namespace gl
+{
+
+class Error
+{
+ public:
+ explicit Error(GLenum errorCode);
+ Error(GLenum errorCode, const char *msg, ...);
+ Error(const Error &other);
+ Error &operator=(const Error &other);
+
+ GLenum getCode() const { return mCode; }
+ bool isError() const { return (mCode != GL_NO_ERROR); }
+
+ const std::string &getMessage() const { return mMessage; }
+
+ private:
+ GLenum mCode;
+ std::string mMessage;
+};
+
+}
+
+#endif // LIBGLESV2_ERROR_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.cpp b/src/3rdparty/angle/src/libGLESv2/Fence.cpp
index e4218bbeec..ee9a07a5c4 100644
--- a/src/3rdparty/angle/src/libGLESv2/Fence.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Fence.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -7,46 +6,189 @@
// Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension.
+// 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.
+
#include "libGLESv2/Fence.h"
#include "libGLESv2/renderer/FenceImpl.h"
#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/main.h"
+
+#include "angle_gl.h"
namespace gl
{
-Fence::Fence(rx::Renderer *renderer)
+FenceNV::FenceNV(rx::Renderer *renderer)
{
mFence = renderer->createFence();
}
-Fence::~Fence()
+FenceNV::~FenceNV()
{
delete mFence;
}
-GLboolean Fence::isFence()
+GLboolean FenceNV::isFence() const
{
- return mFence->isFence();
+ // GL_NV_fence spec:
+ // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
+ return (mFence->isSet() ? GL_TRUE : GL_FALSE);
}
-void Fence::setFence(GLenum condition)
+void FenceNV::setFence(GLenum condition)
{
- mFence->setFence(condition);
+ mFence->set();
+
+ mCondition = condition;
+ mStatus = GL_FALSE;
}
-GLboolean Fence::testFence()
+GLboolean FenceNV::testFence()
{
- return mFence->testFence();
+ // Flush the command buffer by default
+ bool result = mFence->test(true);
+
+ mStatus = (result ? GL_TRUE : GL_FALSE);
+ return mStatus;
}
-void Fence::finishFence()
+void FenceNV::finishFence()
{
- mFence->finishFence();
+ ASSERT(mFence->isSet());
+
+ while (!mFence->test(true))
+ {
+ Sleep(0);
+ }
}
-void Fence::getFenceiv(GLenum pname, GLint *params)
+GLint FenceNV::getFencei(GLenum pname)
{
- mFence->getFenceiv(pname, params);
+ ASSERT(mFence->isSet());
+
+ switch (pname)
+ {
+ case GL_FENCE_STATUS_NV:
+ {
+ // GL_NV_fence spec:
+ // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
+ // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
+ if (mStatus == GL_TRUE)
+ {
+ return GL_TRUE;
+ }
+
+ mStatus = (mFence->test(false) ? GL_TRUE : GL_FALSE);
+ return mStatus;
+ }
+
+ case GL_FENCE_CONDITION_NV:
+ return mCondition;
+
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+FenceSync::FenceSync(rx::Renderer *renderer, GLuint id)
+ : RefCountObject(id)
+{
+ mFence = renderer->createFence();
+
+ LARGE_INTEGER counterFreqency = { 0 };
+ BOOL success = QueryPerformanceFrequency(&counterFreqency);
+ UNUSED_ASSERTION_VARIABLE(success);
+ ASSERT(success);
+
+ mCounterFrequency = counterFreqency.QuadPart;
+}
+
+FenceSync::~FenceSync()
+{
+ delete mFence;
+}
+
+void FenceSync::set(GLenum condition)
+{
+ mCondition = condition;
+ mFence->set();
+}
+
+GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout)
+{
+ ASSERT(mFence->isSet());
+
+ bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0);
+
+ if (mFence->test(flushCommandBuffer))
+ {
+ return GL_ALREADY_SIGNALED;
+ }
+
+ if (mFence->hasError())
+ {
+ return GL_WAIT_FAILED;
+ }
+
+ if (timeout == 0)
+ {
+ return GL_TIMEOUT_EXPIRED;
+ }
+
+ LARGE_INTEGER currentCounter = { 0 };
+ BOOL success = QueryPerformanceCounter(&currentCounter);
+ UNUSED_ASSERTION_VARIABLE(success);
+ ASSERT(success);
+
+ LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll);
+ LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;
+
+ while (currentCounter.QuadPart < endCounter && !mFence->test(flushCommandBuffer))
+ {
+ Sleep(0);
+ BOOL success = QueryPerformanceCounter(&currentCounter);
+ UNUSED_ASSERTION_VARIABLE(success);
+ ASSERT(success);
+ }
+
+ if (mFence->hasError())
+ {
+ return GL_WAIT_FAILED;
+ }
+
+ if (currentCounter.QuadPart >= endCounter)
+ {
+ return GL_TIMEOUT_EXPIRED;
+ }
+
+ return GL_CONDITION_SATISFIED;
+}
+
+void FenceSync::serverWait()
+{
+ // 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.
+}
+
+GLenum FenceSync::getStatus() const
+{
+ if (mFence->test(false))
+ {
+ // The spec does not specify any way to report errors during the status test (e.g. device lost)
+ // so we report the fence is unblocked in case of error or signaled.
+ return GL_SIGNALED;
+ }
+
+ return GL_UNSIGNALED;
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.h b/src/3rdparty/angle/src/libGLESv2/Fence.h
index 1cedebb112..291edb3de1 100644
--- a/src/3rdparty/angle/src/libGLESv2/Fence.h
+++ b/src/3rdparty/angle/src/libGLESv2/Fence.h
@@ -10,6 +10,7 @@
#define LIBGLESV2_FENCE_H_
#include "common/angleutils.h"
+#include "common/RefCountObject.h"
namespace rx
{
@@ -20,22 +21,50 @@ class FenceImpl;
namespace gl
{
-class Fence
+class FenceNV
{
public:
- explicit Fence(rx::Renderer *renderer);
- virtual ~Fence();
+ explicit FenceNV(rx::Renderer *renderer);
+ virtual ~FenceNV();
- GLboolean isFence();
+ GLboolean isFence() const;
void setFence(GLenum condition);
GLboolean testFence();
void finishFence();
- void getFenceiv(GLenum pname, GLint *params);
+ GLint getFencei(GLenum pname);
+
+ GLboolean getStatus() const { return mStatus; }
+ GLuint getCondition() const { return mCondition; }
private:
- DISALLOW_COPY_AND_ASSIGN(Fence);
+ DISALLOW_COPY_AND_ASSIGN(FenceNV);
rx::FenceImpl *mFence;
+
+ GLboolean mStatus;
+ GLenum mCondition;
+};
+
+class FenceSync : public RefCountObject
+{
+ public:
+ explicit FenceSync(rx::Renderer *renderer, GLuint id);
+ virtual ~FenceSync();
+
+ void set(GLenum condition);
+ GLenum clientWait(GLbitfield flags, GLuint64 timeout);
+ void serverWait();
+ GLenum getStatus() const;
+
+ GLuint getCondition() const { return mCondition; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FenceSync);
+
+ rx::FenceImpl *mFence;
+ LONGLONG mCounterFrequency;
+
+ GLenum mCondition;
};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp
index b90d2f6023..5bf7b3fce8 100644
--- a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
index b0abba0ac4..5b21433f90 100644
--- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
@@ -1,6 +1,5 @@
-#include "precompiled.h"
//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -9,255 +8,332 @@
// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
#include "libGLESv2/Framebuffer.h"
-
#include "libGLESv2/main.h"
-#include "libGLESv2/utilities.h"
+#include "libGLESv2/formatutils.h"
#include "libGLESv2/Texture.h"
#include "libGLESv2/Context.h"
-#include "libGLESv2/renderer/Renderer.h"
#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/RenderTarget.h"
+#include "libGLESv2/renderer/d3d/TextureD3D.h"
+
+#include "common/utilities.h"
+
+namespace rx
+{
+RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
+{
+ if (attachment->isTexture())
+ {
+ gl::Texture *texture = attachment->getTexture();
+ ASSERT(texture);
+ TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+ const gl::ImageIndex *index = attachment->getTextureImageIndex();
+ ASSERT(index);
+ return textureD3D->getRenderTarget(*index);
+ }
+
+ gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
+ ASSERT(renderbuffer);
+
+ // TODO: cast to RenderbufferD3D
+ return renderbuffer->getStorage()->getRenderTarget();
+}
+
+// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
+unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
+{
+ if (attachment->isTexture())
+ {
+ gl::Texture *texture = attachment->getTexture();
+ ASSERT(texture);
+ TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+ const gl::ImageIndex *index = attachment->getTextureImageIndex();
+ ASSERT(index);
+ return textureD3D->getRenderTargetSerial(*index);
+ }
+
+ gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
+ ASSERT(renderbuffer);
+
+ // TODO: cast to RenderbufferD3D
+ return renderbuffer->getStorage()->getSerial();
+}
+
+}
namespace gl
{
-Framebuffer::Framebuffer(rx::Renderer *renderer)
- : mRenderer(renderer)
+Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id)
+ : mRenderer(renderer),
+ mId(id),
+ mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
+ mDepthbuffer(NULL),
+ mStencilbuffer(NULL)
{
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
- mColorbufferTypes[colorAttachment] = GL_NONE;
+ mColorbuffers[colorAttachment] = NULL;
mDrawBufferStates[colorAttachment] = GL_NONE;
}
mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
- mReadBufferState = GL_COLOR_ATTACHMENT0_EXT;
-
- mDepthbufferType = GL_NONE;
- mStencilbufferType = GL_NONE;
}
Framebuffer::~Framebuffer()
{
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
- mColorbufferPointers[colorAttachment].set(NULL);
+ SafeDelete(mColorbuffers[colorAttachment]);
}
- mDepthbufferPointer.set(NULL);
- mStencilbufferPointer.set(NULL);
+ SafeDelete(mDepthbuffer);
+ SafeDelete(mStencilbuffer);
}
-Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
+FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const
{
- gl::Context *context = gl::getContext();
- Renderbuffer *buffer = NULL;
-
- if (type == GL_NONE)
- {
- buffer = NULL;
- }
- else if (type == GL_RENDERBUFFER)
- {
- buffer = context->getRenderbuffer(handle);
- }
- else if (IsInternalTextureTarget(type))
+ if (handle == 0)
{
- buffer = context->getTexture(handle)->getRenderbuffer(type);
+ return NULL;
}
- else
+
+ gl::Context *context = gl::getContext();
+
+ switch (type)
{
+ case GL_NONE:
+ return NULL;
+
+ case GL_RENDERBUFFER:
+ return new RenderbufferAttachment(binding, context->getRenderbuffer(handle));
+
+ case GL_TEXTURE_2D:
+ {
+ Texture *texture = context->getTexture(handle);
+ if (texture && texture->getTarget() == GL_TEXTURE_2D)
+ {
+ return new TextureAttachment(binding, texture, ImageIndex::Make2D(level));
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ 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:
+ {
+ Texture *texture = context->getTexture(handle);
+ if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
+ {
+ return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level));
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ case GL_TEXTURE_3D:
+ {
+ Texture *texture = context->getTexture(handle);
+ if (texture && texture->getTarget() == GL_TEXTURE_3D)
+ {
+ return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer));
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ Texture *texture = context->getTexture(handle);
+ if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
+ {
+ return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer));
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ default:
UNREACHABLE();
+ return NULL;
}
-
- return buffer;
}
-void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer)
+void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
{
ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
- mColorbufferTypes[colorAttachment] = (colorbuffer != 0) ? type : GL_NONE;
- mColorbufferPointers[colorAttachment].set(lookupRenderbuffer(type, colorbuffer));
+ SafeDelete(mColorbuffers[colorAttachment]);
+ GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0;
+ mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer);
}
-void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
+void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
{
- mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
- mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
+ SafeDelete(mDepthbuffer);
+ mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer);
}
-void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
+void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
{
- mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
- mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
+ SafeDelete(mStencilbuffer);
+ mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer);
}
-void Framebuffer::detachTexture(GLuint texture)
+void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
{
- for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
- {
- mColorbufferTypes[colorAttachment] = GL_NONE;
- mColorbufferPointers[colorAttachment].set(NULL);
- }
- }
+ FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
- if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
- {
- mDepthbufferType = GL_NONE;
- mDepthbufferPointer.set(NULL);
- }
+ SafeDelete(mDepthbuffer);
+ SafeDelete(mStencilbuffer);
- if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
+ // ensure this is a legitimate depth+stencil format
+ if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
{
- mStencilbufferType = GL_NONE;
- mStencilbufferPointer.set(NULL);
+ mDepthbuffer = attachment;
+
+ // Make a new attachment object to ensure we do not double-delete
+ // See angle issue 686
+ mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
}
}
-void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
+void Framebuffer::detachTexture(GLuint textureId)
{
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
- if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
+ FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
+
+ if (attachment && attachment->isTextureWithId(textureId))
{
- mColorbufferTypes[colorAttachment] = GL_NONE;
- mColorbufferPointers[colorAttachment].set(NULL);
+ SafeDelete(mColorbuffers[colorAttachment]);
}
}
- if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
+ if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId))
{
- mDepthbufferType = GL_NONE;
- mDepthbufferPointer.set(NULL);
+ SafeDelete(mDepthbuffer);
}
- if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
+ if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId))
{
- mStencilbufferType = GL_NONE;
- mStencilbufferPointer.set(NULL);
+ SafeDelete(mStencilbuffer);
}
}
-unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const
+void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
{
- ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
+ for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ {
+ FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
- Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get();
+ if (attachment && attachment->isRenderbufferWithId(renderbufferId))
+ {
+ SafeDelete(mColorbuffers[colorAttachment]);
+ }
+ }
- if (colorbuffer)
+ if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId))
{
- return colorbuffer->getSerial();
+ SafeDelete(mDepthbuffer);
}
- return 0;
-}
-
-unsigned int Framebuffer::getDepthbufferSerial() const
-{
- Renderbuffer *depthbuffer = mDepthbufferPointer.get();
-
- if (depthbuffer)
+ if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId))
{
- return depthbuffer->getSerial();
+ SafeDelete(mStencilbuffer);
}
-
- return 0;
}
-unsigned int Framebuffer::getStencilbufferSerial() const
+FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
{
- Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
-
- if (stencilbuffer)
- {
- return stencilbuffer->getSerial();
- }
-
- return 0;
+ ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
+ return mColorbuffers[colorAttachment];
}
-Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
+FramebufferAttachment *Framebuffer::getDepthbuffer() const
{
- ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
- return mColorbufferPointers[colorAttachment].get();
+ return mDepthbuffer;
}
-Renderbuffer *Framebuffer::getDepthbuffer() const
+FramebufferAttachment *Framebuffer::getStencilbuffer() const
{
- return mDepthbufferPointer.get();
+ return mStencilbuffer;
}
-Renderbuffer *Framebuffer::getStencilbuffer() const
+FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
{
- return mStencilbufferPointer.get();
+ return (hasValidDepthStencil() ? mDepthbuffer : NULL);
}
-Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const
+FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
{
- Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
+ FramebufferAttachment *depthstencilbuffer = mDepthbuffer;
if (!depthstencilbuffer)
{
- depthstencilbuffer = mStencilbufferPointer.get();
+ depthstencilbuffer = mStencilbuffer;
}
return depthstencilbuffer;
}
-Renderbuffer *Framebuffer::getReadColorbuffer() const
+FramebufferAttachment *Framebuffer::getReadColorbuffer() const
{
// Will require more logic if glReadBuffers is supported
- return mColorbufferPointers[0].get();
+ return mColorbuffers[0];
}
GLenum Framebuffer::getReadColorbufferType() const
{
// Will require more logic if glReadBuffers is supported
- return mColorbufferTypes[0];
+ return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE);
}
-Renderbuffer *Framebuffer::getFirstColorbuffer() const
+FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
{
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
- if (mColorbufferTypes[colorAttachment] != GL_NONE)
+ if (mColorbuffers[colorAttachment])
{
- return mColorbufferPointers[colorAttachment].get();
+ return mColorbuffers[colorAttachment];
}
}
return NULL;
}
-GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const
-{
- ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
- return mColorbufferTypes[colorAttachment];
-}
-
-GLenum Framebuffer::getDepthbufferType() const
-{
- return mDepthbufferType;
-}
-
-GLenum Framebuffer::getStencilbufferType() const
-{
- return mStencilbufferType;
-}
-
-GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const
+FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
{
- ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
- return mColorbufferPointers[colorAttachment].id();
-}
-
-GLuint Framebuffer::getDepthbufferHandle() const
-{
- return mDepthbufferPointer.id();
-}
-
-GLuint Framebuffer::getStencilbufferHandle() const
-{
- return mStencilbufferPointer.id();
+ if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
+ {
+ return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
+ }
+ else
+ {
+ switch (attachment)
+ {
+ case GL_DEPTH_ATTACHMENT:
+ return getDepthbuffer();
+ case GL_STENCIL_ATTACHMENT:
+ return getStencilbuffer();
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ return getDepthStencilBuffer();
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+ }
}
GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
@@ -272,7 +348,7 @@ void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBu
bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
{
- return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE);
+ return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE);
}
bool Framebuffer::hasEnabledColorAttachment() const
@@ -290,17 +366,7 @@ bool Framebuffer::hasEnabledColorAttachment() const
bool Framebuffer::hasStencil() const
{
- if (mStencilbufferType != GL_NONE)
- {
- const Renderbuffer *stencilbufferObject = getStencilbuffer();
-
- if (stencilbufferObject)
- {
- return stencilbufferObject->getStencilSize() > 0;
- }
- }
-
- return false;
+ return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0);
}
bool Framebuffer::usingExtendedDrawBuffers() const
@@ -320,63 +386,44 @@ GLenum Framebuffer::completeness() const
{
int width = 0;
int height = 0;
- int colorbufferSize = 0;
+ unsigned int colorbufferSize = 0;
int samples = -1;
bool missingAttachment = true;
+ GLuint clientVersion = mRenderer->getCurrentClientVersion();
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
- if (mColorbufferTypes[colorAttachment] != GL_NONE)
- {
- const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment);
-
- if (!colorbuffer)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
+ const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
+ if (colorbuffer)
+ {
if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
+ GLenum internalformat = colorbuffer->getInternalFormat();
+ // TODO(geofflang): use context's texture caps
+ const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
+ if (colorbuffer->isTexture())
{
- if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
- }
- else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
- {
- GLint internalformat = colorbuffer->getInternalFormat();
- GLenum format = gl::ExtractFormat(internalformat);
-
- if (IsCompressed(format) ||
- format == GL_ALPHA ||
- format == GL_LUMINANCE ||
- format == GL_LUMINANCE_ALPHA)
+ if (!formatCaps.renderable)
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
- bool filtering, renderable;
-
- if ((gl::IsFloat32Format(internalformat) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) ||
- (gl::IsFloat16Format(internalformat) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable)))
- {
- return GL_FRAMEBUFFER_UNSUPPORTED;
- }
-
- if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat))
+ if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
}
else
{
- UNREACHABLE();
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
}
if (!missingAttachment)
@@ -394,16 +441,24 @@ GLenum Framebuffer::completeness() const
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
}
- // all color attachments attachments must have the same number of bitplanes
- if (gl::ComputePixelSize(colorbuffer->getInternalFormat()) != colorbufferSize)
+ // 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 (clientVersion < 3)
{
- return GL_FRAMEBUFFER_UNSUPPORTED;
+ if (formatInfo.pixelBytes != colorbufferSize)
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
}
// D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
{
- if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get())
+ const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment];
+
+ if (previousAttachment &&
+ (colorbuffer->id() == previousAttachment->id() &&
+ colorbuffer->type() == previousAttachment->type()))
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
@@ -414,129 +469,118 @@ GLenum Framebuffer::completeness() const
width = colorbuffer->getWidth();
height = colorbuffer->getHeight();
samples = colorbuffer->getSamples();
- colorbufferSize = gl::ComputePixelSize(colorbuffer->getInternalFormat());
+ colorbufferSize = formatInfo.pixelBytes;
missingAttachment = false;
}
}
}
- const Renderbuffer *depthbuffer = NULL;
- const Renderbuffer *stencilbuffer = NULL;
-
- if (mDepthbufferType != GL_NONE)
+ if (mDepthbuffer)
{
- depthbuffer = getDepthbuffer();
-
- if (!depthbuffer)
+ if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
+ GLenum internalformat = mDepthbuffer->getInternalFormat();
+ // TODO(geofflang): use context's texture caps
+ const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
+ if (mDepthbuffer->isTexture())
{
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
-
- if (mDepthbufferType == GL_RENDERBUFFER)
- {
- if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat()))
+ // depth texture attachments require OES/ANGLE_depth_texture
+ // TODO(geofflang): use context's extensions
+ if (!mRenderer->getRendererExtensions().depthTextures)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- }
- else if (IsInternalTextureTarget(mDepthbufferType))
- {
- GLint internalformat = depthbuffer->getInternalFormat();
- // depth texture attachments require OES/ANGLE_depth_texture
- if (!mRenderer->getDepthTextureSupport())
+ if (!formatCaps.renderable)
{
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ return GL_FRAMEBUFFER_UNSUPPORTED;
}
- if (!gl::IsDepthTexture(internalformat))
+ if (formatInfo.depthBits == 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
}
else
{
- UNREACHABLE();
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ if (!formatCaps.renderable || formatInfo.depthBits == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
}
if (missingAttachment)
{
- width = depthbuffer->getWidth();
- height = depthbuffer->getHeight();
- samples = depthbuffer->getSamples();
+ width = mDepthbuffer->getWidth();
+ height = mDepthbuffer->getHeight();
+ samples = mDepthbuffer->getSamples();
missingAttachment = false;
}
- else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
+ else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight())
{
return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
}
- else if (samples != depthbuffer->getSamples())
+ else if (samples != mDepthbuffer->getSamples())
{
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
}
}
- if (mStencilbufferType != GL_NONE)
+ if (mStencilbuffer)
{
- stencilbuffer = getStencilbuffer();
-
- if (!stencilbuffer)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
-
- if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
+ if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- if (mStencilbufferType == GL_RENDERBUFFER)
+ GLenum internalformat = mStencilbuffer->getInternalFormat();
+ // TODO(geofflang): use context's texture caps
+ const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
+ if (mStencilbuffer->isTexture())
{
- if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat()))
+ // texture stencil attachments come along as part
+ // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
+ // TODO(geofflang): use context's extensions
+ if (!mRenderer->getRendererExtensions().depthTextures)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- }
- else if (IsInternalTextureTarget(mStencilbufferType))
- {
- GLint internalformat = stencilbuffer->getInternalFormat();
- // texture stencil attachments come along as part
- // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
- if (!mRenderer->getDepthTextureSupport())
+ if (!formatCaps.renderable)
{
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ return GL_FRAMEBUFFER_UNSUPPORTED;
}
- if (!gl::IsStencilTexture(internalformat))
+ if (formatInfo.stencilBits == 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
}
else
{
- UNREACHABLE();
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ if (!formatCaps.renderable || formatInfo.stencilBits == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
}
if (missingAttachment)
{
- width = stencilbuffer->getWidth();
- height = stencilbuffer->getHeight();
- samples = stencilbuffer->getSamples();
+ width = mStencilbuffer->getWidth();
+ height = mStencilbuffer->getHeight();
+ samples = mStencilbuffer->getSamples();
missingAttachment = false;
}
- else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
+ else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight())
{
return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
}
- else if (samples != stencilbuffer->getSamples())
+ else if (samples != mStencilbuffer->getSamples())
{
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
}
@@ -544,7 +588,7 @@ GLenum Framebuffer::completeness() 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 (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
+ if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil())
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
@@ -558,18 +602,47 @@ GLenum Framebuffer::completeness() const
return GL_FRAMEBUFFER_COMPLETE;
}
+void Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
+{
+ GLuint maxDimension = caps.maxRenderbufferSize;
+ invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension);
+}
+
+void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE);
+ for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex)
+ {
+ GLenum attachmentTarget = attachments[attachIndex];
+
+ gl::FramebufferAttachment *attachment =
+ (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() :
+ getAttachment(attachmentTarget);
+
+ if (attachment)
+ {
+ rx::RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
+ if (renderTarget)
+ {
+ renderTarget->invalidate(x, y, width, height);
+ }
+ }
+ }
+}
+
DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
- : Framebuffer(renderer)
+ : Framebuffer(renderer, 0)
{
- mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer));
+ Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer);
+ mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer);
- Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil);
- mDepthbufferPointer.set(depthStencilRenderbuffer);
- mStencilbufferPointer.set(depthStencilRenderbuffer);
+ Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil);
- mColorbufferTypes[0] = GL_RENDERBUFFER;
- mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
- mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
+ // Make a new attachment objects to ensure we do not double-delete
+ // See angle issue 686
+ mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL);
+ mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL);
mDrawBufferStates[0] = GL_BACK;
mReadBufferState = GL_BACK;
@@ -583,9 +656,9 @@ int Framebuffer::getSamples() const
// in this case return the first nonzero sample size
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
- if (mColorbufferTypes[colorAttachment] != GL_NONE)
+ if (mColorbuffers[colorAttachment])
{
- return getColorbuffer(colorAttachment)->getSamples();
+ return mColorbuffers[colorAttachment]->getSamples();
}
}
}
@@ -593,6 +666,40 @@ int Framebuffer::getSamples() const
return 0;
}
+bool Framebuffer::hasValidDepthStencil() const
+{
+ // A valid depth-stencil attachment has the same resource bound to both the
+ // depth and stencil attachment points.
+ return (mDepthbuffer && mStencilbuffer &&
+ mDepthbuffer->type() == mStencilbuffer->type() &&
+ mDepthbuffer->id() == mStencilbuffer->id());
+}
+
+ColorbufferInfo Framebuffer::getColorbuffersForRender() const
+{
+ ColorbufferInfo colorbuffersForRender;
+
+ for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment)
+ {
+ GLenum drawBufferState = mDrawBufferStates[colorAttachment];
+ FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
+
+ if (colorbuffer != NULL && drawBufferState != GL_NONE)
+ {
+ ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
+ colorbuffersForRender.push_back(colorbuffer);
+ }
+#if (ANGLE_MRT_PERF_WORKAROUND == ANGLE_WORKAROUND_DISABLED)
+ else
+ {
+ colorbuffersForRender.push_back(NULL);
+ }
+#endif
+ }
+
+ return colorbuffersForRender;
+}
+
GLenum DefaultFramebuffer::completeness() const
{
// The default framebuffer *must* always be complete, though it may not be
@@ -600,4 +707,23 @@ GLenum DefaultFramebuffer::completeness() const
return GL_FRAMEBUFFER_COMPLETE;
}
+FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const
+{
+ switch (attachment)
+ {
+ case GL_COLOR:
+ case GL_BACK:
+ return getColorbuffer(0);
+ case GL_DEPTH:
+ return getDepthbuffer();
+ case GL_STENCIL:
+ return getStencilbuffer();
+ case GL_DEPTH_STENCIL:
+ return getDepthStencilBuffer();
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h
index 50bfd4fd0f..cc12d22953 100644
--- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h
@@ -10,9 +10,11 @@
#ifndef LIBGLESV2_FRAMEBUFFER_H_
#define LIBGLESV2_FRAMEBUFFER_H_
+#include <vector>
+
#include "common/angleutils.h"
#include "common/RefCountObject.h"
-#include "Constants.h"
+#include "constants.h"
namespace rx
{
@@ -21,45 +23,42 @@ class Renderer;
namespace gl
{
-class Renderbuffer;
+class FramebufferAttachment;
class Colorbuffer;
class Depthbuffer;
class Stencilbuffer;
class DepthStencilbuffer;
+struct Caps;
+
+typedef std::vector<FramebufferAttachment *> ColorbufferInfo;
class Framebuffer
{
public:
- explicit Framebuffer(rx::Renderer *renderer);
+ Framebuffer(rx::Renderer *renderer, GLuint id);
virtual ~Framebuffer();
- void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer);
- void setDepthbuffer(GLenum type, GLuint depthbuffer);
- void setStencilbuffer(GLenum type, GLuint stencilbuffer);
+ GLuint id() const { return mId; }
+
+ void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer);
+ void setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer);
+ void setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer);
+ void setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer);
void detachTexture(GLuint texture);
void detachRenderbuffer(GLuint renderbuffer);
- unsigned int getRenderTargetSerial(unsigned int colorAttachment) const;
- unsigned int getDepthbufferSerial() const;
- unsigned int getStencilbufferSerial() const;
-
- Renderbuffer *getColorbuffer(unsigned int colorAttachment) const;
- Renderbuffer *getDepthbuffer() const;
- Renderbuffer *getStencilbuffer() const;
- Renderbuffer *getDepthOrStencilbuffer() const;
- Renderbuffer *getReadColorbuffer() const;
+ FramebufferAttachment *getColorbuffer(unsigned int colorAttachment) const;
+ FramebufferAttachment *getDepthbuffer() const;
+ FramebufferAttachment *getStencilbuffer() const;
+ FramebufferAttachment *getDepthStencilBuffer() const;
+ FramebufferAttachment *getDepthOrStencilbuffer() const;
+ FramebufferAttachment *getReadColorbuffer() const;
GLenum getReadColorbufferType() const;
- Renderbuffer *getFirstColorbuffer() const;
-
- GLenum getColorbufferType(unsigned int colorAttachment) const;
- GLenum getDepthbufferType() const;
- GLenum getStencilbufferType() const;
+ FramebufferAttachment *getFirstColorbuffer() const;
- GLuint getColorbufferHandle(unsigned int colorAttachment) const;
- GLuint getDepthbufferHandle() const;
- GLuint getStencilbufferHandle() const;
+ virtual FramebufferAttachment *getAttachment(GLenum attachment) const;
GLenum getDrawBufferState(unsigned int colorAttachment) const;
void setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer);
@@ -71,25 +70,33 @@ class Framebuffer
bool usingExtendedDrawBuffers() const;
virtual GLenum completeness() const;
+ bool hasValidDepthStencil() const;
+
+ void invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments);
+ void invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments,
+ GLint x, GLint y, GLsizei width, GLsizei height);
+
+ // Use this method to retrieve the color buffer map when doing rendering.
+ // It will apply a workaround for poor shader performance on some systems
+ // by compacting the list to skip NULL values.
+ ColorbufferInfo getColorbuffersForRender() const;
protected:
- GLenum mColorbufferTypes[IMPLEMENTATION_MAX_DRAW_BUFFERS];
- BindingPointer<Renderbuffer> mColorbufferPointers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
- GLenum mDrawBufferStates[IMPLEMENTATION_MAX_DRAW_BUFFERS];
- GLenum mReadBufferState;
+ rx::Renderer *mRenderer;
- GLenum mDepthbufferType;
- BindingPointer<Renderbuffer> mDepthbufferPointer;
+ GLuint mId;
- GLenum mStencilbufferType;
- BindingPointer<Renderbuffer> mStencilbufferPointer;
+ FramebufferAttachment *mColorbuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
+ GLenum mDrawBufferStates[IMPLEMENTATION_MAX_DRAW_BUFFERS];
+ GLenum mReadBufferState;
- rx::Renderer *mRenderer;
+ FramebufferAttachment *mDepthbuffer;
+ FramebufferAttachment *mStencilbuffer;
private:
DISALLOW_COPY_AND_ASSIGN(Framebuffer);
- Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const;
+ FramebufferAttachment *createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const;
};
class DefaultFramebuffer : public Framebuffer
@@ -98,6 +105,7 @@ class DefaultFramebuffer : public Framebuffer
DefaultFramebuffer(rx::Renderer *Renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil);
virtual GLenum completeness() const;
+ virtual FramebufferAttachment *getAttachment(GLenum attachment) const;
private:
DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer);
@@ -105,4 +113,14 @@ class DefaultFramebuffer : public Framebuffer
}
+namespace rx
+{
+class RenderTarget;
+
+// TODO: place this in FramebufferD3D.h
+RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment);
+unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment);
+
+}
+
#endif // LIBGLESV2_FRAMEBUFFER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp
new file mode 100644
index 0000000000..540ede1cd2
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp
@@ -0,0 +1,230 @@
+//
+// 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 "libGLESv2/FramebufferAttachment.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/formatutils.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/renderer/RenderTarget.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/d3d/TextureStorage.h"
+
+#include "common/utilities.h"
+
+namespace gl
+{
+
+////// FramebufferAttachment Implementation //////
+
+FramebufferAttachment::FramebufferAttachment(GLenum binding)
+ : mBinding(binding)
+{
+}
+
+FramebufferAttachment::~FramebufferAttachment()
+{
+}
+
+GLuint FramebufferAttachment::getRedSize() const
+{
+ return (GetInternalFormatInfo(getInternalFormat()).redBits > 0) ? GetInternalFormatInfo(getActualFormat()).redBits : 0;
+}
+
+GLuint FramebufferAttachment::getGreenSize() const
+{
+ return (GetInternalFormatInfo(getInternalFormat()).greenBits > 0) ? GetInternalFormatInfo(getActualFormat()).greenBits : 0;
+}
+
+GLuint FramebufferAttachment::getBlueSize() const
+{
+ return (GetInternalFormatInfo(getInternalFormat()).blueBits > 0) ? GetInternalFormatInfo(getActualFormat()).blueBits : 0;
+}
+
+GLuint FramebufferAttachment::getAlphaSize() const
+{
+ return (GetInternalFormatInfo(getInternalFormat()).alphaBits > 0) ? GetInternalFormatInfo(getActualFormat()).alphaBits : 0;
+}
+
+GLuint FramebufferAttachment::getDepthSize() const
+{
+ return (GetInternalFormatInfo(getInternalFormat()).depthBits > 0) ? GetInternalFormatInfo(getActualFormat()).depthBits : 0;
+}
+
+GLuint FramebufferAttachment::getStencilSize() const
+{
+ return (GetInternalFormatInfo(getInternalFormat()).stencilBits > 0) ? GetInternalFormatInfo(getActualFormat()).stencilBits : 0;
+}
+
+GLenum FramebufferAttachment::getComponentType() const
+{
+ return GetInternalFormatInfo(getActualFormat()).componentType;
+}
+
+GLenum FramebufferAttachment::getColorEncoding() const
+{
+ return GetInternalFormatInfo(getActualFormat()).colorEncoding;
+}
+
+bool FramebufferAttachment::isTexture() const
+{
+ return (type() != GL_RENDERBUFFER);
+}
+
+///// TextureAttachment Implementation ////////
+
+TextureAttachment::TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index)
+ : FramebufferAttachment(binding),
+ mIndex(index)
+{
+ mTexture.set(texture);
+}
+
+TextureAttachment::~TextureAttachment()
+{
+ mTexture.set(NULL);
+}
+
+GLsizei TextureAttachment::getSamples() const
+{
+ return 0;
+}
+
+GLuint TextureAttachment::id() const
+{
+ return mTexture->id();
+}
+
+GLsizei TextureAttachment::getWidth() const
+{
+ return mTexture->getWidth(mIndex);
+}
+
+GLsizei TextureAttachment::getHeight() const
+{
+ return mTexture->getHeight(mIndex);
+}
+
+GLenum TextureAttachment::getInternalFormat() const
+{
+ return mTexture->getInternalFormat(mIndex);
+}
+
+GLenum TextureAttachment::getActualFormat() const
+{
+ return mTexture->getActualFormat(mIndex);
+}
+
+GLenum TextureAttachment::type() const
+{
+ return mIndex.type;
+}
+
+GLint TextureAttachment::mipLevel() const
+{
+ return mIndex.mipIndex;
+}
+
+GLint TextureAttachment::layer() const
+{
+ return mIndex.layerIndex;
+}
+
+Texture *TextureAttachment::getTexture()
+{
+ return mTexture.get();
+}
+
+const ImageIndex *TextureAttachment::getTextureImageIndex() const
+{
+ return &mIndex;
+}
+
+Renderbuffer *TextureAttachment::getRenderbuffer()
+{
+ UNREACHABLE();
+ return NULL;
+}
+
+////// RenderbufferAttachment Implementation //////
+
+RenderbufferAttachment::RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer)
+ : FramebufferAttachment(binding)
+{
+ ASSERT(renderbuffer);
+ mRenderbuffer.set(renderbuffer);
+}
+
+RenderbufferAttachment::~RenderbufferAttachment()
+{
+ mRenderbuffer.set(NULL);
+}
+
+GLsizei RenderbufferAttachment::getWidth() const
+{
+ return mRenderbuffer->getWidth();
+}
+
+GLsizei RenderbufferAttachment::getHeight() const
+{
+ return mRenderbuffer->getHeight();
+}
+
+GLenum RenderbufferAttachment::getInternalFormat() const
+{
+ return mRenderbuffer->getInternalFormat();
+}
+
+GLenum RenderbufferAttachment::getActualFormat() const
+{
+ return mRenderbuffer->getActualFormat();
+}
+
+GLsizei RenderbufferAttachment::getSamples() const
+{
+ return mRenderbuffer->getStorage()->getSamples();
+}
+
+GLuint RenderbufferAttachment::id() const
+{
+ return mRenderbuffer->id();
+}
+
+GLenum RenderbufferAttachment::type() const
+{
+ return GL_RENDERBUFFER;
+}
+
+GLint RenderbufferAttachment::mipLevel() const
+{
+ return 0;
+}
+
+GLint RenderbufferAttachment::layer() const
+{
+ return 0;
+}
+
+Texture *RenderbufferAttachment::getTexture()
+{
+ UNREACHABLE();
+ return NULL;
+}
+
+const ImageIndex *RenderbufferAttachment::getTextureImageIndex() const
+{
+ UNREACHABLE();
+ return NULL;
+}
+
+Renderbuffer *RenderbufferAttachment::getRenderbuffer()
+{
+ return mRenderbuffer.get();
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h
new file mode 100644
index 0000000000..c18ef7364d
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h
@@ -0,0 +1,139 @@
+//
+// 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 LIBGLESV2_FRAMEBUFFERATTACHMENT_H_
+#define LIBGLESV2_FRAMEBUFFERATTACHMENT_H_
+
+#include "common/angleutils.h"
+#include "common/RefCountObject.h"
+#include "Texture.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+class Renderer;
+class RenderTarget;
+class TextureStorage;
+}
+
+namespace gl
+{
+class Renderbuffer;
+
+// 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
+{
+ public:
+ explicit FramebufferAttachment(GLenum binding);
+ virtual ~FramebufferAttachment();
+
+ // 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 isTexture() const;
+
+ bool isTextureWithId(GLuint textureId) const { return isTexture() && id() == textureId; }
+ bool isRenderbufferWithId(GLuint renderbufferId) const { return !isTexture() && id() == renderbufferId; }
+
+ GLenum getBinding() const { return mBinding; }
+
+ // Child class interface
+ virtual GLsizei getWidth() const = 0;
+ virtual GLsizei getHeight() const = 0;
+ virtual GLenum getInternalFormat() const = 0;
+ virtual GLenum getActualFormat() const = 0;
+ virtual GLsizei getSamples() const = 0;
+
+ virtual GLuint id() const = 0;
+ virtual GLenum type() const = 0;
+ virtual GLint mipLevel() const = 0;
+ virtual GLint layer() const = 0;
+
+ virtual Texture *getTexture() = 0;
+ virtual const ImageIndex *getTextureImageIndex() const = 0;
+ virtual Renderbuffer *getRenderbuffer() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FramebufferAttachment);
+
+ GLenum mBinding;
+};
+
+class TextureAttachment : public FramebufferAttachment
+{
+ public:
+ TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index);
+ virtual ~TextureAttachment();
+
+ virtual GLsizei getSamples() const;
+ virtual GLuint id() const;
+
+ virtual GLsizei getWidth() const;
+ virtual GLsizei getHeight() const;
+ virtual GLenum getInternalFormat() const;
+ virtual GLenum getActualFormat() const;
+
+ virtual GLenum type() const;
+ virtual GLint mipLevel() const;
+ virtual GLint layer() const;
+
+ virtual Texture *getTexture();
+ virtual const ImageIndex *getTextureImageIndex() const;
+ virtual Renderbuffer *getRenderbuffer();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureAttachment);
+
+ BindingPointer<Texture> mTexture;
+ ImageIndex mIndex;
+};
+
+class RenderbufferAttachment : public FramebufferAttachment
+{
+ public:
+ RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer);
+
+ virtual ~RenderbufferAttachment();
+
+ virtual GLsizei getWidth() const;
+ virtual GLsizei getHeight() const;
+ virtual GLenum getInternalFormat() const;
+ virtual GLenum getActualFormat() const;
+ virtual GLsizei getSamples() const;
+
+ virtual GLuint id() const;
+ virtual GLenum type() const;
+ virtual GLint mipLevel() const;
+ virtual GLint layer() const;
+
+ virtual Texture *getTexture();
+ virtual const ImageIndex *getTextureImageIndex() const;
+ virtual Renderbuffer *getRenderbuffer();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment);
+
+ BindingPointer<Renderbuffer> mRenderbuffer;
+};
+
+}
+
+#endif // LIBGLESV2_FRAMEBUFFERATTACHMENT_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp
index 37da99aa18..c498f8a178 100644
--- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h
index a92e1684d4..a89cc86775 100644
--- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h
+++ b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h
@@ -10,12 +10,11 @@
#ifndef LIBGLESV2_HANDLEALLOCATOR_H_
#define LIBGLESV2_HANDLEALLOCATOR_H_
-#define GL_APICALL
-#include <GLES2/gl2.h>
+#include "common/angleutils.h"
-#include <vector>
+#include "angle_gl.h"
-#include "common/angleutils.h"
+#include <vector>
namespace gl
{
diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp
new file mode 100644
index 0000000000..3522b997e8
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp
@@ -0,0 +1,57 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ImageIndex.cpp: Implementation for ImageIndex methods.
+
+#include "libGLESv2/ImageIndex.h"
+#include "libGLESv2/Texture.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;
+}
+
+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, TextureCubeMap::targetToLayerIndex(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(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn)
+ : type(typeIn),
+ mipIndex(mipIndexIn),
+ layerIndex(layerIndexIn)
+{}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h b/src/3rdparty/angle/src/libGLESv2/ImageIndex.h
new file mode 100644
index 0000000000..9f2df88061
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/ImageIndex.h
@@ -0,0 +1,41 @@
+//
+// 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 LIBGLESV2_IMAGE_INDEX_H_
+#define LIBGLESV2_IMAGE_INDEX_H_
+
+#include "angle_gl.h"
+
+namespace gl
+{
+
+struct ImageIndex
+{
+ GLenum type;
+ GLint mipIndex;
+ GLint layerIndex;
+
+ ImageIndex(const ImageIndex &other);
+ ImageIndex &operator=(const ImageIndex &other);
+
+ bool hasLayer() const { return layerIndex != ENTIRE_LEVEL; }
+
+ 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 const GLint ENTIRE_LEVEL = static_cast<GLint>(-1);
+
+ private:
+ ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn);
+};
+
+}
+
+#endif // LIBGLESV2_IMAGE_INDEX_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp
index c38aa5a61a..9bfda09a64 100644
--- a/src/3rdparty/angle/src/libGLESv2/Program.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Program.cpp
@@ -1,6 +1,5 @@
-#include "precompiled.h"
//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -11,6 +10,7 @@
#include "libGLESv2/Program.h"
#include "libGLESv2/ProgramBinary.h"
#include "libGLESv2/ResourceManager.h"
+#include "libGLESv2/renderer/Renderer.h"
namespace gl
{
@@ -95,32 +95,36 @@ void InfoLog::append(const char *format, ...)
return;
}
- char info[1024];
-
va_list vararg;
va_start(vararg, format);
- vsnprintf(info, sizeof(info), format, vararg);
+ size_t infoLength = vsnprintf(NULL, 0, format, vararg);
va_end(vararg);
- size_t infoLength = strlen(info);
+ char *logPointer = NULL;
if (!mInfoLog)
{
mInfoLog = new char[infoLength + 2];
- strcpy(mInfoLog, info);
- strcpy(mInfoLog + infoLength, "\n");
+ logPointer = mInfoLog;
}
else
{
- size_t logLength = strlen(mInfoLog);
- char *newLog = new char[logLength + infoLength + 2];
+ size_t currentlogLength = strlen(mInfoLog);
+ char *newLog = new char[currentlogLength + infoLength + 2];
strcpy(newLog, mInfoLog);
- strcpy(newLog + logLength, info);
- strcpy(newLog + logLength + infoLength, "\n");
delete[] mInfoLog;
mInfoLog = newLog;
+
+ logPointer = mInfoLog + currentlogLength;
}
+
+ va_start(vararg, format);
+ vsnprintf(logPointer, infoLength, format, vararg);
+ va_end(vararg);
+
+ logPointer[infoLength] = 0;
+ strcpy(logPointer + infoLength, "\n");
}
void InfoLog::reset()
@@ -141,6 +145,8 @@ Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle
mLinked = false;
mRefCount = 0;
mRenderer = renderer;
+
+ resetUniformBlockBindings();
}
Program::~Program()
@@ -167,7 +173,7 @@ bool Program::attachShader(Shader *shader)
return false;
}
- mVertexShader = (VertexShader*)shader;
+ mVertexShader = shader;
mVertexShader->addRef();
}
else if (shader->getType() == GL_FRAGMENT_SHADER)
@@ -177,7 +183,7 @@ bool Program::attachShader(Shader *shader)
return false;
}
- mFragmentShader = (FragmentShader*)shader;
+ mFragmentShader = shader;
mFragmentShader->addRef();
}
else UNREACHABLE();
@@ -238,14 +244,16 @@ void Program::bindAttributeLocation(GLuint index, const char *name)
// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
// compiling them into binaries, determining the attribute mappings, and collecting
// a list of uniforms
-bool Program::link()
+bool Program::link(const Caps &caps)
{
unlink(false);
mInfoLog.reset();
+ resetUniformBlockBindings();
- mProgramBinary.set(new ProgramBinary(mRenderer));
- mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader);
+ mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
+ mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
+ mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps);
return mLinked;
}
@@ -290,19 +298,20 @@ bool Program::isLinked()
return mLinked;
}
-ProgramBinary* Program::getProgramBinary()
+ProgramBinary* Program::getProgramBinary() const
{
return mProgramBinary.get();
}
-bool Program::setProgramBinary(const void *binary, GLsizei length)
+bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
{
unlink(false);
mInfoLog.reset();
- mProgramBinary.set(new ProgramBinary(mRenderer));
- mLinked = mProgramBinary->load(mInfoLog, binary, length);
+ mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
+ mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
+
if (!mLinked)
{
mProgramBinary.set(NULL);
@@ -494,14 +503,14 @@ bool Program::isFlaggedForDeletion() const
return mDeleteStatus;
}
-void Program::validate()
+void Program::validate(const Caps &caps)
{
mInfoLog.reset();
ProgramBinary *programBinary = getProgramBinary();
if (isLinked() && programBinary)
{
- programBinary->validate(mInfoLog);
+ programBinary->validate(mInfoLog, caps);
}
else
{
@@ -522,4 +531,132 @@ bool Program::isValidated() const
}
}
+GLint Program::getActiveUniformBlockCount()
+{
+ ProgramBinary *programBinary = getProgramBinary();
+ if (programBinary)
+ {
+ return static_cast<GLint>(programBinary->getActiveUniformBlockCount());
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+GLint Program::getActiveUniformBlockMaxLength()
+{
+ ProgramBinary *programBinary = getProgramBinary();
+ if (programBinary)
+ {
+ return static_cast<GLint>(programBinary->getActiveUniformBlockMaxLength());
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+{
+ mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
+}
+
+GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
+{
+ return mUniformBlockBindings[uniformBlockIndex];
+}
+
+void Program::resetUniformBlockBindings()
+{
+ for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++)
+ {
+ mUniformBlockBindings[blockId] = 0;
+ }
+}
+
+void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
+{
+ mTransformFeedbackVaryings.resize(count);
+ for (GLsizei i = 0; i < count; i++)
+ {
+ mTransformFeedbackVaryings[i] = varyings[i];
+ }
+
+ mTransformFeedbackBufferMode = bufferMode;
+}
+
+void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
+{
+ ProgramBinary *programBinary = getProgramBinary();
+ if (programBinary && index < programBinary->getTransformFeedbackVaryingCount())
+ {
+ const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(index);
+ GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length()));
+ if (length)
+ {
+ *length = lastNameIdx;
+ }
+ if (size)
+ {
+ *size = varying.size;
+ }
+ if (type)
+ {
+ *type = varying.type;
+ }
+ if (name)
+ {
+ memcpy(name, varying.name.c_str(), lastNameIdx);
+ name[lastNameIdx] = '\0';
+ }
+ }
+}
+
+GLsizei Program::getTransformFeedbackVaryingCount() const
+{
+ ProgramBinary *programBinary = getProgramBinary();
+ if (programBinary)
+ {
+ return static_cast<GLsizei>(programBinary->getTransformFeedbackVaryingCount());
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+GLsizei Program::getTransformFeedbackVaryingMaxLength() const
+{
+ ProgramBinary *programBinary = getProgramBinary();
+ if (programBinary)
+ {
+ GLsizei maxSize = 0;
+ for (size_t i = 0; i < programBinary->getTransformFeedbackVaryingCount(); i++)
+ {
+ const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(i);
+ maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1));
+ }
+
+ return maxSize;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+GLenum Program::getTransformFeedbackBufferMode() const
+{
+ ProgramBinary *programBinary = getProgramBinary();
+ if (programBinary)
+ {
+ return programBinary->getTransformFeedbackBufferMode();
+ }
+ else
+ {
+ return mTransformFeedbackBufferMode;
+ }
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Program.h b/src/3rdparty/angle/src/libGLESv2/Program.h
index a9db83403d..6528dd1191 100644
--- a/src/3rdparty/angle/src/libGLESv2/Program.h
+++ b/src/3rdparty/angle/src/libGLESv2/Program.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -10,12 +10,16 @@
#ifndef LIBGLESV2_PROGRAM_H_
#define LIBGLESV2_PROGRAM_H_
-#include <string>
-#include <set>
-
#include "common/angleutils.h"
#include "common/RefCountObject.h"
#include "libGLESv2/Constants.h"
+#include "libGLESv2/ProgramBinary.h"
+
+#include <GLES2/gl2.h>
+
+#include <vector>
+#include <string>
+#include <set>
namespace rx
{
@@ -24,10 +28,8 @@ class Renderer;
namespace gl
{
+struct Caps;
class ResourceManager;
-class FragmentShader;
-class VertexShader;
-class ProgramBinary;
class Shader;
extern const char * const g_fakepath;
@@ -75,10 +77,10 @@ class Program
void bindAttributeLocation(GLuint index, const char *name);
- bool link();
+ bool link(const Caps &caps);
bool isLinked();
- bool setProgramBinary(const void *binary, GLsizei length);
- ProgramBinary *getProgramBinary();
+ bool setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length);
+ ProgramBinary *getProgramBinary() const;
int getInfoLogLength() const;
void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
@@ -92,13 +94,25 @@ class Program
GLint getActiveUniformCount();
GLint getActiveUniformMaxLength();
+ GLint getActiveUniformBlockCount();
+ GLint getActiveUniformBlockMaxLength();
+
+ void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+ GLuint getUniformBlockBinding(GLuint uniformBlockIndex) 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;
+
void addRef();
void release();
unsigned int getRefCount() const;
void flagForDeletion();
bool isFlaggedForDeletion() const;
- void validate();
+ void validate(const Caps &caps);
bool isValidated() const;
GLint getProgramBinaryLength() const;
@@ -107,12 +121,18 @@ class Program
DISALLOW_COPY_AND_ASSIGN(Program);
void unlink(bool destroy = false);
+ void resetUniformBlockBindings();
- FragmentShader *mFragmentShader;
- VertexShader *mVertexShader;
+ Shader *mFragmentShader;
+ Shader *mVertexShader;
AttributeBindings mAttributeBindings;
+ GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
+
+ std::vector<std::string> mTransformFeedbackVaryings;
+ GLuint mTransformFeedbackBufferMode;
+
BindingPointer<ProgramBinary> mProgramBinary;
bool mLinked;
bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use
diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
index 13c515a594..3f6d9e0ef9 100644
--- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
@@ -1,6 +1,5 @@
-#include "precompiled.h"
//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -10,109 +9,310 @@
#include "libGLESv2/BinaryStream.h"
#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
+#include "libGLESv2/Renderbuffer.h"
#include "libGLESv2/renderer/ShaderExecutable.h"
#include "common/debug.h"
#include "common/version.h"
-#include "utilities.h"
+#include "common/utilities.h"
+#include "common/platform.h"
#include "libGLESv2/main.h"
#include "libGLESv2/Shader.h"
#include "libGLESv2/Program.h"
+#include "libGLESv2/renderer/ProgramImpl.h"
#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/VertexDataManager.h"
-
-#undef near
-#undef far
+#include "libGLESv2/renderer/d3d/DynamicHLSL.h"
+#include "libGLESv2/renderer/d3d/ShaderD3D.h"
+#include "libGLESv2/renderer/d3d/VertexDataManager.h"
+#include "libGLESv2/Context.h"
+#include "libGLESv2/Buffer.h"
+#include "common/blocklayout.h"
namespace gl
{
-std::string str(int i)
+
+namespace
{
- char buffer[20];
- snprintf(buffer, sizeof(buffer), "%d", i);
- return buffer;
+
+GLenum GetTextureType(GLenum samplerType)
+{
+ switch (samplerType)
+ {
+ case GL_SAMPLER_2D:
+ case GL_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_SAMPLER_2D_SHADOW:
+ return GL_TEXTURE_2D;
+ case GL_SAMPLER_3D:
+ case GL_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ return GL_TEXTURE_3D;
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_CUBE_SHADOW:
+ return GL_TEXTURE_CUBE_MAP;
+ case GL_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ return GL_TEXTURE_CUBE_MAP;
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ return GL_TEXTURE_2D_ARRAY;
+ default: UNREACHABLE();
+ }
+
+ return GL_TEXTURE_2D;
}
-static rx::D3DWorkaroundType DiscardWorkaround(bool usesDiscard)
+unsigned int ParseAndStripArrayIndex(std::string* name)
{
- return (usesDiscard ? rx::ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER : rx::ANGLE_D3D_WORKAROUND_NONE);
+ unsigned int subscript = GL_INVALID_INDEX;
+
+ // Strip any trailing array operator and retrieve the subscript
+ size_t open = name->find_last_of('[');
+ size_t close = name->find_last_of(']');
+ if (open != std::string::npos && close == name->length() - 1)
+ {
+ subscript = atoi(name->substr(open + 1).c_str());
+ name->erase(open);
+ }
+
+ return subscript;
}
-UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index)
- : name(name), element(element), index(index)
+void GetDefaultInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])
{
+ size_t layoutIndex = 0;
+ for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
+ {
+ ASSERT(layoutIndex < MAX_VERTEX_ATTRIBS);
+
+ const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex];
+
+ if (shaderAttr.type != GL_NONE)
+ {
+ GLenum transposedType = TransposeMatrixType(shaderAttr.type);
+
+ for (size_t rowIndex = 0; static_cast<int>(rowIndex) < VariableRowCount(transposedType); rowIndex++, layoutIndex++)
+ {
+ VertexFormat *defaultFormat = &inputLayout[layoutIndex];
+
+ defaultFormat->mType = VariableComponentType(transposedType);
+ defaultFormat->mNormalized = false;
+ defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool
+ defaultFormat->mComponents = VariableColumnCount(transposedType);
+ }
+ }
+ }
}
-unsigned int ProgramBinary::mCurrentSerial = 1;
+std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<rx::PixelShaderOutputVariable> &shaderOutputVars)
+{
+ std::vector<GLenum> defaultPixelOutput(1);
-ProgramBinary::ProgramBinary(rx::Renderer *renderer) : mRenderer(renderer), RefCountObject(0), mSerial(issueSerial())
+ ASSERT(!shaderOutputVars.empty());
+ defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex;
+
+ return defaultPixelOutput;
+}
+
+bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
{
- mPixelExecutable = NULL;
- mVertexExecutable = NULL;
- mGeometryExecutable = NULL;
+ return var.isRowMajorLayout;
+}
- mValidated = false;
+bool IsRowMajorLayout(const sh::ShaderVariable &var)
+{
+ return false;
+}
- for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
- {
- mSemanticIndex[index] = -1;
- }
+}
- for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
+VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
+ : name(name), element(element), index(index)
+{
+}
+
+ProgramBinary::VertexExecutable::VertexExecutable(const VertexFormat inputLayout[],
+ const GLenum signature[],
+ rx::ShaderExecutable *shaderExecutable)
+ : mShaderExecutable(shaderExecutable)
+{
+ for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
{
- mSamplersPS[index].active = false;
+ mInputs[attributeIndex] = inputLayout[attributeIndex];
+ mSignature[attributeIndex] = signature[attributeIndex];
}
+}
+
+ProgramBinary::VertexExecutable::~VertexExecutable()
+{
+ SafeDelete(mShaderExecutable);
+}
- for (int index = 0; index < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++)
+bool ProgramBinary::VertexExecutable::matchesSignature(const GLenum signature[]) const
+{
+ for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
{
- mSamplersVS[index].active = false;
+ if (mSignature[attributeIndex] != signature[attributeIndex])
+ {
+ return false;
+ }
}
- mUsedVertexSamplerRange = 0;
- mUsedPixelSamplerRange = 0;
- mUsesPointSize = false;
+ return true;
}
-ProgramBinary::~ProgramBinary()
+ProgramBinary::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable)
+ : mOutputSignature(outputSignature),
+ mShaderExecutable(shaderExecutable)
+{
+}
+
+ProgramBinary::PixelExecutable::~PixelExecutable()
{
- delete mPixelExecutable;
- mPixelExecutable = NULL;
+ SafeDelete(mShaderExecutable);
+}
+
+LinkedVarying::LinkedVarying()
+{
+}
+
+LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName,
+ unsigned int semanticIndex, unsigned int semanticIndexCount)
+ : name(name), type(type), size(size), semanticName(semanticName), semanticIndex(semanticIndex), semanticIndexCount(semanticIndexCount)
+{
+}
- delete mVertexExecutable;
- mVertexExecutable = NULL;
+unsigned int ProgramBinary::mCurrentSerial = 1;
- delete mGeometryExecutable;
- mGeometryExecutable = NULL;
+ProgramBinary::ProgramBinary(rx::ProgramImpl *impl)
+ : RefCountObject(0),
+ mProgram(impl),
+ mGeometryExecutable(NULL),
+ mUsedVertexSamplerRange(0),
+ mUsedPixelSamplerRange(0),
+ mUsesPointSize(false),
+ mShaderVersion(100),
+ mDirtySamplerMapping(true),
+ mValidated(false),
+ mSerial(issueSerial())
+{
+ ASSERT(impl);
- while (!mUniforms.empty())
+ for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
{
- delete mUniforms.back();
- mUniforms.pop_back();
+ mSemanticIndex[index] = -1;
}
}
+ProgramBinary::~ProgramBinary()
+{
+ reset();
+ SafeDelete(mProgram);
+}
+
unsigned int ProgramBinary::getSerial() const
{
return mSerial;
}
+int ProgramBinary::getShaderVersion() const
+{
+ return mShaderVersion;
+}
+
unsigned int ProgramBinary::issueSerial()
{
return mCurrentSerial++;
}
-rx::ShaderExecutable *ProgramBinary::getPixelExecutable()
+rx::ShaderExecutable *ProgramBinary::getPixelExecutableForFramebuffer(const Framebuffer *fbo)
{
- return mPixelExecutable;
+ std::vector<GLenum> outputs;
+
+ const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender();
+
+ for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
+ {
+ const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
+
+ if (colorbuffer)
+ {
+ outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
+ }
+ else
+ {
+ outputs.push_back(GL_NONE);
+ }
+ }
+
+ return getPixelExecutableForOutputLayout(outputs);
+}
+
+rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature)
+{
+ for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
+ {
+ if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
+ {
+ return mPixelExecutables[executableIndex]->shaderExecutable();
+ }
+ }
+
+ InfoLog tempInfoLog;
+ rx::ShaderExecutable *pixelExecutable = mProgram->getPixelExecutableForOutputLayout(tempInfoLog, outputSignature,
+ mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
+
+ if (!pixelExecutable)
+ {
+ std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
+ tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
+ ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
+ }
+ else
+ {
+ mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
+ }
+
+ return pixelExecutable;
}
-rx::ShaderExecutable *ProgramBinary::getVertexExecutable()
+rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])
{
- return mVertexExecutable;
+ GLenum signature[MAX_VERTEX_ATTRIBS];
+ mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature);
+
+ for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
+ {
+ if (mVertexExecutables[executableIndex]->matchesSignature(signature))
+ {
+ return mVertexExecutables[executableIndex]->shaderExecutable();
+ }
+ }
+
+ InfoLog tempInfoLog;
+ rx::ShaderExecutable *vertexExecutable = mProgram->getVertexExecutableForInputLayout(tempInfoLog, inputLayout, mShaderAttributes,
+ mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
+
+ if (!vertexExecutable)
+ {
+ std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
+ tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
+ ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
+ }
+ else
+ {
+ mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable));
+ }
+
+ return vertexExecutable;
}
-rx::ShaderExecutable *ProgramBinary::getGeometryExecutable()
+rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() const
{
return mGeometryExecutable;
}
@@ -136,7 +336,7 @@ GLuint ProgramBinary::getAttributeLocation(const char *name)
int ProgramBinary::getSemanticIndex(int attributeIndex)
{
ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
-
+
return mSemanticIndex[attributeIndex];
}
@@ -162,7 +362,7 @@ bool ProgramBinary::usesPointSize() const
bool ProgramBinary::usesPointSpriteEmulation() const
{
- return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
+ return mUsesPointSize && mProgram->getRenderer()->getMajorShaderModel() >= 4;
}
bool ProgramBinary::usesGeometryShader() const
@@ -170,26 +370,22 @@ bool ProgramBinary::usesGeometryShader() const
return usesPointSpriteEmulation();
}
-// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
-// index (0-15 for the pixel shader and 0-3 for the vertex shader).
-GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
+GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps)
{
GLint logicalTextureUnit = -1;
switch (type)
{
case SAMPLER_PIXEL:
- ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
-
- if (mSamplersPS[samplerIndex].active)
+ ASSERT(samplerIndex < caps.maxTextureImageUnits);
+ if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
{
logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
}
break;
case SAMPLER_VERTEX:
- ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
-
- if (mSamplersVS[samplerIndex].active)
+ ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
+ if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
{
logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
}
@@ -197,7 +393,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd
default: UNREACHABLE();
}
- if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)mRenderer->getMaxCombinedTextureImageUnits())
+ if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
{
return logicalTextureUnit;
}
@@ -207,741 +403,504 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd
// 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).
-TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
+GLenum ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
{
switch (type)
{
case SAMPLER_PIXEL:
- ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
+ ASSERT(samplerIndex < mSamplersPS.size());
ASSERT(mSamplersPS[samplerIndex].active);
return mSamplersPS[samplerIndex].textureType;
case SAMPLER_VERTEX:
- ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
+ ASSERT(samplerIndex < mSamplersVS.size());
ASSERT(mSamplersVS[samplerIndex].active);
return mSamplersVS[samplerIndex].textureType;
default: UNREACHABLE();
}
- return TEXTURE_2D;
+ return GL_TEXTURE_2D;
}
GLint ProgramBinary::getUniformLocation(std::string name)
{
- unsigned int subscript = 0;
-
- // Strip any trailing array operator and retrieve the subscript
- size_t open = name.find_last_of('[');
- size_t close = name.find_last_of(']');
- if (open != std::string::npos && close == name.length() - 1)
- {
- subscript = atoi(name.substr(open + 1).c_str());
- name.erase(open);
- }
+ unsigned int subscript = ParseAndStripArrayIndex(&name);
unsigned int numUniforms = mUniformIndex.size();
for (unsigned int location = 0; location < numUniforms; location++)
{
- if (mUniformIndex[location].name == name &&
- mUniformIndex[location].element == subscript)
+ if (mUniformIndex[location].name == name)
{
- return location;
+ const int index = mUniformIndex[location].index;
+ const bool isArray = mUniforms[index]->isArray();
+
+ if ((isArray && mUniformIndex[location].element == subscript) ||
+ (subscript == GL_INVALID_INDEX))
+ {
+ return location;
+ }
}
}
return -1;
}
-bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+GLuint ProgramBinary::getUniformIndex(std::string name)
{
- if (location < 0 || location >= (int)mUniformIndex.size())
- {
- return false;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- targetUniform->dirty = true;
-
- int elementCount = targetUniform->elementCount();
-
- if (elementCount == 1 && count > 1)
- return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
- count = std::min(elementCount - (int)mUniformIndex[location].element, count);
+ unsigned int subscript = ParseAndStripArrayIndex(&name);
- if (targetUniform->type == GL_FLOAT)
+ // The app is not allowed to specify array indices other than 0 for arrays of basic types
+ if (subscript != 0 && subscript != GL_INVALID_INDEX)
{
- GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
-
- for (int i = 0; i < count; i++)
- {
- target[0] = v[0];
- target[1] = 0;
- target[2] = 0;
- target[3] = 0;
- target += 4;
- v += 1;
- }
+ return GL_INVALID_INDEX;
}
- else if (targetUniform->type == GL_BOOL)
- {
- GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
- for (int i = 0; i < count; i++)
+ unsigned int numUniforms = mUniforms.size();
+ for (unsigned int index = 0; index < numUniforms; index++)
+ {
+ if (mUniforms[index]->name == name)
{
- boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE;
- boolParams[1] = GL_FALSE;
- boolParams[2] = GL_FALSE;
- boolParams[3] = GL_FALSE;
- boolParams += 4;
- v += 1;
+ if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX)
+ {
+ return index;
+ }
}
}
- else
- {
- return false;
- }
- return true;
+ return GL_INVALID_INDEX;
}
-bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+GLuint ProgramBinary::getUniformBlockIndex(std::string name)
{
- if (location < 0 || location >= (int)mUniformIndex.size())
+ unsigned int subscript = ParseAndStripArrayIndex(&name);
+
+ unsigned int numUniformBlocks = mUniformBlocks.size();
+ for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
{
- return false;
+ const UniformBlock &uniformBlock = *mUniformBlocks[blockIndex];
+ if (uniformBlock.name == name)
+ {
+ const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0);
+ if (subscript == uniformBlock.elementIndex || arrayElementZero)
+ {
+ return blockIndex;
+ }
+ }
}
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- targetUniform->dirty = true;
-
- int elementCount = targetUniform->elementCount();
+ return GL_INVALID_INDEX;
+}
- if (elementCount == 1 && count > 1)
- return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+UniformBlock *ProgramBinary::getUniformBlockByIndex(GLuint blockIndex)
+{
+ ASSERT(blockIndex < mUniformBlocks.size());
+ return mUniformBlocks[blockIndex];
+}
- count = std::min(elementCount - (int)mUniformIndex[location].element, count);
+GLint ProgramBinary::getFragDataLocation(const char *name) const
+{
+ std::string baseName(name);
+ unsigned int arrayIndex;
+ arrayIndex = ParseAndStripArrayIndex(&baseName);
- if (targetUniform->type == GL_FLOAT_VEC2)
+ for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
{
- GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+ const VariableLocation &outputVariable = locationIt->second;
- for (int i = 0; i < count; i++)
+ if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
{
- target[0] = v[0];
- target[1] = v[1];
- target[2] = 0;
- target[3] = 0;
- target += 4;
- v += 2;
+ return static_cast<GLint>(locationIt->first);
}
}
- else if (targetUniform->type == GL_BOOL_VEC2)
- {
- GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
- for (int i = 0; i < count; i++)
- {
- boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE;
- boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE;
- boolParams[2] = GL_FALSE;
- boolParams[3] = GL_FALSE;
- boolParams += 4;
- v += 2;
- }
- }
- else
- {
- return false;
- }
+ return -1;
+}
- return true;
+size_t ProgramBinary::getTransformFeedbackVaryingCount() const
+{
+ return mTransformFeedbackLinkedVaryings.size();
}
-bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const
{
- if (location < 0 || location >= (int)mUniformIndex.size())
- {
- return false;
- }
+ return mTransformFeedbackLinkedVaryings[idx];
+}
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- targetUniform->dirty = true;
+GLenum ProgramBinary::getTransformFeedbackBufferMode() const
+{
+ return mTransformFeedbackBufferMode;
+}
- int elementCount = targetUniform->elementCount();
+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;
+}
- if (elementCount == 1 && count > 1)
- return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+template <typename T>
+void ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType)
+{
+ const int components = VariableComponentCount(targetUniformType);
+ const GLenum targetBoolType = VariableBoolVectorType(targetUniformType);
+
+ LinkedUniform *targetUniform = getUniformByLocation(location);
+
+ int elementCount = targetUniform->elementCount();
count = std::min(elementCount - (int)mUniformIndex[location].element, count);
- if (targetUniform->type == GL_FLOAT_VEC3)
+ if (targetUniform->type == targetUniformType)
{
- GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+ T *target = reinterpret_cast<T*>(targetUniform->data) + mUniformIndex[location].element * 4;
for (int i = 0; i < count; i++)
{
- target[0] = v[0];
- target[1] = v[1];
- target[2] = v[2];
- target[3] = 0;
- target += 4;
- v += 3;
+ 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 == GL_BOOL_VEC3)
+ else if (targetUniform->type == targetBoolType)
{
- GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
+ GLint *boolParams = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
for (int i = 0; i < count; i++)
{
- boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE;
- boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE;
- boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE;
- boolParams[3] = GL_FALSE;
- boolParams += 4;
- v += 3;
+ 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
+ else if (IsSampler(targetUniform->type))
{
- return false;
- }
-
- return true;
-}
-
-bool ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
-{
- if (location < 0 || location >= (int)mUniformIndex.size())
- {
- return false;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- targetUniform->dirty = true;
-
- int elementCount = targetUniform->elementCount();
-
- if (elementCount == 1 && count > 1)
- return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+ ASSERT(targetUniformType == GL_INT);
- count = std::min(elementCount - (int)mUniformIndex[location].element, count);
+ GLint *target = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
- if (targetUniform->type == GL_FLOAT_VEC4)
- {
- GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+ bool wasDirty = targetUniform->dirty;
for (int i = 0; i < count; i++)
{
- target[0] = v[0];
- target[1] = v[1];
- target[2] = v[2];
- target[3] = v[3];
- target += 4;
- v += 4;
+ 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);
}
- }
- else if (targetUniform->type == GL_BOOL_VEC4)
- {
- GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
- for (int i = 0; i < count; i++)
+ if (!wasDirty && targetUniform->dirty)
{
- boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE;
- boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE;
- boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE;
- boolParams[3] = (v[3] == 0.0f) ? GL_FALSE : GL_TRUE;
- boolParams += 4;
- v += 4;
+ mDirtySamplerMapping = true;
}
}
- else
- {
- return false;
- }
+ else UNREACHABLE();
+}
- return true;
+void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ setUniform(location, count, v, GL_FLOAT);
}
-template<typename T, int targetWidth, int targetHeight, int srcWidth, int srcHeight>
-void transposeMatrix(T *target, const GLfloat *value)
+void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
{
- int copyWidth = std::min(targetWidth, srcWidth);
- int copyHeight = std::min(targetHeight, srcHeight);
+ setUniform(location, count, v, GL_FLOAT_VEC2);
+}
+
+void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ setUniform(location, count, v, GL_FLOAT_VEC3);
+}
+
+void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ setUniform(location, count, v, GL_FLOAT_VEC4);
+}
+
+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++)
{
- target[x * targetWidth + y] = (T)value[y * srcWidth + x];
+ SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty);
}
}
// clear unfilled right side
- for (int y = 0; y < copyHeight; y++)
+ for (int y = 0; y < copyWidth; y++)
{
- for (int x = srcWidth; x < targetWidth; x++)
+ for (int x = copyHeight; x < targetWidth; x++)
{
- target[y * targetWidth + x] = (T)0;
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
}
}
// clear unfilled bottom.
- for (int y = srcHeight; y < targetHeight; y++)
+ for (int y = copyWidth; y < targetHeight; y++)
{
for (int x = 0; x < targetWidth; x++)
{
- target[y * targetWidth + x] = (T)0;
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
}
}
-}
-
-bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
-{
- if (location < 0 || location >= (int)mUniformIndex.size())
- {
- return false;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- targetUniform->dirty = true;
-
- if (targetUniform->type != GL_FLOAT_MAT2)
- {
- return false;
- }
-
- int elementCount = targetUniform->elementCount();
-
- if (elementCount == 1 && count > 1)
- return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
- count = std::min(elementCount - (int)mUniformIndex[location].element, count);
- GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8;
-
- for (int i = 0; i < count; i++)
- {
- transposeMatrix<GLfloat,4,2,2,2>(target, value);
- target += 8;
- value += 4;
- }
-
- return true;
-}
-
-bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
-{
- if (location < 0 || location >= (int)mUniformIndex.size())
- {
- return false;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- targetUniform->dirty = true;
-
- if (targetUniform->type != GL_FLOAT_MAT3)
- {
- return false;
- }
-
- int elementCount = targetUniform->elementCount();
- if (elementCount == 1 && count > 1)
- return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
- count = std::min(elementCount - (int)mUniformIndex[location].element, count);
- GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12;
-
- for (int i = 0; i < count; i++)
- {
- transposeMatrix<GLfloat,4,3,3,3>(target, value);
- target += 12;
- value += 9;
- }
-
- return true;
+ return dirty;
}
-
-bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
+template<typename T>
+bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
{
- if (location < 0 || location >= (int)mUniformIndex.size())
- {
- return false;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- targetUniform->dirty = true;
-
- if (targetUniform->type != GL_FLOAT_MAT4)
- {
- return false;
- }
-
- int elementCount = targetUniform->elementCount();
-
- if (elementCount == 1 && count > 1)
- return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
- count = std::min(elementCount - (int)mUniformIndex[location].element, count);
- GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16);
-
- for (int i = 0; i < count; i++)
- {
- transposeMatrix<GLfloat,4,4,4,4>(target, value);
- target += 16;
- value += 16;
- }
-
- return true;
-}
-
-bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)
-{
- if (location < 0 || location >= (int)mUniformIndex.size())
- {
- return false;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- targetUniform->dirty = true;
-
- int elementCount = targetUniform->elementCount();
-
- if (elementCount == 1 && count > 1)
- return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
- count = std::min(elementCount - (int)mUniformIndex[location].element, count);
+ bool dirty = false;
+ int copyWidth = std::min(targetWidth, srcWidth);
+ int copyHeight = std::min(targetHeight, srcHeight);
- if (targetUniform->type == GL_INT ||
- targetUniform->type == GL_SAMPLER_2D ||
- targetUniform->type == GL_SAMPLER_CUBE)
+ for (int y = 0; y < copyHeight; y++)
{
- GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
- for (int i = 0; i < count; i++)
+ for (int x = 0; x < copyWidth; x++)
{
- target[0] = v[0];
- target[1] = 0;
- target[2] = 0;
- target[3] = 0;
- target += 4;
- v += 1;
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty);
}
}
- else if (targetUniform->type == GL_BOOL)
+ // clear unfilled right side
+ for (int y = 0; y < copyHeight; y++)
{
- GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
- for (int i = 0; i < count; i++)
+ for (int x = copyWidth; x < targetWidth; x++)
{
- boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
- boolParams[1] = GL_FALSE;
- boolParams[2] = GL_FALSE;
- boolParams[3] = GL_FALSE;
- boolParams += 4;
- v += 1;
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
}
}
- else
+ // clear unfilled bottom.
+ for (int y = copyHeight; y < targetHeight; y++)
{
- return false;
+ for (int x = 0; x < targetWidth; x++)
+ {
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+ }
}
- return true;
+ return dirty;
}
-bool ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+template <int cols, int rows>
+void ProgramBinary::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType)
{
- if (location < 0 || location >= (int)mUniformIndex.size())
- {
- return false;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- targetUniform->dirty = true;
+ LinkedUniform *targetUniform = getUniformByLocation(location);
int elementCount = targetUniform->elementCount();
- if (elementCount == 1 && count > 1)
- return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
-
count = std::min(elementCount - (int)mUniformIndex[location].element, count);
+ const unsigned int targetMatrixStride = (4 * rows);
+ GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride);
- if (targetUniform->type == GL_INT_VEC2)
+ for (int i = 0; i < count; i++)
{
- GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
- for (int i = 0; i < count; i++)
+ // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
+ if (transpose == GL_FALSE)
{
- target[0] = v[0];
- target[1] = v[1];
- target[2] = 0;
- target[3] = 0;
- target += 4;
- v += 2;
+ targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty;
}
- }
- else if (targetUniform->type == GL_BOOL_VEC2)
- {
- GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
- for (int i = 0; i < count; i++)
+ else
{
- boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
- boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE;
- boolParams[2] = GL_FALSE;
- boolParams[3] = GL_FALSE;
- boolParams += 4;
- v += 2;
+ targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
}
+ target += targetMatrixStride;
+ value += cols * rows;
}
- else
- {
- return false;
- }
-
- return true;
}
-bool ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
{
- if (location < 0 || location >= (int)mUniformIndex.size())
- {
- return false;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- targetUniform->dirty = true;
+ setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
+}
- int elementCount = targetUniform->elementCount();
+void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
+}
- if (elementCount == 1 && count > 1)
- return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
+}
- count = std::min(elementCount - (int)mUniformIndex[location].element, count);
+void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
+}
- if (targetUniform->type == GL_INT_VEC3)
- {
- GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
+void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
+}
- for (int i = 0; i < count; i++)
- {
- target[0] = v[0];
- target[1] = v[1];
- target[2] = v[2];
- target[3] = 0;
- target += 4;
- v += 3;
- }
- }
- else if (targetUniform->type == GL_BOOL_VEC3)
- {
- GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
+void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
+}
- for (int i = 0; i < count; i++)
- {
- boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
- boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE;
- boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE;
- boolParams[3] = GL_FALSE;
- boolParams += 4;
- v += 3;
- }
- }
- else
- {
- return false;
- }
+void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
+}
- return true;
+void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+ setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
}
-bool ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
{
- if (location < 0 || location >= (int)mUniformIndex.size())
- {
- return false;
- }
+ setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
+}
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- targetUniform->dirty = true;
+void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+ setUniform(location, count, v, GL_INT);
+}
- int elementCount = targetUniform->elementCount();
+void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+ setUniform(location, count, v, GL_INT_VEC2);
+}
- if (elementCount == 1 && count > 1)
- return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+ setUniform(location, count, v, GL_INT_VEC3);
+}
- count = std::min(elementCount - (int)mUniformIndex[location].element, count);
+void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+ setUniform(location, count, v, GL_INT_VEC4);
+}
- if (targetUniform->type == GL_INT_VEC4)
- {
- GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
+void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ setUniform(location, count, v, GL_UNSIGNED_INT);
+}
- for (int i = 0; i < count; i++)
- {
- target[0] = v[0];
- target[1] = v[1];
- target[2] = v[2];
- target[3] = v[3];
- target += 4;
- v += 4;
- }
- }
- else if (targetUniform->type == GL_BOOL_VEC4)
- {
- GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
+void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
+}
- for (int i = 0; i < count; i++)
- {
- boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
- boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE;
- boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE;
- boolParams[3] = (v[3] == 0) ? GL_FALSE : GL_TRUE;
- boolParams += 4;
- v += 4;
- }
- }
- else
- {
- return false;
- }
+void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
+}
- return true;
+void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
}
-bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
+template <typename T>
+void ProgramBinary::getUniformv(GLint location, T *params, GLenum uniformType)
{
- if (location < 0 || location >= (int)mUniformIndex.size())
+ LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+ if (IsMatrixType(targetUniform->type))
{
- return false;
+ const int rows = VariableRowCount(targetUniform->type);
+ const int cols = VariableColumnCount(targetUniform->type);
+ transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows);
}
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- // sized queries -- ensure the provided buffer is large enough
- if (bufSize)
+ else if (uniformType == VariableComponentType(targetUniform->type))
{
- int requiredBytes = UniformExternalSize(targetUniform->type);
- if (*bufSize < requiredBytes)
- {
- return false;
- }
+ unsigned int size = VariableComponentCount(targetUniform->type);
+ memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T),
+ size * sizeof(T));
}
-
- switch (targetUniform->type)
+ else
{
- case GL_FLOAT_MAT2:
- transposeMatrix<GLfloat,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
- break;
- case GL_FLOAT_MAT3:
- transposeMatrix<GLfloat,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
- break;
- case GL_FLOAT_MAT4:
- transposeMatrix<GLfloat,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
- break;
- default:
+ unsigned int size = VariableComponentCount(targetUniform->type);
+ switch (VariableComponentType(targetUniform->type))
{
- unsigned int size = UniformComponentCount(targetUniform->type);
-
- switch (UniformComponentType(targetUniform->type))
+ case GL_BOOL:
{
- case GL_BOOL:
- {
- GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
+ GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
- for (unsigned int i = 0; i < size; i++)
- {
- params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
- }
- }
- break;
- case GL_FLOAT:
- memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLfloat),
- size * sizeof(GLfloat));
- break;
- case GL_INT:
+ for (unsigned int i = 0; i < size; i++)
{
- GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
- for (unsigned int i = 0; i < size; i++)
- {
- params[i] = (float)intParams[i];
- }
+ params[i] = (boolParams[i] == GL_FALSE) ? static_cast<T>(0) : static_cast<T>(1);
}
- break;
- default: UNREACHABLE();
}
- }
- }
-
- return true;
-}
+ break;
-bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
-{
- if (location < 0 || location >= (int)mUniformIndex.size())
- {
- return false;
- }
+ case GL_FLOAT:
+ {
+ GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+ for (unsigned int i = 0; i < size; i++)
+ {
+ params[i] = static_cast<T>(floatParams[i]);
+ }
+ }
+ break;
- // sized queries -- ensure the provided buffer is large enough
- if (bufSize)
- {
- int requiredBytes = UniformExternalSize(targetUniform->type);
- if (*bufSize < requiredBytes)
- {
- return false;
- }
- }
+ case GL_INT:
+ {
+ GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
- switch (targetUniform->type)
- {
- case GL_FLOAT_MAT2:
- transposeMatrix<GLint,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
- break;
- case GL_FLOAT_MAT3:
- transposeMatrix<GLint,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
- break;
- case GL_FLOAT_MAT4:
- transposeMatrix<GLint,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
- break;
- default:
- {
- unsigned int size = VariableColumnCount(targetUniform->type);
+ for (unsigned int i = 0; i < size; i++)
+ {
+ params[i] = static_cast<T>(intParams[i]);
+ }
+ }
+ break;
- switch (UniformComponentType(targetUniform->type))
+ case GL_UNSIGNED_INT:
{
- case GL_BOOL:
- {
- GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
+ GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4;
- for (unsigned int i = 0; i < size; i++)
- {
- params[i] = boolParams[i];
- }
- }
- break;
- case GL_FLOAT:
+ for (unsigned int i = 0; i < size; i++)
{
- GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
-
- for (unsigned int i = 0; i < size; i++)
- {
- params[i] = (GLint)floatParams[i];
- }
+ params[i] = static_cast<T>(uintParams[i]);
}
- break;
- case GL_INT:
- memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLint),
- size * sizeof(GLint));
- break;
- default: UNREACHABLE();
}
+ break;
+
+ default: UNREACHABLE();
}
}
+}
- return true;
+void ProgramBinary::getUniformfv(GLint location, GLfloat *params)
+{
+ getUniformv(location, params, GL_FLOAT);
+}
+
+void ProgramBinary::getUniformiv(GLint location, GLint *params)
+{
+ getUniformv(location, params, GL_INT);
+}
+
+void ProgramBinary::getUniformuiv(GLint location, GLuint *params)
+{
+ getUniformv(location, params, GL_UNSIGNED_INT);
}
void ProgramBinary::dirtyAllUniforms()
@@ -953,23 +912,28 @@ void ProgramBinary::dirtyAllUniforms()
}
}
-// Applies all the uniforms set for this program object to the renderer
-void ProgramBinary::applyUniforms()
+void ProgramBinary::updateSamplerMapping()
{
+ if (!mDirtySamplerMapping)
+ {
+ return;
+ }
+
+ mDirtySamplerMapping = false;
+
// Retrieve sampler uniform values
- for (std::vector<Uniform*>::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub)
+ for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
{
- Uniform *targetUniform = *ub;
+ LinkedUniform *targetUniform = mUniforms[uniformIndex];
if (targetUniform->dirty)
{
- if (targetUniform->type == GL_SAMPLER_2D ||
- targetUniform->type == GL_SAMPLER_CUBE)
+ if (IsSampler(targetUniform->type))
{
int count = targetUniform->elementCount();
- GLint (*v)[4] = (GLint(*)[4])targetUniform->data;
+ GLint (*v)[4] = reinterpret_cast<GLint(*)[4]>(targetUniform->data);
- if (targetUniform->psRegisterIndex >= 0)
+ if (targetUniform->isReferencedByFragmentShader())
{
unsigned int firstIndex = targetUniform->psRegisterIndex;
@@ -977,7 +941,7 @@ void ProgramBinary::applyUniforms()
{
unsigned int samplerIndex = firstIndex + i;
- if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
+ if (samplerIndex < mSamplersPS.size())
{
ASSERT(mSamplersPS[samplerIndex].active);
mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
@@ -985,7 +949,7 @@ void ProgramBinary::applyUniforms()
}
}
- if (targetUniform->vsRegisterIndex >= 0)
+ if (targetUniform->isReferencedByVertexShader())
{
unsigned int firstIndex = targetUniform->vsRegisterIndex;
@@ -993,7 +957,7 @@ void ProgramBinary::applyUniforms()
{
unsigned int samplerIndex = firstIndex + i;
- if (samplerIndex < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS)
+ if (samplerIndex < mSamplersVS.size())
{
ASSERT(mSamplersVS[samplerIndex].active);
mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
@@ -1003,882 +967,568 @@ void ProgramBinary::applyUniforms()
}
}
}
-
- mRenderer->applyUniforms(this, &mUniforms);
}
-// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
-// Returns the number of used varying registers, or -1 if unsuccesful
-int ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader)
+// Applies all the uniforms set for this program object to the renderer
+Error ProgramBinary::applyUniforms()
{
- const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
+ updateSamplerMapping();
- fragmentShader->resetVaryingsRegisterAssignment();
-
- for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
+ Error error = mProgram->getRenderer()->applyUniforms(*this);
+ if (error.isError())
{
- int n = VariableRowCount(varying->type) * varying->size;
- int m = VariableColumnCount(varying->type);
- bool success = false;
-
- if (m == 2 || m == 3 || m == 4)
- {
- for (int r = 0; r <= maxVaryingVectors - n && !success; r++)
- {
- bool available = true;
-
- for (int y = 0; y < n && available; y++)
- {
- for (int x = 0; x < m && available; x++)
- {
- if (packing[r + y][x])
- {
- available = false;
- }
- }
- }
+ return error;
+ }
- if (available)
- {
- varying->reg = r;
- varying->col = 0;
+ for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+ {
+ mUniforms[uniformIndex]->dirty = false;
+ }
- for (int y = 0; y < n; y++)
- {
- for (int x = 0; x < m; x++)
- {
- packing[r + y][x] = &*varying;
- }
- }
+ return gl::Error(GL_NO_ERROR);
+}
- success = true;
- }
- }
+Error ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const Caps &caps)
+{
+ const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL};
+ const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL};
- if (!success && m == 2)
- {
- for (int r = maxVaryingVectors - n; r >= 0 && !success; r--)
- {
- bool available = true;
+ const unsigned int reservedBuffersInVS = mProgram->getRenderer()->getReservedVertexUniformBuffers();
+ const unsigned int reservedBuffersInFS = mProgram->getRenderer()->getReservedFragmentUniformBuffers();
- for (int y = 0; y < n && available; y++)
- {
- for (int x = 2; x < 4 && available; x++)
- {
- if (packing[r + y][x])
- {
- available = false;
- }
- }
- }
+ ASSERT(boundBuffers.size() == mUniformBlocks.size());
- if (available)
- {
- varying->reg = r;
- varying->col = 2;
+ for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++)
+ {
+ UniformBlock *uniformBlock = getUniformBlockByIndex(uniformBlockIndex);
+ gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex];
- for (int y = 0; y < n; y++)
- {
- for (int x = 2; x < 4; x++)
- {
- packing[r + y][x] = &*varying;
- }
- }
+ ASSERT(uniformBlock && uniformBuffer);
- success = true;
- }
- }
- }
- }
- else if (m == 1)
+ if (uniformBuffer->getSize() < uniformBlock->dataSize)
{
- int space[4] = {0};
-
- for (int y = 0; y < maxVaryingVectors; y++)
- {
- for (int x = 0; x < 4; x++)
- {
- space[x] += packing[y][x] ? 0 : 1;
- }
- }
-
- int column = 0;
-
- for (int x = 0; x < 4; x++)
- {
- if (space[x] >= n && space[x] < space[column])
- {
- column = x;
- }
- }
-
- if (space[column] >= n)
- {
- for (int r = 0; r < maxVaryingVectors; r++)
- {
- if (!packing[r][column])
- {
- varying->reg = r;
-
- for (int y = r; y < r + n; y++)
- {
- packing[y][column] = &*varying;
- }
-
- break;
- }
- }
-
- varying->col = column;
-
- success = true;
- }
+ // undefined behaviour
+ return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small.");
}
- else UNREACHABLE();
- if (!success)
+ // Unnecessary to apply an unreferenced standard or shared UBO
+ if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader())
{
- infoLog.append("Could not pack varying %s", varying->name.c_str());
-
- return -1;
+ continue;
}
- }
- // Return the number of used registers
- int registers = 0;
+ if (uniformBlock->isReferencedByVertexShader())
+ {
+ unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
+ ASSERT(vertexUniformBuffers[registerIndex] == NULL);
+ ASSERT(registerIndex < caps.maxVertexUniformBlocks);
+ vertexUniformBuffers[registerIndex] = uniformBuffer;
+ }
- for (int r = 0; r < maxVaryingVectors; r++)
- {
- if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
+ if (uniformBlock->isReferencedByFragmentShader())
{
- registers++;
+ unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
+ ASSERT(fragmentUniformBuffers[registerIndex] == NULL);
+ ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
+ fragmentUniformBuffers[registerIndex] = uniformBuffer;
}
}
- return registers;
+ return mProgram->getRenderer()->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
}
-bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4],
- std::string& pixelHLSL, std::string& vertexHLSL,
- FragmentShader *fragmentShader, VertexShader *vertexShader)
+bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader)
{
- if (pixelHLSL.empty() || vertexHLSL.empty())
- {
- return false;
- }
-
- bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
- bool usesFragColor = fragmentShader->mUsesFragColor;
- bool usesFragData = fragmentShader->mUsesFragData;
- if (usesFragColor && usesFragData)
- {
- infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
- return false;
- }
-
- // Write the HLSL input/output declarations
- const int shaderModel = mRenderer->getMajorShaderModel();
- const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
-
- const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0);
-
- // The output color is broadcast to all enabled draw buffers when writing to gl_FragColor
- const bool broadcast = fragmentShader->mUsesFragColor;
- const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1);
+ std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
+ std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings();
- if (registersNeeded > maxVaryingVectors)
- {
- infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
-
- return false;
- }
-
- vertexShader->resetVaryingsRegisterAssignment();
-
- for (VaryingList::iterator input = fragmentShader->mVaryings.begin(); input != fragmentShader->mVaryings.end(); input++)
+ for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++)
{
+ PackedVarying *input = &fragmentVaryings[fragVaryingIndex];
bool matched = false;
- for (VaryingList::iterator output = vertexShader->mVaryings.begin(); output != vertexShader->mVaryings.end(); output++)
+ // Built-in varyings obey special rules
+ if (input->isBuiltIn())
+ {
+ continue;
+ }
+
+ for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++)
{
+ PackedVarying *output = &vertexVaryings[vertVaryingIndex];
if (output->name == input->name)
{
- if (output->type != input->type || output->size != input->size)
+ if (!linkValidateVaryings(infoLog, output->name, *input, *output))
{
- infoLog.append("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
-
return false;
}
- output->reg = input->reg;
- output->col = input->col;
+ output->registerIndex = input->registerIndex;
+ output->columnIndex = input->columnIndex;
matched = true;
break;
}
}
- if (!matched)
+ // We permit unmatched, unreferenced varyings
+ if (!matched && input->staticUse)
{
infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
-
return false;
}
}
- mUsesPointSize = vertexShader->mUsesPointSize;
- std::string varyingSemantic = (mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
- std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
- std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
- std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
-
- // special varyings that use reserved registers
- int reservedRegisterIndex = registers;
- std::string fragCoordSemantic;
- std::string pointCoordSemantic;
-
- if (fragmentShader->mUsesFragCoord)
- {
- fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
- }
-
- if (fragmentShader->mUsesPointCoord)
- {
- // Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords.
- // In DX11 we compute this in the GS.
- if (shaderModel == 3)
- {
- pointCoordSemantic = "TEXCOORD0";
- }
- else if (shaderModel >= 4)
- {
- pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
- }
- }
-
- vertexHLSL += "struct VS_INPUT\n"
- "{\n";
-
- int semanticIndex = 0;
- for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
- {
- switch (attribute->type)
- {
- case GL_FLOAT: vertexHLSL += " float "; break;
- case GL_FLOAT_VEC2: vertexHLSL += " float2 "; break;
- case GL_FLOAT_VEC3: vertexHLSL += " float3 "; break;
- case GL_FLOAT_VEC4: vertexHLSL += " float4 "; break;
- case GL_FLOAT_MAT2: vertexHLSL += " float2x2 "; break;
- case GL_FLOAT_MAT3: vertexHLSL += " float3x3 "; break;
- case GL_FLOAT_MAT4: vertexHLSL += " float4x4 "; break;
- default: UNREACHABLE();
- }
+ return true;
+}
- vertexHLSL += decorateAttribute(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
+bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length)
+{
+#ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
+ return false;
+#else
+ ASSERT(binaryFormat == mProgram->getBinaryFormat());
- semanticIndex += VariableRowCount(attribute->type);
- }
+ reset();
- vertexHLSL += "};\n"
- "\n"
- "struct VS_OUTPUT\n"
- "{\n";
+ BinaryInputStream stream(binary, length);
- if (shaderModel < 4)
+ GLenum format = stream.readInt<GLenum>();
+ if (format != mProgram->getBinaryFormat())
{
- vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
+ infoLog.append("Invalid program binary format.");
+ return false;
}
- for (int r = 0; r < registers; r++)
+ int majorVersion = stream.readInt<int>();
+ int minorVersion = stream.readInt<int>();
+ if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
{
- int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
-
- vertexHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
+ infoLog.append("Invalid program binary version.");
+ return false;
}
- if (fragmentShader->mUsesFragCoord)
+ 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)
{
- vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
+ infoLog.append("Invalid program binary version.");
+ return false;
}
- if (vertexShader->mUsesPointSize && shaderModel >= 3)
+ int compileFlags = stream.readInt<int>();
+ if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
{
- vertexHLSL += " float gl_PointSize : PSIZE;\n";
+ infoLog.append("Mismatched compilation flags.");
+ return false;
}
- if (shaderModel >= 4)
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
{
- vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
+ stream.readInt(&mLinkedAttribute[i].type);
+ stream.readString(&mLinkedAttribute[i].name);
+ stream.readInt(&mShaderAttributes[i].type);
+ stream.readString(&mShaderAttributes[i].name);
+ stream.readInt(&mSemanticIndex[i]);
}
- vertexHLSL += "};\n"
- "\n"
- "VS_OUTPUT main(VS_INPUT input)\n"
- "{\n";
-
- for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
- {
- vertexHLSL += " " + decorateAttribute(attribute->name) + " = ";
-
- if (VariableRowCount(attribute->type) > 1) // Matrix
- {
- vertexHLSL += "transpose";
- }
-
- vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n";
- }
+ initAttributesByLayout();
- if (shaderModel >= 4)
+ const unsigned int psSamplerCount = stream.readInt<unsigned int>();
+ for (unsigned int i = 0; i < psSamplerCount; ++i)
{
- vertexHLSL += "\n"
- " gl_main();\n"
- "\n"
- " VS_OUTPUT output;\n"
- " output.gl_Position.x = gl_Position.x;\n"
- " output.gl_Position.y = -gl_Position.y;\n"
- " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
- " output.gl_Position.w = gl_Position.w;\n";
+ Sampler sampler;
+ stream.readBool(&sampler.active);
+ stream.readInt(&sampler.logicalTextureUnit);
+ stream.readInt(&sampler.textureType);
+ mSamplersPS.push_back(sampler);
}
- else
+ const unsigned int vsSamplerCount = stream.readInt<unsigned int>();
+ for (unsigned int i = 0; i < vsSamplerCount; ++i)
{
- vertexHLSL += "\n"
- " gl_main();\n"
- "\n"
- " VS_OUTPUT output;\n"
- " output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
- " output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
- " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
- " output.gl_Position.w = gl_Position.w;\n";
+ Sampler sampler;
+ stream.readBool(&sampler.active);
+ stream.readInt(&sampler.logicalTextureUnit);
+ stream.readInt(&sampler.textureType);
+ mSamplersVS.push_back(sampler);
}
- if (vertexShader->mUsesPointSize && shaderModel >= 3)
- {
- vertexHLSL += " output.gl_PointSize = gl_PointSize;\n";
- }
+ stream.readInt(&mUsedVertexSamplerRange);
+ stream.readInt(&mUsedPixelSamplerRange);
+ stream.readBool(&mUsesPointSize);
+ stream.readInt(&mShaderVersion);
- if (fragmentShader->mUsesFragCoord)
+ const unsigned int uniformCount = stream.readInt<unsigned int>();
+ if (stream.error())
{
- vertexHLSL += " output.gl_FragCoord = gl_Position;\n";
+ infoLog.append("Invalid program binary.");
+ return false;
}
- for (VaryingList::iterator varying = vertexShader->mVaryings.begin(); varying != vertexShader->mVaryings.end(); varying++)
+ mUniforms.resize(uniformCount);
+ for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
{
- if (varying->reg >= 0)
- {
- for (int i = 0; i < varying->size; i++)
- {
- int rows = VariableRowCount(varying->type);
+ GLenum type = stream.readInt<GLenum>();
+ GLenum precision = stream.readInt<GLenum>();
+ std::string name = stream.readString();
+ unsigned int arraySize = stream.readInt<unsigned int>();
+ int blockIndex = stream.readInt<int>();
- for (int j = 0; j < rows; j++)
- {
- int r = varying->reg + i * rows + j;
- vertexHLSL += " output.v" + str(r);
+ int offset = stream.readInt<int>();
+ int arrayStride = stream.readInt<int>();
+ int matrixStride = stream.readInt<int>();
+ bool isRowMajorMatrix = stream.readBool();
- bool sharedRegister = false; // Register used by multiple varyings
-
- for (int x = 0; x < 4; x++)
- {
- if (packing[r][x] && packing[r][x] != packing[r][0])
- {
- sharedRegister = true;
- break;
- }
- }
-
- if(sharedRegister)
- {
- vertexHLSL += ".";
+ const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix);
- for (int x = 0; x < 4; x++)
- {
- if (packing[r][x] == &*varying)
- {
- switch(x)
- {
- case 0: vertexHLSL += "x"; break;
- case 1: vertexHLSL += "y"; break;
- case 2: vertexHLSL += "z"; break;
- case 3: vertexHLSL += "w"; break;
- }
- }
- }
- }
+ LinkedUniform *uniform = new LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo);
- vertexHLSL += " = " + varying->name;
-
- if (varying->array)
- {
- vertexHLSL += "[" + str(i) + "]";
- }
+ stream.readInt(&uniform->psRegisterIndex);
+ stream.readInt(&uniform->vsRegisterIndex);
+ stream.readInt(&uniform->registerCount);
+ stream.readInt(&uniform->registerElement);
- if (rows > 1)
- {
- vertexHLSL += "[" + str(j) + "]";
- }
-
- vertexHLSL += ";\n";
- }
- }
- }
+ mUniforms[uniformIndex] = uniform;
}
- vertexHLSL += "\n"
- " return output;\n"
- "}\n";
+ unsigned int uniformBlockCount = stream.readInt<unsigned int>();
+ if (stream.error())
+ {
+ infoLog.append("Invalid program binary.");
+ return false;
+ }
- pixelHLSL += "struct PS_INPUT\n"
- "{\n";
-
- for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
+ mUniformBlocks.resize(uniformBlockCount);
+ for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
{
- if (varying->reg >= 0)
+ std::string name = stream.readString();
+ unsigned int elementIndex = stream.readInt<unsigned int>();
+ unsigned int dataSize = stream.readInt<unsigned int>();
+
+ UniformBlock *uniformBlock = new UniformBlock(name, elementIndex, dataSize);
+
+ stream.readInt(&uniformBlock->psRegisterIndex);
+ stream.readInt(&uniformBlock->vsRegisterIndex);
+
+ unsigned int numMembers = stream.readInt<unsigned int>();
+ uniformBlock->memberUniformIndexes.resize(numMembers);
+ for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
{
- for (int i = 0; i < varying->size; i++)
- {
- int rows = VariableRowCount(varying->type);
- for (int j = 0; j < rows; j++)
- {
- std::string n = str(varying->reg + i * rows + j);
- pixelHLSL += " float" + str(VariableColumnCount(varying->type)) + " v" + n + " : " + varyingSemantic + n + ";\n";
- }
- }
+ stream.readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]);
}
- else UNREACHABLE();
+
+ mUniformBlocks[uniformBlockIndex] = uniformBlock;
}
- if (fragmentShader->mUsesFragCoord)
+ const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
+ if (stream.error())
{
- pixelHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
+ infoLog.append("Invalid program binary.");
+ return false;
}
-
- if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
+
+ mUniformIndex.resize(uniformIndexCount);
+ for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++)
{
- pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
+ stream.readString(&mUniformIndex[uniformIndexIndex].name);
+ stream.readInt(&mUniformIndex[uniformIndexIndex].element);
+ stream.readInt(&mUniformIndex[uniformIndexIndex].index);
}
- // Must consume the PSIZE element if the geometry shader is not active
- // We won't know if we use a GS until we draw
- if (vertexShader->mUsesPointSize && shaderModel >= 4)
+ stream.readInt(&mTransformFeedbackBufferMode);
+ const unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
+ mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
+ for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
{
- pixelHLSL += " float gl_PointSize : PSIZE;\n";
+ LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
+
+ stream.readString(&varying.name);
+ stream.readInt(&varying.type);
+ stream.readInt(&varying.size);
+ stream.readString(&varying.semanticName);
+ stream.readInt(&varying.semanticIndex);
+ stream.readInt(&varying.semanticIndexCount);
}
- if (fragmentShader->mUsesFragCoord)
+ const unsigned int vertexShaderCount = stream.readInt<unsigned int>();
+ for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
{
- if (shaderModel >= 4)
+ VertexFormat inputLayout[MAX_VERTEX_ATTRIBS];
+
+ for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++)
{
- pixelHLSL += " float4 dx_VPos : SV_Position;\n";
+ VertexFormat *vertexInput = &inputLayout[inputIndex];
+ stream.readInt(&vertexInput->mType);
+ stream.readInt(&vertexInput->mNormalized);
+ stream.readInt(&vertexInput->mComponents);
+ stream.readBool(&vertexInput->mPureInteger);
}
- else if (shaderModel >= 3)
+
+ unsigned int vertexShaderSize = stream.readInt<unsigned int>();
+ const unsigned char *vertexShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset();
+ rx::ShaderExecutable *shaderExecutable = mProgram->getRenderer()->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction),
+ vertexShaderSize, rx::SHADER_VERTEX,
+ mTransformFeedbackLinkedVaryings,
+ (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
+ if (!shaderExecutable)
{
- pixelHLSL += " float2 dx_VPos : VPOS;\n";
+ infoLog.append("Could not create vertex shader.");
+ return false;
}
- }
- pixelHLSL += "};\n"
- "\n"
- "struct PS_OUTPUT\n"
- "{\n";
+ // generated converted input layout
+ GLenum signature[MAX_VERTEX_ATTRIBS];
+ mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature);
- for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
- {
- pixelHLSL += " float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n";
- }
+ // add new binary
+ mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
- if (fragmentShader->mUsesFragDepth)
- {
- pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n";
+ stream.skip(vertexShaderSize);
}
- pixelHLSL += "};\n"
- "\n";
-
- if (fragmentShader->mUsesFrontFacing)
+ const size_t pixelShaderCount = stream.readInt<unsigned int>();
+ for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
{
- if (shaderModel >= 4)
- {
- pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
- "{\n";
- }
- else
+ const size_t outputCount = stream.readInt<unsigned int>();
+ std::vector<GLenum> outputs(outputCount);
+ for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
{
- pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
- "{\n";
+ stream.readInt(&outputs[outputIndex]);
}
- }
- else
- {
- pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n"
- "{\n";
- }
- if (fragmentShader->mUsesFragCoord)
- {
- pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
-
- if (shaderModel >= 4)
- {
- pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n"
- " gl_FragCoord.y = input.dx_VPos.y;\n";
- }
- else if (shaderModel >= 3)
- {
- pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
- " gl_FragCoord.y = input.dx_VPos.y + 0.5;\n";
- }
- else
+ const size_t pixelShaderSize = stream.readInt<unsigned int>();
+ const unsigned char *pixelShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset();
+ rx::Renderer *renderer = mProgram->getRenderer();
+ rx::ShaderExecutable *shaderExecutable = renderer->loadExecutable(pixelShaderFunction, pixelShaderSize,
+ rx::SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
+ (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
+
+ if (!shaderExecutable)
{
- // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport()
- pixelHLSL += " 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";
+ infoLog.append("Could not create pixel shader.");
+ return false;
}
-
- pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n"
- " gl_FragCoord.w = rhw;\n";
- }
- if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
- {
- pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n";
- pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
+ // add new binary
+ mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
+
+ stream.skip(pixelShaderSize);
}
- if (fragmentShader->mUsesFrontFacing)
+ unsigned int geometryShaderSize = stream.readInt<unsigned int>();
+
+ if (geometryShaderSize > 0)
{
- if (shaderModel <= 3)
- {
- pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
- }
- else
+ const char *geometryShaderFunction = (const char*) binary + stream.offset();
+ rx::Renderer *renderer = mProgram->getRenderer();
+ mGeometryExecutable = renderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction),
+ geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
+ (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
+
+ if (!mGeometryExecutable)
{
- pixelHLSL += " gl_FrontFacing = isFrontFace;\n";
+ infoLog.append("Could not create geometry shader.");
+ return false;
}
+ stream.skip(geometryShaderSize);
}
- for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
+ if (!mProgram->load(infoLog, &stream))
{
- if (varying->reg >= 0)
- {
- for (int i = 0; i < varying->size; i++)
- {
- int rows = VariableRowCount(varying->type);
- for (int j = 0; j < rows; j++)
- {
- std::string n = str(varying->reg + i * rows + j);
- pixelHLSL += " " + varying->name;
-
- if (varying->array)
- {
- pixelHLSL += "[" + str(i) + "]";
- }
-
- if (rows > 1)
- {
- pixelHLSL += "[" + str(j) + "]";
- }
-
- switch (VariableColumnCount(varying->type))
- {
- case 1: pixelHLSL += " = input.v" + n + ".x;\n"; break;
- case 2: pixelHLSL += " = input.v" + n + ".xy;\n"; break;
- case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break;
- case 4: pixelHLSL += " = input.v" + n + ";\n"; break;
- default: UNREACHABLE();
- }
- }
- }
- }
- else UNREACHABLE();
+ return false;
}
- pixelHLSL += "\n"
- " gl_main();\n"
- "\n"
- " PS_OUTPUT output;\n";
-
- for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
- {
- unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
+ const char *ptr = (const char*) binary + stream.offset();
- pixelHLSL += " output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n";
- }
+ const GUID *binaryIdentifier = (const GUID *) ptr;
+ ptr += sizeof(GUID);
- if (fragmentShader->mUsesFragDepth)
+ GUID identifier = mProgram->getRenderer()->getAdapterIdentifier();
+ if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0)
{
- pixelHLSL += " output.gl_Depth = gl_Depth;\n";
+ infoLog.append("Invalid program binary.");
+ return false;
}
- pixelHLSL += "\n"
- " return output;\n"
- "}\n";
+ mProgram->initializeUniformStorage(mUniforms);
return true;
+#endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
}
-bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
+bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length)
{
- BinaryInputStream stream(binary, length);
-
- int format = 0;
- stream.read(&format);
- if (format != GL_PROGRAM_BINARY_ANGLE)
+ if (binaryFormat)
{
- infoLog.append("Invalid program binary format.");
- return false;
+ *binaryFormat = mProgram->getBinaryFormat();
}
- int majorVersion = 0;
- int minorVersion = 0;
- stream.read(&majorVersion);
- stream.read(&minorVersion);
- if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
- {
- infoLog.append("Invalid program binary version.");
- return false;
- }
+ BinaryOutputStream stream;
-#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY)
- unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
- stream.read(commitString, ANGLE_COMMIT_HASH_SIZE);
- if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0)
+ stream.writeInt(mProgram->getBinaryFormat());
+ 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(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
+
+ for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
{
- infoLog.append("Invalid program binary version.");
- return false;
+ stream.writeInt(mLinkedAttribute[i].type);
+ stream.writeString(mLinkedAttribute[i].name);
+ stream.writeInt(mShaderAttributes[i].type);
+ stream.writeString(mShaderAttributes[i].name);
+ stream.writeInt(mSemanticIndex[i]);
}
- int compileFlags = 0;
- stream.read(&compileFlags);
- if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+ stream.writeInt(mSamplersPS.size());
+ for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
{
- infoLog.append("Mismatched compilation flags.");
- return false;
+ stream.writeInt(mSamplersPS[i].active);
+ stream.writeInt(mSamplersPS[i].logicalTextureUnit);
+ stream.writeInt(mSamplersPS[i].textureType);
}
-#endif
- for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
+ stream.writeInt(mSamplersVS.size());
+ for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
{
- stream.read(&mLinkedAttribute[i].type);
- std::string name;
- stream.read(&name);
- mLinkedAttribute[i].name = name;
- stream.read(&mSemanticIndex[i]);
+ stream.writeInt(mSamplersVS[i].active);
+ stream.writeInt(mSamplersVS[i].logicalTextureUnit);
+ stream.writeInt(mSamplersVS[i].textureType);
}
- initAttributesByLayout();
+ stream.writeInt(mUsedVertexSamplerRange);
+ stream.writeInt(mUsedPixelSamplerRange);
+ stream.writeInt(mUsesPointSize);
+ stream.writeInt(mShaderVersion);
- for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
+ stream.writeInt(mUniforms.size());
+ for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
{
- stream.read(&mSamplersPS[i].active);
- stream.read(&mSamplersPS[i].logicalTextureUnit);
-
- int textureType;
- stream.read(&textureType);
- mSamplersPS[i].textureType = (TextureType) textureType;
- }
+ const LinkedUniform &uniform = *mUniforms[uniformIndex];
- for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
- {
- stream.read(&mSamplersVS[i].active);
- stream.read(&mSamplersVS[i].logicalTextureUnit);
-
- int textureType;
- stream.read(&textureType);
- mSamplersVS[i].textureType = (TextureType) textureType;
- }
+ stream.writeInt(uniform.type);
+ stream.writeInt(uniform.precision);
+ stream.writeString(uniform.name);
+ stream.writeInt(uniform.arraySize);
+ stream.writeInt(uniform.blockIndex);
- stream.read(&mUsedVertexSamplerRange);
- stream.read(&mUsedPixelSamplerRange);
- stream.read(&mUsesPointSize);
+ stream.writeInt(uniform.blockInfo.offset);
+ stream.writeInt(uniform.blockInfo.arrayStride);
+ stream.writeInt(uniform.blockInfo.matrixStride);
+ stream.writeInt(uniform.blockInfo.isRowMajorMatrix);
- size_t size;
- stream.read(&size);
- if (stream.error())
- {
- infoLog.append("Invalid program binary.");
- return false;
+ stream.writeInt(uniform.psRegisterIndex);
+ stream.writeInt(uniform.vsRegisterIndex);
+ stream.writeInt(uniform.registerCount);
+ stream.writeInt(uniform.registerElement);
}
- mUniforms.resize(size);
- for (unsigned int i = 0; i < size; ++i)
+ stream.writeInt(mUniformBlocks.size());
+ for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex)
{
- GLenum type;
- GLenum precision;
- std::string name;
- unsigned int arraySize;
+ const UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
- stream.read(&type);
- stream.read(&precision);
- stream.read(&name);
- stream.read(&arraySize);
+ stream.writeString(uniformBlock.name);
+ stream.writeInt(uniformBlock.elementIndex);
+ stream.writeInt(uniformBlock.dataSize);
- mUniforms[i] = new Uniform(type, precision, name, arraySize);
-
- stream.read(&mUniforms[i]->psRegisterIndex);
- stream.read(&mUniforms[i]->vsRegisterIndex);
- stream.read(&mUniforms[i]->registerCount);
- }
+ stream.writeInt(uniformBlock.memberUniformIndexes.size());
+ for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
+ {
+ stream.writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]);
+ }
- stream.read(&size);
- if (stream.error())
- {
- infoLog.append("Invalid program binary.");
- return false;
+ stream.writeInt(uniformBlock.psRegisterIndex);
+ stream.writeInt(uniformBlock.vsRegisterIndex);
}
- mUniformIndex.resize(size);
- for (unsigned int i = 0; i < size; ++i)
+ stream.writeInt(mUniformIndex.size());
+ for (size_t i = 0; i < mUniformIndex.size(); ++i)
{
- stream.read(&mUniformIndex[i].name);
- stream.read(&mUniformIndex[i].element);
- stream.read(&mUniformIndex[i].index);
+ stream.writeString(mUniformIndex[i].name);
+ stream.writeInt(mUniformIndex[i].element);
+ stream.writeInt(mUniformIndex[i].index);
}
- unsigned int pixelShaderSize;
- stream.read(&pixelShaderSize);
-
- unsigned int vertexShaderSize;
- stream.read(&vertexShaderSize);
-
- unsigned int geometryShaderSize;
- stream.read(&geometryShaderSize);
-
- const char *ptr = (const char*) binary + stream.offset();
-
-#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY)
- const GUID *binaryIdentifier = (const GUID *) ptr;
- ptr += sizeof(GUID);
-
- GUID identifier = mRenderer->getAdapterIdentifier();
- if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0)
+ stream.writeInt(mTransformFeedbackBufferMode);
+ stream.writeInt(mTransformFeedbackLinkedVaryings.size());
+ for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
{
- infoLog.append("Invalid program binary.");
- return false;
+ const LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
+
+ stream.writeString(varying.name);
+ stream.writeInt(varying.type);
+ stream.writeInt(varying.size);
+ stream.writeString(varying.semanticName);
+ stream.writeInt(varying.semanticIndex);
+ stream.writeInt(varying.semanticIndexCount);
}
-#endif
- const char *pixelShaderFunction = ptr;
- ptr += pixelShaderSize;
+ stream.writeInt(mVertexExecutables.size());
+ for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
+ {
+ VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
- const char *vertexShaderFunction = ptr;
- ptr += vertexShaderSize;
+ for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
+ {
+ const VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex];
+ stream.writeInt(vertexInput.mType);
+ stream.writeInt(vertexInput.mNormalized);
+ stream.writeInt(vertexInput.mComponents);
+ stream.writeInt(vertexInput.mPureInteger);
+ }
- const char *geometryShaderFunction = geometryShaderSize > 0 ? ptr : NULL;
- ptr += geometryShaderSize;
+ size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
+ stream.writeInt(vertexShaderSize);
- mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(pixelShaderFunction),
- pixelShaderSize, rx::SHADER_PIXEL);
- if (!mPixelExecutable)
- {
- infoLog.append("Could not create pixel shader.");
- return false;
+ const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
+ stream.writeBytes(vertexBlob, vertexShaderSize);
}
- mVertexExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction),
- vertexShaderSize, rx::SHADER_VERTEX);
- if (!mVertexExecutable)
+ stream.writeInt(mPixelExecutables.size());
+ for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
{
- infoLog.append("Could not create vertex shader.");
- delete mPixelExecutable;
- mPixelExecutable = NULL;
- return false;
- }
+ PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
- if (geometryShaderFunction != NULL && geometryShaderSize > 0)
- {
- mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction),
- geometryShaderSize, rx::SHADER_GEOMETRY);
- if (!mGeometryExecutable)
+ const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
+ stream.writeInt(outputs.size());
+ for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
{
- infoLog.append("Could not create geometry shader.");
- delete mPixelExecutable;
- mPixelExecutable = NULL;
- delete mVertexExecutable;
- mVertexExecutable = NULL;
- return false;
+ stream.writeInt(outputs[outputIndex]);
}
- }
- else
- {
- mGeometryExecutable = NULL;
- }
-
- return true;
-}
-bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
-{
- BinaryOutputStream stream;
+ size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
+ stream.writeInt(pixelShaderSize);
- stream.write(GL_PROGRAM_BINARY_ANGLE);
- stream.write(ANGLE_MAJOR_VERSION);
- stream.write(ANGLE_MINOR_VERSION);
-#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY)
- stream.write(ANGLE_COMMIT_HASH, ANGLE_COMMIT_HASH_SIZE);
- stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
-#endif
- for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
- {
- stream.write(mLinkedAttribute[i].type);
- stream.write(mLinkedAttribute[i].name);
- stream.write(mSemanticIndex[i]);
+ const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
+ stream.writeBytes(pixelBlob, pixelShaderSize);
}
- for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
- {
- stream.write(mSamplersPS[i].active);
- stream.write(mSamplersPS[i].logicalTextureUnit);
- stream.write((int) mSamplersPS[i].textureType);
- }
+ size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
+ stream.writeInt(geometryShaderSize);
- for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
+ if (mGeometryExecutable != NULL && geometryShaderSize > 0)
{
- stream.write(mSamplersVS[i].active);
- stream.write(mSamplersVS[i].logicalTextureUnit);
- stream.write((int) mSamplersVS[i].textureType);
+ const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
+ stream.writeBytes(geometryBlob, geometryShaderSize);
}
- stream.write(mUsedVertexSamplerRange);
- stream.write(mUsedPixelSamplerRange);
- stream.write(mUsesPointSize);
-
- stream.write(mUniforms.size());
- for (unsigned int i = 0; i < mUniforms.size(); ++i)
+ if (!mProgram->save(&stream))
{
- stream.write(mUniforms[i]->type);
- stream.write(mUniforms[i]->precision);
- stream.write(mUniforms[i]->name);
- stream.write(mUniforms[i]->arraySize);
-
- stream.write(mUniforms[i]->psRegisterIndex);
- stream.write(mUniforms[i]->vsRegisterIndex);
- stream.write(mUniforms[i]->registerCount);
- }
+ if (length)
+ {
+ *length = 0;
+ }
- stream.write(mUniformIndex.size());
- for (unsigned int i = 0; i < mUniformIndex.size(); ++i)
- {
- stream.write(mUniformIndex[i].name);
- stream.write(mUniformIndex[i].element);
- stream.write(mUniformIndex[i].index);
+ return false;
}
- UINT pixelShaderSize = mPixelExecutable->getLength();
- stream.write(pixelShaderSize);
-
- UINT vertexShaderSize = mVertexExecutable->getLength();
- stream.write(vertexShaderSize);
-
- UINT geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
- stream.write(geometryShaderSize);
-
-#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY)
- GUID identifier = mRenderer->getAdapterIdentifier();
-#endif
+ GUID identifier = mProgram->getRenderer()->getAdapterIdentifier();
GLsizei streamLength = stream.length();
const void *streamData = stream.data();
- GLsizei totalLength = streamLength + sizeof(GUID) + pixelShaderSize + vertexShaderSize + geometryShaderSize;
+ GLsizei totalLength = streamLength + sizeof(GUID);
if (totalLength > bufSize)
{
if (length)
@@ -1896,22 +1546,8 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
memcpy(ptr, streamData, streamLength);
ptr += streamLength;
-#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY)
memcpy(ptr, &identifier, sizeof(GUID));
ptr += sizeof(GUID);
-#endif
-
- memcpy(ptr, mPixelExecutable->getFunction(), pixelShaderSize);
- ptr += pixelShaderSize;
-
- memcpy(ptr, mVertexExecutable->getFunction(), vertexShaderSize);
- ptr += vertexShaderSize;
-
- if (mGeometryExecutable != NULL && geometryShaderSize > 0)
- {
- memcpy(ptr, mGeometryExecutable->getFunction(), geometryShaderSize);
- ptr += geometryShaderSize;
- }
ASSERT(ptr - totalLength == binary);
}
@@ -1927,7 +1563,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
GLint ProgramBinary::getLength()
{
GLint length;
- if (save(NULL, INT_MAX, &length))
+ if (save(NULL, NULL, INT_MAX, &length))
{
return length;
}
@@ -1937,77 +1573,98 @@ GLint ProgramBinary::getLength()
}
}
-bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
+bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
+ const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps)
{
if (!fragmentShader || !fragmentShader->isCompiled())
{
return false;
}
+ ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
if (!vertexShader || !vertexShader->isCompiled())
{
return false;
}
+ ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
- std::string pixelHLSL = fragmentShader->getHLSL();
- std::string vertexHLSL = vertexShader->getHLSL();
+ reset();
- // Map the varyings to the register file
- const Varying *packing[IMPLEMENTATION_MAX_VARYING_VECTORS][4] = {NULL};
- int registers = packVaryings(infoLog, packing, fragmentShader);
+ mSamplersPS.resize(caps.maxTextureImageUnits);
+ mSamplersVS.resize(caps.maxVertexTextureImageUnits);
- if (registers < 0)
- {
- return false;
- }
+ mTransformFeedbackBufferMode = transformFeedbackBufferMode;
+
+ rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
+ rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
- if (!linkVaryings(infoLog, registers, packing, pixelHLSL, vertexHLSL, fragmentShader, vertexShader))
+ mShaderVersion = vertexShaderD3D->getShaderVersion();
+
+ int registers;
+ std::vector<LinkedVarying> linkedVaryings;
+ if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, &registers, &linkedVaryings, &mOutputVariables))
{
return false;
}
+ mUsesPointSize = vertexShaderD3D->usesPointSize();
+
bool success = true;
- if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader))
+ if (!linkAttributes(infoLog, attributeBindings, vertexShader))
{
success = false;
}
- if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms()))
+ if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps))
{
success = false;
}
// special case for gl_DepthRange, the only built-in uniform (also a struct)
- if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange)
+ if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange())
+ {
+ const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo();
+
+ mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo));
+ mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo));
+ mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo));
+ }
+
+ if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps))
{
- mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0));
- mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0));
- mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0));
+ success = false;
+ }
+
+ if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
+ transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings, caps))
+ {
+ success = false;
}
if (success)
{
- mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX, DiscardWorkaround(vertexShader->mUsesDiscardRewriting));
- mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, DiscardWorkaround(fragmentShader->mUsesDiscardRewriting));
+ VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS];
+ GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout);
+ rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout);
+
+ std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(mProgram->getPixelShaderKey());
+ rx::ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput);
if (usesGeometryShader())
{
- std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
- mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, rx::ANGLE_D3D_WORKAROUND_NONE);
+ std::string geometryHLSL = mProgram->getDynamicHLSL()->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
+ mGeometryExecutable = mProgram->getRenderer()->compileToExecutable(infoLog, geometryHLSL.c_str(),
+ rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
+ (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
+ rx::ANGLE_D3D_WORKAROUND_NONE);
}
- if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
+ if (!defaultVertexExecutable || !defaultPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
{
infoLog.append("Failed to create D3D shaders.");
success = false;
-
- delete mVertexExecutable;
- mVertexExecutable = NULL;
- delete mPixelExecutable;
- mPixelExecutable = NULL;
- delete mGeometryExecutable;
- mGeometryExecutable = NULL;
+ reset();
}
}
@@ -2015,65 +1672,86 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
}
// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
-bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
+bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader)
{
+ const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
+
unsigned int usedLocations = 0;
+ const std::vector<sh::Attribute> &shaderAttributes = vertexShader->getActiveAttributes();
// Link attributes that have a binding location
- for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
+ for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
{
- int location = attributeBindings.getAttributeBinding(attribute->name);
+ const sh::Attribute &attribute = shaderAttributes[attributeIndex];
- if (location != -1) // Set by glBindAttribLocation
- {
- if (!mLinkedAttribute[location].name.empty())
- {
- // Multiple active attributes bound to the same location; not an error
- }
+ ASSERT(attribute.staticUse);
+
+ const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
- mLinkedAttribute[location] = *attribute;
+ mShaderAttributes[attributeIndex] = attribute;
- int rows = VariableRowCount(attribute->type);
+ if (location != -1) // Set by glBindAttribLocation or by location layout qualifier
+ {
+ const int rows = VariableRegisterCount(attribute.type);
if (rows + location > MAX_VERTEX_ATTRIBS)
{
- infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location);
+ infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location);
return false;
}
- for (int i = 0; i < rows; i++)
+ for (int row = 0; row < rows; row++)
{
- usedLocations |= 1 << (location + i);
+ const int rowLocation = location + row;
+ sh::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation];
+
+ // In GLSL 3.00, attribute aliasing produces a link error
+ // In GLSL 1.00, attribute aliasing is allowed
+ if (mShaderVersion >= 300)
+ {
+ if (!linkedAttribute.name.empty())
+ {
+ infoLog.append("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), linkedAttribute.name.c_str(), rowLocation);
+ return false;
+ }
+ }
+
+ linkedAttribute = attribute;
+ usedLocations |= 1 << rowLocation;
}
}
}
// Link attributes that don't have a binding location
- for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
+ for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
{
- int location = attributeBindings.getAttributeBinding(attribute->name);
+ const sh::Attribute &attribute = shaderAttributes[attributeIndex];
- if (location == -1) // Not set by glBindAttribLocation
+ ASSERT(attribute.staticUse);
+
+ const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
+
+ if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier
{
- int rows = VariableRowCount(attribute->type);
+ int rows = VariableRegisterCount(attribute.type);
int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
{
- infoLog.append("Too many active attributes (%s)", attribute->name.c_str());
+ infoLog.append("Too many active attributes (%s)", attribute.name.c_str());
return false; // Fail to link
}
- mLinkedAttribute[availableIndex] = *attribute;
+ mLinkedAttribute[availableIndex] = attribute;
}
}
for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
{
- int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
- int rows = std::max(VariableRowCount(mLinkedAttribute[attributeIndex].type), 1);
+ int index = vertexShaderD3D->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
+ int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type);
for (int r = 0; r < rows; r++)
{
@@ -2086,19 +1764,48 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at
return true;
}
-bool ProgramBinary::linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms)
+bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable,
+ const sh::ShaderVariable &fragmentVariable, bool validatePrecision)
{
- for (sh::ActiveUniforms::const_iterator uniform = vertexUniforms.begin(); uniform != vertexUniforms.end(); uniform++)
+ if (vertexVariable.type != fragmentVariable.type)
+ {
+ infoLog.append("Types for %s differ between vertex and fragment shaders", variableName.c_str());
+ return false;
+ }
+ if (vertexVariable.arraySize != fragmentVariable.arraySize)
{
- if (!defineUniform(GL_VERTEX_SHADER, *uniform, infoLog))
+ infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str());
+ return false;
+ }
+ if (validatePrecision && vertexVariable.precision != fragmentVariable.precision)
+ {
+ infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str());
+ return false;
+ }
+
+ if (vertexVariable.fields.size() != fragmentVariable.fields.size())
+ {
+ infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", variableName.c_str());
+ return false;
+ }
+ const unsigned int numMembers = 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.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')",
+ memberIndex, variableName.c_str(),
+ vertexMember.name.c_str(), fragmentMember.name.c_str());
return false;
}
- }
- for (sh::ActiveUniforms::const_iterator uniform = fragmentUniforms.begin(); uniform != fragmentUniforms.end(); uniform++)
- {
- if (!defineUniform(GL_FRAGMENT_SHADER, *uniform, infoLog))
+ const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." +
+ vertexMember.name + "'";
+
+ if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision))
{
return false;
}
@@ -2107,274 +1814,582 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &ver
return true;
}
-bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog)
+bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform)
{
- if (constant.type == GL_SAMPLER_2D ||
- constant.type == GL_SAMPLER_CUBE)
+ if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
{
- unsigned int samplerIndex = constant.registerIndex;
-
- do
- {
- if (shader == GL_VERTEX_SHADER)
- {
- if (samplerIndex < mRenderer->getMaxVertexTextureImageUnits())
- {
- mSamplersVS[samplerIndex].active = true;
- mSamplersVS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D;
- mSamplersVS[samplerIndex].logicalTextureUnit = 0;
- mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange);
- }
- else
- {
- infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", mRenderer->getMaxVertexTextureImageUnits());
- return false;
- }
- }
- else if (shader == GL_FRAGMENT_SHADER)
- {
- if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
- {
- mSamplersPS[samplerIndex].active = true;
- mSamplersPS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D;
- mSamplersPS[samplerIndex].logicalTextureUnit = 0;
- mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange);
- }
- else
- {
- infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
- return false;
- }
- }
- else UNREACHABLE();
+ return false;
+ }
- samplerIndex++;
- }
- while (samplerIndex < constant.registerIndex + constant.arraySize);
+ return true;
+}
+
+bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying)
+{
+ if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
+ {
+ return false;
+ }
+
+ if (vertexVarying.interpolation != fragmentVarying.interpolation)
+ {
+ infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
+{
+ if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
+ {
+ return false;
+ }
+
+ if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout)
+ {
+ infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str());
+ return false;
}
- Uniform *uniform = NULL;
- GLint location = getUniformLocation(constant.name);
+ return true;
+}
+
+bool ProgramBinary::linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps)
+{
+ const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader.getImplementation());
+ const rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader.getImplementation());
+
+ const std::vector<sh::Uniform> &vertexUniforms = vertexShader.getUniforms();
+ const std::vector<sh::Uniform> &fragmentUniforms = fragmentShader.getUniforms();
+
+ // Check that uniforms defined in the vertex and fragment shaders are identical
+ typedef std::map<std::string, const sh::Uniform*> UniformMap;
+ UniformMap linkedUniforms;
- if (location >= 0) // Previously defined, type and precision must match
+ for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++)
{
- uniform = mUniforms[mUniformIndex[location].index];
+ const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex];
+ linkedUniforms[vertexUniform.name] = &vertexUniform;
+ }
- if (uniform->type != constant.type)
+ for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++)
+ {
+ const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex];
+ UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name);
+ if (entry != linkedUniforms.end())
{
- infoLog.append("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
- return false;
+ const sh::Uniform &vertexUniform = *entry->second;
+ const std::string &uniformName = "uniform '" + vertexUniform.name + "'";
+ if (!linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform))
+ {
+ return false;
+ }
}
+ }
- if (uniform->precision != constant.precision)
+ for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++)
+ {
+ const sh::Uniform &uniform = vertexUniforms[uniformIndex];
+
+ if (uniform.staticUse)
{
- infoLog.append("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
- return false;
+ defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name));
}
}
- else
+
+ for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++)
{
- uniform = new Uniform(constant.type, constant.precision, constant.name, constant.arraySize);
+ const sh::Uniform &uniform = fragmentUniforms[uniformIndex];
+
+ if (uniform.staticUse)
+ {
+ defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name));
+ }
}
- if (!uniform)
+ if (!indexUniforms(infoLog, caps))
{
return false;
}
- if (shader == GL_FRAGMENT_SHADER)
+ mProgram->initializeUniformStorage(mUniforms);
+
+ return true;
+}
+
+void ProgramBinary::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister)
+{
+ ShShaderOutput outputType = rx::ShaderD3D::getCompilerOutputType(shader);
+ sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
+ encoder.skipRegisters(uniformRegister);
+
+ defineUniform(shader, uniform, uniform.name, &encoder);
+}
+
+void ProgramBinary::defineUniform(GLenum shader, const sh::ShaderVariable &uniform,
+ const std::string &fullName, sh::HLSLBlockEncoder *encoder)
+{
+ if (uniform.isStruct())
{
- uniform->psRegisterIndex = constant.registerIndex;
+ for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
+ {
+ const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
+
+ 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);
+
+ defineUniform(shader, field, fieldFullName, encoder);
+ }
+
+ encoder->exitAggregateType();
+ }
}
- else if (shader == GL_VERTEX_SHADER)
+ else // Not a struct
{
- uniform->vsRegisterIndex = constant.registerIndex;
- }
- else UNREACHABLE();
+ // Arrays are treated as aggregate types
+ if (uniform.isArray())
+ {
+ encoder->enterAggregateType();
+ }
- if (location >= 0)
- {
- return uniform->type == constant.type;
- }
+ LinkedUniform *linkedUniform = getUniformByName(fullName);
- mUniforms.push_back(uniform);
- unsigned int uniformIndex = mUniforms.size() - 1;
+ if (!linkedUniform)
+ {
+ linkedUniform = new LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
+ -1, sh::BlockMemberInfo::getDefaultBlockInfo());
+ ASSERT(linkedUniform);
+ linkedUniform->registerElement = encoder->getCurrentElement();
+ mUniforms.push_back(linkedUniform);
+ }
- for (unsigned int i = 0; i < uniform->elementCount(); i++)
- {
- mUniformIndex.push_back(UniformLocation(constant.name, i, uniformIndex));
+ ASSERT(linkedUniform->registerElement == encoder->getCurrentElement());
+
+ if (shader == GL_FRAGMENT_SHADER)
+ {
+ linkedUniform->psRegisterIndex = encoder->getCurrentRegister();
+ }
+ else if (shader == GL_VERTEX_SHADER)
+ {
+ linkedUniform->vsRegisterIndex = encoder->getCurrentRegister();
+ }
+ else UNREACHABLE();
+
+ // Advance the uniform offset, to track registers allocation for structs
+ encoder->encodeType(uniform.type, uniform.arraySize, false);
+
+ // Arrays are treated as aggregate types
+ if (uniform.isArray())
+ {
+ encoder->exitAggregateType();
+ }
}
+}
- if (shader == GL_VERTEX_SHADER)
+bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps)
+{
+ ASSERT(IsSampler(uniform.type));
+ ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX);
+
+ if (uniform.vsRegisterIndex != GL_INVALID_INDEX)
{
- if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors())
+ if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS,
+ &mUsedVertexSamplerRange))
{
- infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors());
+ infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).",
+ mSamplersVS.size());
+ return false;
+ }
+
+ unsigned int maxVertexVectors = mProgram->getRenderer()->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors;
+ if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors)
+ {
+ infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)",
+ caps.maxVertexUniformVectors);
return false;
}
}
- else if (shader == GL_FRAGMENT_SHADER)
+
+ if (uniform.psRegisterIndex != GL_INVALID_INDEX)
{
- if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedFragmentUniformVectors() + mRenderer->getMaxFragmentUniformVectors())
+ if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS,
+ &mUsedPixelSamplerRange))
+ {
+ infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).",
+ mSamplersPS.size());
+ return false;
+ }
+
+ unsigned int maxFragmentVectors = mProgram->getRenderer()->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors;
+ if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors)
{
- infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", mRenderer->getMaxFragmentUniformVectors());
+ infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)",
+ caps.maxFragmentUniformVectors);
return false;
}
}
- else UNREACHABLE();
return true;
}
-std::string ProgramBinary::generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
+bool ProgramBinary::indexUniforms(InfoLog &infoLog, const Caps &caps)
{
- // for now we only handle point sprite emulation
- ASSERT(usesPointSpriteEmulation());
- return generatePointSpriteHLSL(registers, packing, fragmentShader, vertexShader);
+ for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+ {
+ const LinkedUniform &uniform = *mUniforms[uniformIndex];
+
+ if (IsSampler(uniform.type))
+ {
+ if (!indexSamplerUniform(uniform, infoLog, caps))
+ {
+ return false;
+ }
+ }
+
+ for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++)
+ {
+ mUniformIndex.push_back(VariableLocation(uniform.name, arrayElementIndex, uniformIndex));
+ }
+ }
+
+ return true;
}
-std::string ProgramBinary::generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
+bool ProgramBinary::assignSamplers(unsigned int startSamplerIndex,
+ GLenum samplerType,
+ unsigned int samplerCount,
+ std::vector<Sampler> &outSamplers,
+ GLuint *outUsedRange)
{
- ASSERT(registers >= 0);
- ASSERT(vertexShader->mUsesPointSize);
- ASSERT(mRenderer->getMajorShaderModel() >= 4);
+ unsigned int samplerIndex = startSamplerIndex;
- std::string geomHLSL;
+ do
+ {
+ if (samplerIndex < outSamplers.size())
+ {
+ Sampler& sampler = outSamplers[samplerIndex];
+ sampler.active = true;
+ sampler.textureType = GetTextureType(samplerType);
+ sampler.logicalTextureUnit = 0;
+ *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
+ }
+ else
+ {
+ return false;
+ }
- std::string varyingSemantic = "TEXCOORD";
+ samplerIndex++;
+ } while (samplerIndex < startSamplerIndex + samplerCount);
- std::string fragCoordSemantic;
- std::string pointCoordSemantic;
+ return true;
+}
- int reservedRegisterIndex = registers;
+bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock)
+{
+ const char* blockName = vertexInterfaceBlock.name.c_str();
- if (fragmentShader->mUsesFragCoord)
+ // validate blocks for the same member types
+ if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size())
{
- fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
+ infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName);
+ return false;
}
- if (fragmentShader->mUsesPointCoord)
+ if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize)
{
- pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
+ infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName);
+ return false;
}
- geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n"
- "\n"
- "struct GS_INPUT\n"
- "{\n";
+ if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
+ {
+ infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName);
+ return false;
+ }
- for (int r = 0; r < registers; r++)
+ const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size();
+ for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
{
- int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
+ const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex];
+ const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex];
+
+ if (vertexMember.name != fragmentMember.name)
+ {
+ infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')",
+ blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str());
+ return false;
+ }
- geomHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
+ std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
+ if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember))
+ {
+ return false;
+ }
}
- if (fragmentShader->mUsesFragCoord)
+ return true;
+}
+
+bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps)
+{
+ const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks();
+ const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks();
+
+ // 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 (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
{
- geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
+ const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex];
+ linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
}
- geomHLSL += " float gl_PointSize : PSIZE;\n"
- " float4 gl_Position : SV_Position;\n"
- "};\n"
- "\n"
- "struct GS_OUTPUT\n"
- "{\n";
+ for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
+ {
+ const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex];
+ UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name);
+ if (entry != linkedUniformBlocks.end())
+ {
+ const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
+ if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock))
+ {
+ return false;
+ }
+ }
+ }
- for (int r = 0; r < registers; r++)
+ for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
{
- int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
+ const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex];
- geomHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
+ // Note: shared and std140 layouts are always considered active
+ if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
+ {
+ if (!defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps))
+ {
+ return false;
+ }
+ }
}
- if (fragmentShader->mUsesFragCoord)
+ for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
{
- geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
+ const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex];
+
+ // Note: shared and std140 layouts are always considered active
+ if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
+ {
+ if (!defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps))
+ {
+ return false;
+ }
+ }
}
- if (fragmentShader->mUsesPointCoord)
+ return true;
+}
+
+bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
+ const std::vector<std::string> &transformFeedbackVaryingNames,
+ GLenum transformFeedbackBufferMode,
+ std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings,
+ const Caps &caps) const
+{
+ size_t totalComponents = 0;
+
+ // Gather the linked varyings that are used for transform feedback, they should all exist.
+ outTransformFeedbackLinkedVaryings->clear();
+ for (size_t i = 0; i < transformFeedbackVaryingNames.size(); i++)
{
- geomHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
- }
+ bool found = false;
+ for (size_t j = 0; j < linkedVaryings.size(); j++)
+ {
+ if (transformFeedbackVaryingNames[i] == linkedVaryings[j].name)
+ {
+ for (size_t k = 0; k < outTransformFeedbackLinkedVaryings->size(); k++)
+ {
+ if (outTransformFeedbackLinkedVaryings->at(k).name == linkedVaryings[j].name)
+ {
+ infoLog.append("Two transform feedback varyings specify the same output variable (%s).", linkedVaryings[j].name.c_str());
+ return false;
+ }
+ }
+
+ size_t componentCount = linkedVaryings[j].semanticIndexCount * 4;
+ if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
+ componentCount > caps.maxTransformFeedbackSeparateComponents)
+ {
+ infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).",
+ linkedVaryings[j].name.c_str(), componentCount, caps.maxTransformFeedbackSeparateComponents);
+ return false;
+ }
- geomHLSL += " float gl_PointSize : PSIZE;\n"
- " float4 gl_Position : SV_Position;\n"
- "};\n"
- "\n"
- "static float2 pointSpriteCorners[] = \n"
- "{\n"
- " float2( 0.5f, -0.5f),\n"
- " float2( 0.5f, 0.5f),\n"
- " float2(-0.5f, -0.5f),\n"
- " float2(-0.5f, 0.5f)\n"
- "};\n"
- "\n"
- "static float2 pointSpriteTexcoords[] = \n"
- "{\n"
- " float2(1.0f, 1.0f),\n"
- " float2(1.0f, 0.0f),\n"
- " float2(0.0f, 1.0f),\n"
- " float2(0.0f, 0.0f)\n"
- "};\n"
- "\n"
- "static float minPointSize = " + str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n"
- "static float maxPointSize = " + str(mRenderer->getMaxPointSize()) + ".0f;\n"
- "\n"
- "[maxvertexcount(4)]\n"
- "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n"
- "{\n"
- " GS_OUTPUT output = (GS_OUTPUT)0;\n"
- " output.gl_PointSize = input[0].gl_PointSize;\n";
+ totalComponents += componentCount;
+
+ outTransformFeedbackLinkedVaryings->push_back(linkedVaryings[j]);
+ found = true;
+ break;
+ }
+ }
- for (int r = 0; r < registers; r++)
+ // All transform feedback varyings are expected to exist since packVaryings checks for them.
+ ASSERT(found);
+ }
+
+ if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > caps.maxTransformFeedbackInterleavedComponents)
{
- geomHLSL += " output.v" + str(r) + " = input[0].v" + str(r) + ";\n";
+ infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).",
+ totalComponents, caps.maxTransformFeedbackInterleavedComponents);
+ return false;
}
- if (fragmentShader->mUsesFragCoord)
+ return true;
+}
+
+template <typename VarT>
+void ProgramBinary::defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
+ sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
+ bool inRowMajorLayout)
+{
+ for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++)
{
- geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n";
+ const VarT &field = fields[uniformIndex];
+ 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) : "");
+ defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout);
+
+ encoder->exitAggregateType();
+ }
+ }
+ else
+ {
+ bool isRowMajorMatrix = (IsMatrixType(field.type) && inRowMajorLayout);
+
+ sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
+
+ LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize,
+ blockIndex, memberInfo);
+
+ // add to uniform list, but not index, since uniform block uniforms have no location
+ blockUniformIndexes->push_back(mUniforms.size());
+ mUniforms.push_back(newUniform);
+ }
}
+}
- geomHLSL += " \n"
- " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n"
- " float4 gl_Position = input[0].gl_Position;\n"
- " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * gl_Position.w;\n";
+bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps)
+{
+ const rx::ShaderD3D* shaderD3D = rx::ShaderD3D::makeShaderD3D(shader.getImplementation());
- for (int corner = 0; corner < 4; corner++)
+ // create uniform block entries if they do not exist
+ if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX)
{
- geomHLSL += " \n"
- " output.gl_Position = gl_Position + float4(pointSpriteCorners[" + str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
+ std::vector<unsigned int> blockUniformIndexes;
+ const unsigned int blockIndex = mUniformBlocks.size();
+
+ // define member uniforms
+ sh::BlockLayoutEncoder *encoder = NULL;
- if (fragmentShader->mUsesPointCoord)
+ if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
{
- geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + str(corner) + "];\n";
+ encoder = new sh::Std140BlockEncoder;
}
+ else
+ {
+ encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
+ }
+ ASSERT(encoder);
+
+ defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout);
+
+ size_t dataSize = encoder->getBlockSize();
- geomHLSL += " outStream.Append(output);\n";
+ // create all the uniform blocks
+ if (interfaceBlock.arraySize > 0)
+ {
+ for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++)
+ {
+ UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize);
+ newUniformBlock->memberUniformIndexes = blockUniformIndexes;
+ mUniformBlocks.push_back(newUniformBlock);
+ }
+ }
+ else
+ {
+ UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize);
+ newUniformBlock->memberUniformIndexes = blockUniformIndexes;
+ mUniformBlocks.push_back(newUniformBlock);
+ }
}
- geomHLSL += " \n"
- " outStream.RestartStrip();\n"
- "}\n";
+ if (interfaceBlock.staticUse)
+ {
+ // Assign registers to the uniform blocks
+ const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name);
+ const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize);
+ ASSERT(blockIndex != GL_INVALID_INDEX);
+ ASSERT(blockIndex + elementCount <= mUniformBlocks.size());
+
+ unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name);
- return geomHLSL;
+ for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++)
+ {
+ UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement];
+ ASSERT(uniformBlock->name == interfaceBlock.name);
+
+ if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(),
+ interfaceBlockRegister + uniformBlockElement, caps))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
-// This method needs to match OutputHLSL::decorate
-std::string ProgramBinary::decorateAttribute(const std::string &name)
+bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps)
{
- if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
+ if (shader == GL_VERTEX_SHADER)
{
- return "_" + name;
+ uniformBlock->vsRegisterIndex = registerIndex;
+ if (registerIndex - mProgram->getRenderer()->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks)
+ {
+ infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks);
+ return false;
+ }
+ }
+ else if (shader == GL_FRAGMENT_SHADER)
+ {
+ uniformBlock->psRegisterIndex = registerIndex;
+ if (registerIndex - mProgram->getRenderer()->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks)
+ {
+ infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks);
+ return false;
+ }
}
-
- return name;
+ else UNREACHABLE();
+
+ return true;
}
-bool ProgramBinary::isValidated() const
+bool ProgramBinary::isValidated() const
{
return mValidated;
}
@@ -2500,10 +2515,145 @@ GLint ProgramBinary::getActiveUniformMaxLength() const
return maxLength;
}
-void ProgramBinary::validate(InfoLog &infoLog)
+GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const
+{
+ const gl::LinkedUniform& uniform = *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 ProgramBinary::isValidUniformLocation(GLint location) const
+{
+ ASSERT(rx::IsIntegerCastSafe<GLint>(mUniformIndex.size()));
+ return (location >= 0 && location < static_cast<GLint>(mUniformIndex.size()));
+}
+
+LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const
+{
+ ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformIndex.size());
+ return mUniforms[mUniformIndex[location].index];
+}
+
+LinkedUniform *ProgramBinary::getUniformByName(const std::string &name) const
+{
+ for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+ {
+ if (mUniforms[uniformIndex]->name == name)
+ {
+ return mUniforms[uniformIndex];
+ }
+ }
+
+ return NULL;
+}
+
+void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
+{
+ ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
+
+ const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
+
+ if (bufSize > 0)
+ {
+ std::string string = uniformBlock.name;
+
+ if (uniformBlock.isArrayElement())
+ {
+ string += ArrayString(uniformBlock.elementIndex);
+ }
+
+ strncpy(uniformBlockName, string.c_str(), bufSize);
+ uniformBlockName[bufSize - 1] = '\0';
+
+ if (length)
+ {
+ *length = strlen(uniformBlockName);
+ }
+ }
+}
+
+void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
+{
+ ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
+
+ const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
+
+ switch (pname)
+ {
+ case GL_UNIFORM_BLOCK_DATA_SIZE:
+ *params = static_cast<GLint>(uniformBlock.dataSize);
+ break;
+ case GL_UNIFORM_BLOCK_NAME_LENGTH:
+ *params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0));
+ break;
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ *params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size());
+ break;
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ {
+ for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
+ {
+ params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]);
+ }
+ }
+ break;
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ *params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader());
+ break;
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ *params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader());
+ break;
+ default: UNREACHABLE();
+ }
+}
+
+GLuint ProgramBinary::getActiveUniformBlockCount() const
+{
+ return mUniformBlocks.size();
+}
+
+GLuint ProgramBinary::getActiveUniformBlockMaxLength() const
+{
+ unsigned int maxLength = 0;
+
+ unsigned int numUniformBlocks = mUniformBlocks.size();
+ for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
+ {
+ const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
+ if (!uniformBlock.name.empty())
+ {
+ const unsigned int length = uniformBlock.name.length() + 1;
+
+ // Counting in "[0]".
+ const unsigned int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
+
+ maxLength = std::max(length + arrayLength, maxLength);
+ }
+ }
+
+ return maxLength;
+}
+
+void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps)
{
applyUniforms();
- if (!validateSamplers(&infoLog))
+ if (!validateSamplers(&infoLog, caps))
{
mValidated = false;
}
@@ -2513,39 +2663,34 @@ void ProgramBinary::validate(InfoLog &infoLog)
}
}
-bool ProgramBinary::validateSamplers(InfoLog *infoLog)
+bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps)
{
// 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.
+ updateSamplerMapping();
- const unsigned int maxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
- TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
-
- for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i)
- {
- textureUnitType[i] = TEXTURE_UNKNOWN;
- }
+ std::vector<GLenum> textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE);
for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
{
if (mSamplersPS[i].active)
{
unsigned int unit = mSamplersPS[i].logicalTextureUnit;
-
- if (unit >= maxCombinedTextureImageUnits)
+
+ if (unit >= textureUnitTypes.size())
{
if (infoLog)
{
- infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
+ infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size());
}
return false;
}
- if (textureUnitType[unit] != TEXTURE_UNKNOWN)
+ if (textureUnitTypes[unit] != GL_NONE)
{
- if (mSamplersPS[i].textureType != textureUnitType[unit])
+ if (mSamplersPS[i].textureType != textureUnitTypes[unit])
{
if (infoLog)
{
@@ -2557,7 +2702,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog)
}
else
{
- textureUnitType[unit] = mSamplersPS[i].textureType;
+ textureUnitTypes[unit] = mSamplersPS[i].textureType;
}
}
}
@@ -2567,20 +2712,20 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog)
if (mSamplersVS[i].active)
{
unsigned int unit = mSamplersVS[i].logicalTextureUnit;
-
- if (unit >= maxCombinedTextureImageUnits)
+
+ if (unit >= textureUnitTypes.size())
{
if (infoLog)
{
- infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
+ infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size());
}
return false;
}
- if (textureUnitType[unit] != TEXTURE_UNKNOWN)
+ if (textureUnitTypes[unit] != GL_NONE)
{
- if (mSamplersVS[i].textureType != textureUnitType[unit])
+ if (mSamplersVS[i].textureType != textureUnitTypes[unit])
{
if (infoLog)
{
@@ -2592,7 +2737,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog)
}
else
{
- textureUnitType[unit] = mSamplersVS[i].textureType;
+ textureUnitTypes[unit] = mSamplersVS[i].textureType;
}
}
}
@@ -2600,7 +2745,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog)
return true;
}
-ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D)
+ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
{
}
@@ -2648,4 +2793,33 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA
}
}
+void ProgramBinary::reset()
+{
+ SafeDeleteContainer(mVertexExecutables);
+ SafeDeleteContainer(mPixelExecutables);
+
+ SafeDelete(mGeometryExecutable);
+
+ mTransformFeedbackBufferMode = GL_NONE;
+ mTransformFeedbackLinkedVaryings.clear();
+
+ mSamplersPS.clear();
+ mSamplersVS.clear();
+
+ mUsedVertexSamplerRange = 0;
+ mUsedPixelSamplerRange = 0;
+ mUsesPointSize = false;
+ mShaderVersion = 0;
+ mDirtySamplerMapping = true;
+
+ SafeDeleteContainer(mUniforms);
+ SafeDeleteContainer(mUniformBlocks);
+ mUniformIndex.clear();
+ mOutputVariables.clear();
+
+ mProgram->reset();
+
+ mValidated = false;
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h
index d6320863f2..ad470d417b 100644
--- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h
+++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -10,94 +10,152 @@
#ifndef LIBGLESV2_PROGRAM_BINARY_H_
#define LIBGLESV2_PROGRAM_BINARY_H_
-#define GL_APICALL
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <string>
-#include <vector>
-
#include "common/RefCountObject.h"
#include "angletypes.h"
-#include "libGLESv2/mathutil.h"
+#include "common/mathutil.h"
#include "libGLESv2/Uniform.h"
#include "libGLESv2/Shader.h"
#include "libGLESv2/Constants.h"
+#include "libGLESv2/renderer/d3d/VertexDataManager.h"
+#include "libGLESv2/renderer/d3d/DynamicHLSL.h"
+
+#include "angle_gl.h"
+
+#include <string>
+#include <vector>
+
+// TODO(jmadill): place this in workarounds library
+#define ANGLE_WORKAROUND_ENABLED 1
+#define ANGLE_WORKAROUND_DISABLED 2
+#define ANGLE_MRT_PERF_WORKAROUND ANGLE_WORKAROUND_ENABLED
+
+namespace sh
+{
+class HLSLBlockEncoder;
+}
+
+#include <GLES3/gl3.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <string>
+#include <vector>
namespace rx
{
class ShaderExecutable;
class Renderer;
struct TranslatedAttribute;
+class UniformStorage;
+class ProgramImpl;
}
namespace gl
{
-class FragmentShader;
-class VertexShader;
+struct Caps;
+class Shader;
class InfoLog;
class AttributeBindings;
-struct Varying;
+class Buffer;
+class Framebuffer;
// Struct used for correlating uniforms/elements of uniform arrays to handles
-struct UniformLocation
+struct VariableLocation
{
- UniformLocation()
+ VariableLocation()
{
}
- UniformLocation(const std::string &name, unsigned int element, unsigned int index);
+ VariableLocation(const std::string &name, unsigned int element, unsigned int index);
std::string name;
unsigned int element;
unsigned int index;
};
+struct LinkedVarying
+{
+ LinkedVarying();
+ LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName,
+ unsigned int semanticIndex, unsigned int semanticIndexCount);
+
+ // Original GL name
+ std::string name;
+
+ GLenum type;
+ GLsizei size;
+
+ // DirectX semantic information
+ std::string semanticName;
+ unsigned int semanticIndex;
+ unsigned int semanticIndexCount;
+};
+
// This is the result of linking a program. It is the state that would be passed to ProgramBinary.
class ProgramBinary : public RefCountObject
{
public:
- explicit ProgramBinary(rx::Renderer *renderer);
+ explicit ProgramBinary(rx::ProgramImpl *impl);
~ProgramBinary();
- rx::ShaderExecutable *getPixelExecutable();
- rx::ShaderExecutable *getVertexExecutable();
- rx::ShaderExecutable *getGeometryExecutable();
+ rx::ProgramImpl *getImplementation() { return mProgram; }
+ const rx::ProgramImpl *getImplementation() const { return mProgram; }
+
+ rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo);
+ rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout);
+ rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]);
+ rx::ShaderExecutable *getGeometryExecutable() const;
GLuint getAttributeLocation(const char *name);
int getSemanticIndex(int attributeIndex);
- GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex);
- TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex);
+ GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps);
+ GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex);
GLint getUsedSamplerRange(SamplerType type);
bool usesPointSize() const;
bool usesPointSpriteEmulation() const;
bool usesGeometryShader() const;
GLint getUniformLocation(std::string name);
- bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
- bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
- bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
- bool setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
- bool setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value);
- bool setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value);
- bool setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value);
- bool setUniform1iv(GLint location, GLsizei count, const GLint *v);
- bool setUniform2iv(GLint location, GLsizei count, const GLint *v);
- bool setUniform3iv(GLint location, GLsizei count, const GLint *v);
- bool setUniform4iv(GLint location, GLsizei count, const GLint *v);
-
- bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params);
- bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params);
+ GLuint getUniformIndex(std::string name);
+ GLuint getUniformBlockIndex(std::string name);
+ 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);
+ void getUniformiv(GLint location, GLint *params);
+ void getUniformuiv(GLint location, GLuint *params);
void dirtyAllUniforms();
- void applyUniforms();
- bool load(InfoLog &infoLog, const void *binary, GLsizei length);
- bool save(void* binary, GLsizei bufSize, GLsizei *length);
+ Error applyUniforms();
+ Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps);
+
+ bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
+ bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
GLint getLength();
- bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader);
+ bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
+ const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps);
void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
@@ -107,62 +165,157 @@ class ProgramBinary : public RefCountObject
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;
+ LinkedUniform *getUniformByLocation(GLint location) const;
+ LinkedUniform *getUniformByName(const std::string &name) const;
+
+ void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const;
+ void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const;
+ GLuint getActiveUniformBlockCount() const;
+ GLuint getActiveUniformBlockMaxLength() const;
+ UniformBlock *getUniformBlockByIndex(GLuint blockIndex);
+
+ GLint getFragDataLocation(const char *name) const;
+
+ size_t getTransformFeedbackVaryingCount() const;
+ const LinkedVarying &getTransformFeedbackVarying(size_t idx) const;
+ GLenum getTransformFeedbackBufferMode() const;
- void validate(InfoLog &infoLog);
- bool validateSamplers(InfoLog *infoLog);
+ void validate(InfoLog &infoLog, const Caps &caps);
+ bool validateSamplers(InfoLog *infoLog, const Caps &caps);
bool isValidated() const;
+ void updateSamplerMapping();
unsigned int getSerial() const;
+ int getShaderVersion() const;
void initAttributesByLayout();
- void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const;
+ void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const;
- static std::string decorateAttribute(const std::string &name); // Prepend an underscore
+ const std::vector<LinkedUniform*> &getUniforms() const { return mUniforms; }
+
+ static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader);
private:
DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
- int packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader);
- bool linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4],
- std::string& pixelHLSL, std::string& vertexHLSL,
- FragmentShader *fragmentShader, VertexShader *vertexShader);
+ struct Sampler
+ {
+ Sampler();
+
+ bool active;
+ GLint logicalTextureUnit;
+ GLenum textureType;
+ };
+
+ void reset();
+
+ bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader);
+
+ static bool linkValidateVariablesBase(InfoLog &infoLog,
+ const std::string &variableName,
+ const sh::ShaderVariable &vertexVariable,
+ const sh::ShaderVariable &fragmentVariable,
+ bool validatePrecision);
+
+ static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
+ static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
+ static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
+ bool linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
+ void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister);
+ void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder);
+ bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps);
+ bool indexUniforms(InfoLog &infoLog, const Caps &caps);
+ static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount,
+ std::vector<Sampler> &outSamplers, GLuint *outUsedRange);
+ bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock);
+ bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
+ bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
+ const std::vector<std::string> &transformFeedbackVaryingNames,
+ GLenum transformFeedbackBufferMode,
+ std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings,
+ const Caps &caps) const;
+ template <typename VarT>
+ void defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
+ sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
+ bool inRowMajorLayout);
+ bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps);
+ bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps);
+ void defineOutputVariables(Shader *fragmentShader);
+
+ 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);
+
+ template <typename T>
+ void getUniformv(GLint location, T *params, GLenum uniformType);
+
+ class VertexExecutable
+ {
+ public:
+ VertexExecutable(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS],
+ const GLenum signature[MAX_VERTEX_ATTRIBS],
+ rx::ShaderExecutable *shaderExecutable);
+ ~VertexExecutable();
+
+ bool matchesSignature(const GLenum convertedLayout[MAX_VERTEX_ATTRIBS]) const;
+
+ const VertexFormat *inputs() const { return mInputs; }
+ const GLenum *signature() const { return mSignature; }
+ rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
+
+ private:
+ VertexFormat mInputs[MAX_VERTEX_ATTRIBS];
+ GLenum mSignature[MAX_VERTEX_ATTRIBS];
+ rx::ShaderExecutable *mShaderExecutable;
+ };
+
+ class PixelExecutable
+ {
+ public:
+ PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable);
+ ~PixelExecutable();
- bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader);
+ bool matchesSignature(const std::vector<GLenum> &signature) const { return mOutputSignature == signature; }
- bool linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms);
- bool defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog);
-
- std::string generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
- std::string generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
+ const std::vector<GLenum> &outputSignature() const { return mOutputSignature; }
+ rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
- rx::Renderer *const mRenderer;
+ private:
+ std::vector<GLenum> mOutputSignature;
+ rx::ShaderExecutable *mShaderExecutable;
+ };
+
+ rx::ProgramImpl *mProgram;
+
+ std::vector<VertexExecutable *> mVertexExecutables;
+ std::vector<PixelExecutable *> mPixelExecutables;
- rx::ShaderExecutable *mPixelExecutable;
- rx::ShaderExecutable *mVertexExecutable;
rx::ShaderExecutable *mGeometryExecutable;
- Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
+ sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
+ sh::Attribute mShaderAttributes[MAX_VERTEX_ATTRIBS];
int mSemanticIndex[MAX_VERTEX_ATTRIBS];
int mAttributesByLayout[MAX_VERTEX_ATTRIBS];
- struct Sampler
- {
- Sampler();
-
- bool active;
- GLint logicalTextureUnit;
- TextureType textureType;
- };
+ GLenum mTransformFeedbackBufferMode;
+ std::vector<LinkedVarying> mTransformFeedbackLinkedVaryings;
- Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS];
- Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+ std::vector<Sampler> mSamplersPS;
+ std::vector<Sampler> mSamplersVS;
GLuint mUsedVertexSamplerRange;
GLuint mUsedPixelSamplerRange;
bool mUsesPointSize;
+ int mShaderVersion;
+ bool mDirtySamplerMapping;
- UniformArray mUniforms;
- typedef std::vector<UniformLocation> UniformIndex;
- UniformIndex mUniformIndex;
+ std::vector<LinkedUniform*> mUniforms;
+ std::vector<UniformBlock*> mUniformBlocks;
+ std::vector<VariableLocation> mUniformIndex;
+ std::map<int, VariableLocation> mOutputVariables;
bool mValidated;
@@ -171,6 +324,7 @@ class ProgramBinary : public RefCountObject
static unsigned int issueSerial();
static unsigned int mCurrentSerial;
};
+
}
#endif // LIBGLESV2_PROGRAM_BINARY_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Query.cpp b/src/3rdparty/angle/src/libGLESv2/Query.cpp
index bd987954f1..4ee3525509 100644
--- a/src/3rdparty/angle/src/libGLESv2/Query.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Query.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -9,39 +8,38 @@
#include "libGLESv2/Query.h"
#include "libGLESv2/renderer/QueryImpl.h"
-#include "libGLESv2/renderer/Renderer.h"
namespace gl
{
-
-Query::Query(rx::Renderer *renderer, GLenum type, GLuint id) : RefCountObject(id)
-{
- mQuery = renderer->createQuery(type);
+Query::Query(rx::QueryImpl *impl, GLuint id)
+ : RefCountObject(id),
+ mQuery(impl)
+{
}
Query::~Query()
{
- delete mQuery;
+ SafeDelete(mQuery);
}
-void Query::begin()
+Error Query::begin()
{
- mQuery->begin();
+ return mQuery->begin();
}
-void Query::end()
+Error Query::end()
{
- mQuery->end();
+ return mQuery->end();
}
-GLuint Query::getResult()
+Error Query::getResult(GLuint *params)
{
- return mQuery->getResult();
+ return mQuery->getResult(params);
}
-GLboolean Query::isResultAvailable()
+Error Query::isResultAvailable(GLuint *available)
{
- return mQuery->isResultAvailable();
+ return mQuery->isResultAvailable(available);
}
GLenum Query::getType() const
diff --git a/src/3rdparty/angle/src/libGLESv2/Query.h b/src/3rdparty/angle/src/libGLESv2/Query.h
index e9b95b729b..a7ec404f85 100644
--- a/src/3rdparty/angle/src/libGLESv2/Query.h
+++ b/src/3rdparty/angle/src/libGLESv2/Query.h
@@ -9,15 +9,14 @@
#ifndef LIBGLESV2_QUERY_H_
#define LIBGLESV2_QUERY_H_
-#define GL_APICALL
-#include <GLES2/gl2.h>
-
+#include "libGLESv2/Error.h"
#include "common/angleutils.h"
#include "common/RefCountObject.h"
+#include "angle_gl.h"
+
namespace rx
{
-class Renderer;
class QueryImpl;
}
@@ -27,14 +26,14 @@ namespace gl
class Query : public RefCountObject
{
public:
- Query(rx::Renderer *renderer, GLenum type, GLuint id);
+ Query(rx::QueryImpl *impl, GLuint id);
virtual ~Query();
- void begin();
- void end();
+ Error begin();
+ Error end();
- GLuint getResult();
- GLboolean isResultAvailable();
+ Error getResult(GLuint *params);
+ Error isResultAvailable(GLuint *available);
GLenum getType() const;
diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp
index 98d33ec6c3..9406fce58d 100644
--- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -10,312 +9,105 @@
// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-
#include "libGLESv2/Texture.h"
+#include "libGLESv2/formatutils.h"
+#include "libGLESv2/FramebufferAttachment.h"
#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/utilities.h"
+#include "libGLESv2/renderer/RenderTarget.h"
+
+#include "common/utilities.h"
namespace gl
{
unsigned int RenderbufferStorage::mCurrentSerial = 1;
-RenderbufferInterface::RenderbufferInterface()
-{
-}
-
-// The default case for classes inherited from RenderbufferInterface is not to
-// need to do anything upon the reference count to the parent Renderbuffer incrementing
-// or decrementing.
-void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy)
-{
-}
-
-void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy)
-{
-}
-
-GLuint RenderbufferInterface::getRedSize() const
-{
- return gl::GetRedSize(getActualFormat());
-}
-
-GLuint RenderbufferInterface::getGreenSize() const
-{
- return gl::GetGreenSize(getActualFormat());
-}
-
-GLuint RenderbufferInterface::getBlueSize() const
-{
- return gl::GetBlueSize(getActualFormat());
-}
-
-GLuint RenderbufferInterface::getAlphaSize() const
-{
- return gl::GetAlphaSize(getActualFormat());
-}
-
-GLuint RenderbufferInterface::getDepthSize() const
-{
- return gl::GetDepthSize(getActualFormat());
-}
-
-GLuint RenderbufferInterface::getStencilSize() const
-{
- return gl::GetStencilSize(getActualFormat());
-}
-
-///// RenderbufferTexture2D Implementation ////////
-
-RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLenum target) : mTarget(target)
-{
- mTexture2D.set(texture);
-}
-
-RenderbufferTexture2D::~RenderbufferTexture2D()
-{
- mTexture2D.set(NULL);
-}
-
-// Textures need to maintain their own reference count for references via
-// Renderbuffers acting as proxies. Here, we notify the texture of a reference.
-void RenderbufferTexture2D::addProxyRef(const Renderbuffer *proxy)
-{
- mTexture2D->addProxyRef(proxy);
-}
-
-void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy)
-{
- mTexture2D->releaseProxy(proxy);
-}
-
-rx::RenderTarget *RenderbufferTexture2D::getRenderTarget()
-{
- return mTexture2D->getRenderTarget(mTarget);
-}
-
-rx::RenderTarget *RenderbufferTexture2D::getDepthStencil()
-{
- return mTexture2D->getDepthStencil(mTarget);
-}
-
-GLsizei RenderbufferTexture2D::getWidth() const
-{
- return mTexture2D->getWidth(0);
-}
-
-GLsizei RenderbufferTexture2D::getHeight() const
-{
- return mTexture2D->getHeight(0);
-}
-
-GLenum RenderbufferTexture2D::getInternalFormat() const
-{
- return mTexture2D->getInternalFormat(0);
-}
-
-GLenum RenderbufferTexture2D::getActualFormat() const
-{
- return mTexture2D->getActualFormat(0);
-}
-
-GLsizei RenderbufferTexture2D::getSamples() const
-{
- return 0;
-}
-
-unsigned int RenderbufferTexture2D::getSerial() const
-{
- return mTexture2D->getRenderTargetSerial(mTarget);
-}
-
-unsigned int RenderbufferTexture2D::getTextureSerial() const
-{
- return mTexture2D->getTextureSerial();
-}
-
-///// RenderbufferTextureCubeMap Implementation ////////
-
-RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target) : mTarget(target)
-{
- mTextureCubeMap.set(texture);
-}
-
-RenderbufferTextureCubeMap::~RenderbufferTextureCubeMap()
-{
- mTextureCubeMap.set(NULL);
-}
-
-// Textures need to maintain their own reference count for references via
-// Renderbuffers acting as proxies. Here, we notify the texture of a reference.
-void RenderbufferTextureCubeMap::addProxyRef(const Renderbuffer *proxy)
-{
- mTextureCubeMap->addProxyRef(proxy);
-}
-
-void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy)
+Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *newStorage)
+ : RefCountObject(id),
+ mStorage(newStorage)
{
- mTextureCubeMap->releaseProxy(proxy);
-}
-
-rx::RenderTarget *RenderbufferTextureCubeMap::getRenderTarget()
-{
- return mTextureCubeMap->getRenderTarget(mTarget);
-}
-
-rx::RenderTarget *RenderbufferTextureCubeMap::getDepthStencil()
-{
- return NULL;
-}
-
-GLsizei RenderbufferTextureCubeMap::getWidth() const
-{
- return mTextureCubeMap->getWidth(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-}
-
-GLsizei RenderbufferTextureCubeMap::getHeight() const
-{
- return mTextureCubeMap->getHeight(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-}
-
-GLenum RenderbufferTextureCubeMap::getInternalFormat() const
-{
- return mTextureCubeMap->getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-}
-
-GLenum RenderbufferTextureCubeMap::getActualFormat() const
-{
- return mTextureCubeMap->getActualFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-}
-
-GLsizei RenderbufferTextureCubeMap::getSamples() const
-{
- return 0;
-}
-
-unsigned int RenderbufferTextureCubeMap::getSerial() const
-{
- return mTextureCubeMap->getRenderTargetSerial(mTarget);
-}
-
-unsigned int RenderbufferTextureCubeMap::getTextureSerial() const
-{
- return mTextureCubeMap->getTextureSerial();
-}
-
-////// Renderbuffer Implementation //////
-
-Renderbuffer::Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *instance) : RefCountObject(id)
-{
- ASSERT(instance != NULL);
- mInstance = instance;
+ ASSERT(mStorage);
}
Renderbuffer::~Renderbuffer()
{
- delete mInstance;
-}
-
-// The RenderbufferInterface contained in this Renderbuffer may need to maintain
-// its own reference count, so we pass it on here.
-void Renderbuffer::addRef() const
-{
- mInstance->addProxyRef(this);
-
- RefCountObject::addRef();
+ SafeDelete(mStorage);
}
-void Renderbuffer::release() const
+void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
{
- mInstance->releaseProxy(this);
+ ASSERT(newStorage);
- RefCountObject::release();
-}
-
-rx::RenderTarget *Renderbuffer::getRenderTarget()
-{
- return mInstance->getRenderTarget();
+ SafeDelete(mStorage);
+ mStorage = newStorage;
}
-rx::RenderTarget *Renderbuffer::getDepthStencil()
+RenderbufferStorage *Renderbuffer::getStorage()
{
- return mInstance->getDepthStencil();
+ ASSERT(mStorage);
+ return mStorage;
}
GLsizei Renderbuffer::getWidth() const
{
- return mInstance->getWidth();
+ ASSERT(mStorage);
+ return mStorage->getWidth();
}
GLsizei Renderbuffer::getHeight() const
{
- return mInstance->getHeight();
+ ASSERT(mStorage);
+ return mStorage->getHeight();
}
GLenum Renderbuffer::getInternalFormat() const
{
- return mInstance->getInternalFormat();
+ ASSERT(mStorage);
+ return mStorage->getInternalFormat();
}
GLenum Renderbuffer::getActualFormat() const
{
- return mInstance->getActualFormat();
+ ASSERT(mStorage);
+ return mStorage->getActualFormat();
+}
+
+GLsizei Renderbuffer::getSamples() const
+{
+ ASSERT(mStorage);
+ return mStorage->getSamples();
}
GLuint Renderbuffer::getRedSize() const
{
- return mInstance->getRedSize();
+ return GetInternalFormatInfo(getActualFormat()).redBits;
}
GLuint Renderbuffer::getGreenSize() const
{
- return mInstance->getGreenSize();
+ return GetInternalFormatInfo(getActualFormat()).greenBits;
}
GLuint Renderbuffer::getBlueSize() const
{
- return mInstance->getBlueSize();
+ return GetInternalFormatInfo(getActualFormat()).blueBits;
}
GLuint Renderbuffer::getAlphaSize() const
{
- return mInstance->getAlphaSize();
+ return GetInternalFormatInfo(getActualFormat()).alphaBits;
}
GLuint Renderbuffer::getDepthSize() const
{
- return mInstance->getDepthSize();
+ return GetInternalFormatInfo(getActualFormat()).depthBits;
}
GLuint Renderbuffer::getStencilSize() const
{
- return mInstance->getStencilSize();
-}
-
-GLsizei Renderbuffer::getSamples() const
-{
- return mInstance->getSamples();
-}
-
-unsigned int Renderbuffer::getSerial() const
-{
- return mInstance->getSerial();
-}
-
-unsigned int Renderbuffer::getTextureSerial() const
-{
- return mInstance->getTextureSerial();
-}
-
-void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
-{
- ASSERT(newStorage != NULL);
-
- delete mInstance;
- mInstance = newStorage;
+ return GetInternalFormatInfo(getActualFormat()).stencilBits;
}
-RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial())
+RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerials(1))
{
mWidth = 0;
mHeight = 0;
@@ -333,11 +125,6 @@ rx::RenderTarget *RenderbufferStorage::getRenderTarget()
return NULL;
}
-rx::RenderTarget *RenderbufferStorage::getDepthStencil()
-{
- return NULL;
-}
-
GLsizei RenderbufferStorage::getWidth() const
{
return mWidth;
@@ -368,16 +155,21 @@ unsigned int RenderbufferStorage::getSerial() const
return mSerial;
}
-unsigned int RenderbufferStorage::issueSerial()
+unsigned int RenderbufferStorage::issueSerials(unsigned int count)
+{
+ unsigned int firstSerial = mCurrentSerial;
+ mCurrentSerial += count;
+ return firstSerial;
+}
+
+bool RenderbufferStorage::isTexture() const
{
- return mCurrentSerial++;
+ return false;
}
-unsigned int RenderbufferStorage::issueCubeSerials()
+unsigned int RenderbufferStorage::getTextureSerial() const
{
- unsigned int firstSerial = mCurrentSerial;
- mCurrentSerial += 6;
- return firstSerial;
+ return -1;
}
Colorbuffer::Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain)
@@ -396,7 +188,7 @@ Colorbuffer::Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain)
Colorbuffer::Colorbuffer(rx::Renderer *renderer, int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL)
{
- mRenderTarget = renderer->createRenderTarget(width, height, format, samples, false);
+ mRenderTarget = renderer->createRenderTarget(width, height, format, samples);
if (mRenderTarget)
{
@@ -418,12 +210,7 @@ Colorbuffer::~Colorbuffer()
rx::RenderTarget *Colorbuffer::getRenderTarget()
{
- if (mRenderTarget)
- {
- return mRenderTarget;
- }
-
- return NULL;
+ return mRenderTarget;
}
DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain)
@@ -442,7 +229,7 @@ DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *sw
DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples)
{
- mDepthStencil = renderer->createRenderTarget(width, height, GL_DEPTH24_STENCIL8_OES, samples, true);
+ mDepthStencil = renderer->createRenderTarget(width, height, GL_DEPTH24_STENCIL8_OES, samples);
mWidth = mDepthStencil->getWidth();
mHeight = mDepthStencil->getHeight();
@@ -459,14 +246,9 @@ DepthStencilbuffer::~DepthStencilbuffer()
}
}
-rx::RenderTarget *DepthStencilbuffer::getDepthStencil()
+rx::RenderTarget *DepthStencilbuffer::getRenderTarget()
{
- if (mDepthStencil)
- {
- return mDepthStencil;
- }
-
- return NULL;
+ return mDepthStencil;
}
Depthbuffer::Depthbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples)
diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h
index d46fd44557..71bcb0e1f8 100644
--- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h
@@ -12,8 +12,7 @@
#ifndef LIBGLESV2_RENDERBUFFER_H_
#define LIBGLESV2_RENDERBUFFER_H_
-#define GL_APICALL
-#include <GLES2/gl2.h>
+#include "angle_gl.h"
#include "common/angleutils.h"
#include "common/RefCountObject.h"
@@ -23,35 +22,33 @@ namespace rx
class Renderer;
class SwapChain;
class RenderTarget;
+class TextureStorage;
}
namespace gl
{
-class Texture2D;
-class TextureCubeMap;
-class Renderbuffer;
-class Colorbuffer;
-class DepthStencilbuffer;
+class RenderbufferStorage;
+class FramebufferAttachment;
-class RenderbufferInterface
+// 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 : public RefCountObject
{
public:
- RenderbufferInterface();
-
- virtual ~RenderbufferInterface() {};
-
- virtual void addProxyRef(const Renderbuffer *proxy);
- virtual void releaseProxy(const Renderbuffer *proxy);
-
- virtual rx::RenderTarget *getRenderTarget() = 0;
- virtual rx::RenderTarget *getDepthStencil() = 0;
+ Renderbuffer(GLuint id, RenderbufferStorage *newStorage);
+ virtual ~Renderbuffer();
- virtual GLsizei getWidth() const = 0;
- virtual GLsizei getHeight() const = 0;
- virtual GLenum getInternalFormat() const = 0;
- virtual GLenum getActualFormat() const = 0;
- virtual GLsizei getSamples() const = 0;
+ void setStorage(RenderbufferStorage *newStorage);
+ RenderbufferStorage *getStorage();
+ GLsizei getWidth() const;
+ GLsizei getHeight() const;
+ GLenum getInternalFormat() const;
+ GLenum getActualFormat() const;
+ GLsizei getSamples() const;
GLuint getRedSize() const;
GLuint getGreenSize() const;
GLuint getBlueSize() const;
@@ -59,75 +56,14 @@ class RenderbufferInterface
GLuint getDepthSize() const;
GLuint getStencilSize() const;
- virtual unsigned int getSerial() const = 0;
- virtual unsigned int getTextureSerial() const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RenderbufferInterface);
-};
-
-class RenderbufferTexture2D : public RenderbufferInterface
-{
- public:
- RenderbufferTexture2D(Texture2D *texture, GLenum target);
-
- virtual ~RenderbufferTexture2D();
-
- void addProxyRef(const Renderbuffer *proxy);
- void releaseProxy(const Renderbuffer *proxy);
-
- rx::RenderTarget *getRenderTarget();
- rx::RenderTarget *getDepthStencil();
-
- virtual GLsizei getWidth() const;
- virtual GLsizei getHeight() const;
- virtual GLenum getInternalFormat() const;
- virtual GLenum getActualFormat() const;
- virtual GLsizei getSamples() const;
-
- virtual unsigned int getSerial() const;
- virtual unsigned int getTextureSerial() const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RenderbufferTexture2D);
-
- BindingPointer <Texture2D> mTexture2D;
- GLenum mTarget;
-};
-
-class RenderbufferTextureCubeMap : public RenderbufferInterface
-{
- public:
- RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target);
-
- virtual ~RenderbufferTextureCubeMap();
-
- void addProxyRef(const Renderbuffer *proxy);
- void releaseProxy(const Renderbuffer *proxy);
-
- rx::RenderTarget *getRenderTarget();
- rx::RenderTarget *getDepthStencil();
-
- virtual GLsizei getWidth() const;
- virtual GLsizei getHeight() const;
- virtual GLenum getInternalFormat() const;
- virtual GLenum getActualFormat() const;
- virtual GLsizei getSamples() const;
-
- virtual unsigned int getSerial() const;
- virtual unsigned int getTextureSerial() const;
-
private:
- DISALLOW_COPY_AND_ASSIGN(RenderbufferTextureCubeMap);
-
- BindingPointer <TextureCubeMap> mTextureCubeMap;
- GLenum mTarget;
+ RenderbufferStorage *mStorage;
};
// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage
// is called. The specific concrete type depends on whether the internal format is
// colour depth, stencil or packed depth/stencil.
-class RenderbufferStorage : public RenderbufferInterface
+class RenderbufferStorage
{
public:
RenderbufferStorage();
@@ -135,7 +71,6 @@ class RenderbufferStorage : public RenderbufferInterface
virtual ~RenderbufferStorage() = 0;
virtual rx::RenderTarget *getRenderTarget();
- virtual rx::RenderTarget *getDepthStencil();
virtual GLsizei getWidth() const;
virtual GLsizei getHeight() const;
@@ -144,10 +79,11 @@ class RenderbufferStorage : public RenderbufferInterface
virtual GLsizei getSamples() const;
virtual unsigned int getSerial() const;
- virtual unsigned int getTextureSerial() const { return 0; }
- static unsigned int issueSerial();
- static unsigned int issueCubeSerials();
+ virtual bool isTexture() const;
+ virtual unsigned int getTextureSerial() const;
+
+ static unsigned int issueSerials(unsigned int count);
protected:
GLsizei mWidth;
@@ -164,49 +100,6 @@ class RenderbufferStorage : public RenderbufferInterface
static unsigned int mCurrentSerial;
};
-// Renderbuffer implements the GL renderbuffer object.
-// It's only a proxy for a RenderbufferInterface instance; the internal object
-// can change whenever glRenderbufferStorage is called.
-class Renderbuffer : public RefCountObject
-{
- public:
- Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *storage);
-
- virtual ~Renderbuffer();
-
- // These functions from RefCountObject are overloaded here because
- // Textures need to maintain their own count of references to them via
- // Renderbuffers/RenderbufferTextures. These functions invoke those
- // reference counting functions on the RenderbufferInterface.
- void addRef() const;
- void release() const;
-
- rx::RenderTarget *getRenderTarget();
- rx::RenderTarget *getDepthStencil();
-
- GLsizei getWidth() const;
- GLsizei getHeight() const;
- GLenum getInternalFormat() const;
- GLenum getActualFormat() const;
- GLuint getRedSize() const;
- GLuint getGreenSize() const;
- GLuint getBlueSize() const;
- GLuint getAlphaSize() const;
- GLuint getDepthSize() const;
- GLuint getStencilSize() const;
- GLsizei getSamples() const;
-
- unsigned int getSerial() const;
- unsigned int getTextureSerial() const;
-
- void setStorage(RenderbufferStorage *newStorage);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Renderbuffer);
-
- RenderbufferInterface *mInstance;
-};
-
class Colorbuffer : public RenderbufferStorage
{
public:
@@ -231,7 +124,7 @@ class DepthStencilbuffer : public RenderbufferStorage
~DepthStencilbuffer();
- virtual rx::RenderTarget *getDepthStencil();
+ virtual rx::RenderTarget *getRenderTarget();
protected:
rx::RenderTarget *mDepthStencil;
@@ -261,6 +154,7 @@ class Stencilbuffer : public DepthStencilbuffer
private:
DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);
};
+
}
#endif // LIBGLESV2_RENDERBUFFER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp
index 58dd44fd95..9121de1750 100644
--- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp
@@ -1,6 +1,5 @@
-#include "precompiled.h"
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -15,6 +14,9 @@
#include "libGLESv2/Renderbuffer.h"
#include "libGLESv2/Shader.h"
#include "libGLESv2/Texture.h"
+#include "libGLESv2/Sampler.h"
+#include "libGLESv2/Fence.h"
+#include "libGLESv2/renderer/Renderer.h"
namespace gl
{
@@ -50,6 +52,16 @@ ResourceManager::~ResourceManager()
{
deleteTexture(mTextureMap.begin()->first);
}
+
+ while (!mSamplerMap.empty())
+ {
+ deleteSampler(mSamplerMap.begin()->first);
+ }
+
+ while (!mFenceSyncMap.empty())
+ {
+ deleteFenceSync(mFenceSyncMap.begin()->first);
+ }
}
void ResourceManager::addRef()
@@ -80,13 +92,9 @@ GLuint ResourceManager::createShader(GLenum type)
{
GLuint handle = mProgramShaderHandleAllocator.allocate();
- if (type == GL_VERTEX_SHADER)
- {
- mShaderMap[handle] = new VertexShader(this, mRenderer, handle);
- }
- else if (type == GL_FRAGMENT_SHADER)
+ if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER)
{
- mShaderMap[handle] = new FragmentShader(this, mRenderer, handle);
+ mShaderMap[handle] = new Shader(this, mRenderer->createShader(type), type, handle);
}
else UNREACHABLE();
@@ -123,6 +131,28 @@ GLuint ResourceManager::createRenderbuffer()
return handle;
}
+// Returns an unused sampler name
+GLuint ResourceManager::createSampler()
+{
+ GLuint handle = mSamplerHandleAllocator.allocate();
+
+ mSamplerMap[handle] = NULL;
+
+ return handle;
+}
+
+// Returns the next unused fence name, and allocates the fence
+GLuint ResourceManager::createFenceSync()
+{
+ GLuint handle = mFenceSyncHandleAllocator.allocate();
+
+ FenceSync *fenceSync = new FenceSync(mRenderer, handle);
+ fenceSync->addRef();
+ mFenceSyncMap[handle] = fenceSync;
+
+ return handle;
+}
+
void ResourceManager::deleteBuffer(GLuint buffer)
{
BufferMap::iterator bufferObject = mBufferMap.find(buffer);
@@ -197,6 +227,30 @@ void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
}
}
+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);
+ }
+}
+
Buffer *ResourceManager::getBuffer(unsigned int handle)
{
BufferMap::iterator buffer = mBufferMap.find(handle);
@@ -269,6 +323,34 @@ Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
}
}
+Sampler *ResourceManager::getSampler(unsigned int handle)
+{
+ auto sampler = mSamplerMap.find(handle);
+
+ if (sampler == mSamplerMap.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ return sampler->second;
+ }
+}
+
+FenceSync *ResourceManager::getFenceSync(unsigned int handle)
+{
+ auto fenceObjectIt = mFenceSyncMap.find(handle);
+
+ if (fenceObjectIt == mFenceSyncMap.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ return fenceObjectIt->second;
+ }
+}
+
void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
{
mRenderbufferMap[handle] = buffer;
@@ -278,25 +360,33 @@ void ResourceManager::checkBufferAllocation(unsigned int buffer)
{
if (buffer != 0 && !getBuffer(buffer))
{
- Buffer *bufferObject = new Buffer(mRenderer, buffer);
+ Buffer *bufferObject = new Buffer(mRenderer->createBuffer(), buffer);
mBufferMap[buffer] = bufferObject;
bufferObject->addRef();
}
}
-void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type)
+void ResourceManager::checkTextureAllocation(GLuint texture, GLenum type)
{
if (!getTexture(texture) && texture != 0)
{
Texture *textureObject;
- if (type == TEXTURE_2D)
+ if (type == GL_TEXTURE_2D)
+ {
+ textureObject = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), texture);
+ }
+ else if (type == GL_TEXTURE_CUBE_MAP)
+ {
+ textureObject = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), texture);
+ }
+ else if (type == GL_TEXTURE_3D)
{
- textureObject = new Texture2D(mRenderer, texture);
+ textureObject = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), texture);
}
- else if (type == TEXTURE_CUBE)
+ else if (type == GL_TEXTURE_2D_ARRAY)
{
- textureObject = new TextureCubeMap(mRenderer, texture);
+ textureObject = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), texture);
}
else
{
@@ -313,10 +403,25 @@ void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer)
{
if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
{
- Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer, renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0));
+ Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0));
mRenderbufferMap[renderbuffer] = renderbufferObject;
renderbufferObject->addRef();
}
}
+void ResourceManager::checkSamplerAllocation(GLuint sampler)
+{
+ if (sampler != 0 && !getSampler(sampler))
+ {
+ Sampler *samplerObject = new Sampler(sampler);
+ mSamplerMap[sampler] = samplerObject;
+ samplerObject->addRef();
+ }
+}
+
+bool ResourceManager::isSampler(GLuint sampler)
+{
+ return mSamplerMap.find(sampler) != mSamplerMap.end();
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h
index e99c77c35d..7d53bd4854 100644
--- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h
+++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -10,19 +10,14 @@
#ifndef LIBGLESV2_RESOURCEMANAGER_H_
#define LIBGLESV2_RESOURCEMANAGER_H_
-#define GL_APICALL
-#include <GLES2/gl2.h>
-
-#ifdef _MSC_VER
-#include <hash_map>
-#else
-#include <unordered_map>
-#endif
-
#include "common/angleutils.h"
#include "libGLESv2/angletypes.h"
#include "libGLESv2/HandleAllocator.h"
+#include "angle_gl.h"
+
+#include <unordered_map>
+
namespace rx
{
class Renderer;
@@ -35,6 +30,8 @@ class Shader;
class Program;
class Texture;
class Renderbuffer;
+class Sampler;
+class FenceSync;
class ResourceManager
{
@@ -50,24 +47,33 @@ class ResourceManager
GLuint createProgram();
GLuint createTexture();
GLuint createRenderbuffer();
+ GLuint createSampler();
+ GLuint createFenceSync();
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);
Buffer *getBuffer(GLuint handle);
Shader *getShader(GLuint handle);
Program *getProgram(GLuint handle);
Texture *getTexture(GLuint handle);
Renderbuffer *getRenderbuffer(GLuint handle);
-
+ Sampler *getSampler(GLuint handle);
+ FenceSync *getFenceSync(GLuint handle);
+
void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
void checkBufferAllocation(unsigned int buffer);
- void checkTextureAllocation(GLuint texture, TextureType type);
+ void checkTextureAllocation(GLuint texture, GLenum type);
void checkRenderbufferAllocation(GLuint renderbuffer);
+ void checkSamplerAllocation(GLuint sampler);
+
+ bool isSampler(GLuint sampler);
private:
DISALLOW_COPY_AND_ASSIGN(ResourceManager);
@@ -75,32 +81,32 @@ class ResourceManager
std::size_t mRefCount;
rx::Renderer *mRenderer;
-#ifndef HASH_MAP
-# ifdef _MSC_VER
-# define HASH_MAP stdext::hash_map
-# else
-# define HASH_MAP std::unordered_map
-# endif
-#endif
-
- typedef HASH_MAP<GLuint, Buffer*> BufferMap;
+ typedef std::unordered_map<GLuint, Buffer*> BufferMap;
BufferMap mBufferMap;
HandleAllocator mBufferHandleAllocator;
- typedef HASH_MAP<GLuint, Shader*> ShaderMap;
+ typedef std::unordered_map<GLuint, Shader*> ShaderMap;
ShaderMap mShaderMap;
- typedef HASH_MAP<GLuint, Program*> ProgramMap;
+ typedef std::unordered_map<GLuint, Program*> ProgramMap;
ProgramMap mProgramMap;
HandleAllocator mProgramShaderHandleAllocator;
- typedef HASH_MAP<GLuint, Texture*> TextureMap;
+ typedef std::unordered_map<GLuint, Texture*> TextureMap;
TextureMap mTextureMap;
HandleAllocator mTextureHandleAllocator;
- typedef HASH_MAP<GLuint, Renderbuffer*> RenderbufferMap;
+ typedef std::unordered_map<GLuint, Renderbuffer*> RenderbufferMap;
RenderbufferMap mRenderbufferMap;
HandleAllocator mRenderbufferHandleAllocator;
+
+ typedef std::unordered_map<GLuint, Sampler*> SamplerMap;
+ SamplerMap mSamplerMap;
+ HandleAllocator mSamplerHandleAllocator;
+
+ typedef std::unordered_map<GLuint, FenceSync*> FenceMap;
+ FenceMap mFenceSyncMap;
+ HandleAllocator mFenceSyncHandleAllocator;
};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Sampler.cpp b/src/3rdparty/angle/src/libGLESv2/Sampler.cpp
new file mode 100644
index 0000000000..b906e65557
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/Sampler.cpp
@@ -0,0 +1,43 @@
+//
+// 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 "libGLESv2/Sampler.h"
+#include "libGLESv2/angletypes.h"
+
+namespace gl
+{
+
+Sampler::Sampler(GLuint id)
+ : RefCountObject(id),
+ mMinFilter(GL_NEAREST_MIPMAP_LINEAR),
+ mMagFilter(GL_LINEAR),
+ mWrapS(GL_REPEAT),
+ mWrapT(GL_REPEAT),
+ mWrapR(GL_REPEAT),
+ mMinLod(-1000.0f),
+ mMaxLod(1000.0f),
+ mComparisonMode(GL_NONE),
+ mComparisonFunc(GL_LEQUAL)
+{
+}
+
+void Sampler::getState(SamplerState *samplerState) const
+{
+ samplerState->minFilter = mMinFilter;
+ samplerState->magFilter = mMagFilter;
+ samplerState->wrapS = mWrapS;
+ samplerState->wrapT = mWrapT;
+ samplerState->wrapR = mWrapR;
+ samplerState->minLod = mMinLod;
+ samplerState->maxLod = mMaxLod;
+ samplerState->compareMode = mComparisonMode;
+ samplerState->compareFunc = mComparisonFunc;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Sampler.h b/src/3rdparty/angle/src/libGLESv2/Sampler.h
new file mode 100644
index 0000000000..257bc25d22
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/Sampler.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.
+//
+
+// Sampler.h : Defines the Sampler class, which represents a GLES 3
+// sampler object. Sampler objects store some state needed to sample textures.
+
+#ifndef LIBGLESV2_SAMPLER_H_
+#define LIBGLESV2_SAMPLER_H_
+
+#include "common/RefCountObject.h"
+
+namespace gl
+{
+struct SamplerState;
+
+class Sampler : public RefCountObject
+{
+ public:
+ Sampler(GLuint id);
+
+ void setMinFilter(GLenum minFilter) { mMinFilter = minFilter; }
+ void setMagFilter(GLenum magFilter) { mMagFilter = magFilter; }
+ void setWrapS(GLenum wrapS) { mWrapS = wrapS; }
+ void setWrapT(GLenum wrapT) { mWrapT = wrapT; }
+ void setWrapR(GLenum wrapR) { mWrapR = wrapR; }
+ void setMinLod(GLfloat minLod) { mMinLod = minLod; }
+ void setMaxLod(GLfloat maxLod) { mMaxLod = maxLod; }
+ void setComparisonMode(GLenum comparisonMode) { mComparisonMode = comparisonMode; }
+ void setComparisonFunc(GLenum comparisonFunc) { mComparisonFunc = comparisonFunc; }
+
+ GLenum getMinFilter() const { return mMinFilter; }
+ GLenum getMagFilter() const { return mMagFilter; }
+ GLenum getWrapS() const { return mWrapS; }
+ GLenum getWrapT() const { return mWrapT; }
+ GLenum getWrapR() const { return mWrapR; }
+ GLfloat getMinLod() const { return mMinLod; }
+ GLfloat getMaxLod() const { return mMaxLod; }
+ GLenum getComparisonMode() const { return mComparisonMode; }
+ GLenum getComparisonFunc() const { return mComparisonFunc; }
+
+ void getState(SamplerState *samplerState) const;
+
+ private:
+ GLenum mMinFilter;
+ GLenum mMagFilter;
+ GLenum mWrapS;
+ GLenum mWrapT;
+ GLenum mWrapR;
+ GLfloat mMinLod;
+ GLfloat mMaxLod;
+ GLenum mComparisonMode;
+ GLenum mComparisonFunc;
+};
+
+}
+
+#endif // LIBGLESV2_SAMPLER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp
index f6a2f03dfc..e3da2b1a9e 100644
--- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp
@@ -1,6 +1,5 @@
-#include "precompiled.h"
//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -10,37 +9,34 @@
// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
#include "libGLESv2/Shader.h"
-
-#include "GLSLANG/ShaderLang.h"
-#include "libGLESv2/utilities.h"
#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/ShaderImpl.h"
#include "libGLESv2/Constants.h"
#include "libGLESv2/ResourceManager.h"
+#include "common/utilities.h"
+
+#include "GLSLANG/ShaderLang.h"
+
+#include <sstream>
+
namespace gl
{
-void *Shader::mFragmentCompiler = NULL;
-void *Shader::mVertexCompiler = NULL;
-Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
- : mHandle(handle), mRenderer(renderer), mResourceManager(manager)
+Shader::Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle)
+ : mShader(impl),
+ mType(type),
+ mHandle(handle),
+ mResourceManager(manager),
+ mRefCount(0),
+ mDeleteStatus(false),
+ mCompiled(false)
{
- mSource = NULL;
- mHlsl = NULL;
- mInfoLog = NULL;
-
- uncompile();
- initializeCompiler();
-
- mRefCount = 0;
- mDeleteStatus = false;
+ ASSERT(impl);
}
Shader::~Shader()
{
- delete[] mSource;
- delete[] mHlsl;
- delete[] mInfoLog;
}
GLuint Shader::getHandle() const
@@ -48,69 +44,31 @@ GLuint Shader::getHandle() const
return mHandle;
}
-void Shader::setSource(GLsizei count, const char **string, const GLint *length)
+void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
{
- delete[] mSource;
- int totalLength = 0;
+ std::ostringstream stream;
for (int i = 0; i < count; i++)
{
- if (length && length[i] >= 0)
- {
- totalLength += length[i];
- }
- else
- {
- totalLength += (int)strlen(string[i]);
- }
+ stream << string[i];
}
- mSource = new char[totalLength + 1];
- char *code = mSource;
-
- for (int i = 0; i < count; i++)
- {
- int stringLength;
-
- if (length && length[i] >= 0)
- {
- stringLength = length[i];
- }
- else
- {
- stringLength = (int)strlen(string[i]);
- }
-
- strncpy(code, string[i], stringLength);
- code += stringLength;
- }
-
- mSource[totalLength] = '\0';
+ mSource = stream.str();
}
int Shader::getInfoLogLength() const
{
- if (!mInfoLog)
- {
- return 0;
- }
- else
- {
- return strlen(mInfoLog) + 1;
- }
+ return mShader->getInfoLog().empty() ? 0 : (mShader->getInfoLog().length() + 1);
}
-void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
+void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
{
int index = 0;
if (bufSize > 0)
{
- if (mInfoLog)
- {
- index = std::min(bufSize - 1, (int)strlen(mInfoLog));
- memcpy(infoLog, mInfoLog, index);
- }
+ index = std::min(bufSize - 1, static_cast<GLsizei>(mShader->getInfoLog().length()));
+ memcpy(infoLog, mShader->getInfoLog().c_str(), index);
infoLog[index] = '\0';
}
@@ -123,39 +81,22 @@ void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
int Shader::getSourceLength() const
{
- if (!mSource)
- {
- return 0;
- }
- else
- {
- return strlen(mSource) + 1;
- }
+ return mSource.empty() ? 0 : (mSource.length() + 1);
}
int Shader::getTranslatedSourceLength() const
{
- if (!mHlsl)
- {
- return 0;
- }
- else
- {
- return strlen(mHlsl) + 1;
- }
+ return mShader->getTranslatedSource().empty() ? 0 : (mShader->getTranslatedSource().length() + 1);
}
-void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer)
+void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer)
{
int index = 0;
if (bufSize > 0)
{
- if (source)
- {
- index = std::min(bufSize - 1, (int)strlen(source));
- memcpy(buffer, source, index);
- }
+ index = std::min(bufSize - 1, static_cast<GLsizei>(source.length()));
+ memcpy(buffer, source.c_str(), index);
buffer[index] = '\0';
}
@@ -166,29 +107,19 @@ void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char
}
}
-void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer)
+void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
{
getSourceImpl(mSource, bufSize, length, buffer);
}
-void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
+void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const
{
- getSourceImpl(mHlsl, bufSize, length, buffer);
+ getSourceImpl(mShader->getTranslatedSource(), bufSize, length, buffer);
}
-const sh::ActiveUniforms &Shader::getUniforms()
+void Shader::compile()
{
- return mActiveUniforms;
-}
-
-bool Shader::isCompiled()
-{
- return mHlsl != NULL;
-}
-
-const char *Shader::getHLSL()
-{
- return mHlsl;
+ mCompiled = mShader->compile(mSource);
}
void Shader::addRef()
@@ -221,404 +152,54 @@ void Shader::flagForDeletion()
mDeleteStatus = true;
}
-// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
-void Shader::initializeCompiler()
+const std::vector<gl::PackedVarying> &Shader::getVaryings() const
{
- if (!mFragmentCompiler)
- {
- int result = ShInitialize();
-
- if (result)
- {
- ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
-
- ShBuiltInResources resources;
- ShInitBuiltInResources(&resources);
-
- resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
- resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors();
- resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors();
- resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits();
- resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
- resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
- resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors();
- resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets();
- resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport();
- resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1;
- // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
- resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
- resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
-
- mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
- mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
- }
- }
+ return mShader->getVaryings();
}
-void Shader::releaseCompiler()
+const std::vector<sh::Uniform> &Shader::getUniforms() const
{
- ShDestruct(mFragmentCompiler);
- ShDestruct(mVertexCompiler);
-
- mFragmentCompiler = NULL;
- mVertexCompiler = NULL;
-
- ShFinalize();
+ return mShader->getUniforms();
}
-void Shader::parseVaryings()
+const std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() const
{
- if (mHlsl)
- {
- const char *input = strstr(mHlsl, "// Varyings") + 12;
-
- while(true)
- {
- char varyingType[256];
- char varyingName[256];
-
- int matches = sscanf(input, "static %255s %255s", varyingType, varyingName);
-
- if (matches != 2)
- {
- break;
- }
-
- char *array = strstr(varyingName, "[");
- int size = 1;
-
- if (array)
- {
- size = atoi(array + 1);
- *array = '\0';
- }
-
- mVaryings.push_back(Varying(parseType(varyingType), varyingName, size, array != NULL));
-
- input = strstr(input, ";") + 2;
- }
-
- mUsesMultipleRenderTargets = strstr(mHlsl, "GL_USES_MRT") != NULL;
- mUsesFragColor = strstr(mHlsl, "GL_USES_FRAG_COLOR") != NULL;
- mUsesFragData = strstr(mHlsl, "GL_USES_FRAG_DATA") != NULL;
- mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL;
- mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
- mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
- mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
- mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL;
- mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL;
- mUsesDiscardRewriting = strstr(mHlsl, "ANGLE_USES_DISCARD_REWRITING") != NULL;
- }
+ return mShader->getInterfaceBlocks();
}
-void Shader::resetVaryingsRegisterAssignment()
+const std::vector<sh::Attribute> &Shader::getActiveAttributes() const
{
- for (VaryingList::iterator var = mVaryings.begin(); var != mVaryings.end(); var++)
- {
- var->reg = -1;
- var->col = -1;
- }
+ return mShader->getActiveAttributes();
}
-// initialize/clean up previous state
-void Shader::uncompile()
+const std::vector<sh::Attribute> &Shader::getActiveOutputVariables() const
{
- // set by compileToHLSL
- delete[] mHlsl;
- mHlsl = NULL;
- delete[] mInfoLog;
- mInfoLog = NULL;
-
- // set by parseVaryings
- mVaryings.clear();
-
- mUsesMultipleRenderTargets = false;
- mUsesFragColor = false;
- mUsesFragData = false;
- mUsesFragCoord = false;
- mUsesFrontFacing = false;
- mUsesPointSize = false;
- mUsesPointCoord = false;
- mUsesDepthRange = false;
- mUsesFragDepth = false;
- mUsesDiscardRewriting = false;
-
- mActiveUniforms.clear();
+ return mShader->getActiveOutputVariables();
}
-void Shader::compileToHLSL(void *compiler)
+std::vector<gl::PackedVarying> &Shader::getVaryings()
{
- // ensure we don't pass a NULL source to the compiler
- const char *source = "\0";
- if (mSource)
- {
- source = mSource;
- }
-
- // ensure the compiler is loaded
- initializeCompiler();
-
- int compileOptions = SH_OBJECT_CODE;
- std::string sourcePath;
- if (perfActive())
- {
- sourcePath = getTempPath();
- writeFile(sourcePath.c_str(), source, strlen(source));
- compileOptions |= SH_LINE_DIRECTIVES;
- }
-
- int result;
- if (sourcePath.empty())
- {
- result = ShCompile(compiler, &source, 1, compileOptions);
- }
- else
- {
- const char* sourceStrings[2] =
- {
- sourcePath.c_str(),
- source
- };
-
- result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH);
- }
-
- if (result)
- {
- size_t objCodeLen = 0;
- ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
- mHlsl = new char[objCodeLen];
- ShGetObjectCode(compiler, mHlsl);
-
- void *activeUniforms;
- ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
- mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms;
- }
- else
- {
- size_t infoLogLen = 0;
- ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
- mInfoLog = new char[infoLogLen];
- ShGetInfoLog(compiler, mInfoLog);
-
- TRACE("\n%s", mInfoLog);
- }
+ return mShader->getVaryings();
}
-GLenum Shader::parseType(const std::string &type)
+std::vector<sh::Uniform> &Shader::getUniforms()
{
- if (type == "float")
- {
- return GL_FLOAT;
- }
- else if (type == "float2")
- {
- return GL_FLOAT_VEC2;
- }
- else if (type == "float3")
- {
- return GL_FLOAT_VEC3;
- }
- else if (type == "float4")
- {
- return GL_FLOAT_VEC4;
- }
- else if (type == "float2x2")
- {
- return GL_FLOAT_MAT2;
- }
- else if (type == "float3x3")
- {
- return GL_FLOAT_MAT3;
- }
- else if (type == "float4x4")
- {
- return GL_FLOAT_MAT4;
- }
- else UNREACHABLE();
-
- return GL_NONE;
-}
-
-// true if varying x has a higher priority in packing than y
-bool Shader::compareVarying(const Varying &x, const Varying &y)
-{
- if(x.type == y.type)
- {
- return x.size > y.size;
- }
-
- switch (x.type)
- {
- case GL_FLOAT_MAT4: return true;
- case GL_FLOAT_MAT2:
- switch(y.type)
- {
- case GL_FLOAT_MAT4: return false;
- case GL_FLOAT_MAT2: return true;
- case GL_FLOAT_VEC4: return true;
- case GL_FLOAT_MAT3: return true;
- case GL_FLOAT_VEC3: return true;
- case GL_FLOAT_VEC2: return true;
- case GL_FLOAT: return true;
- default: UNREACHABLE();
- }
- break;
- case GL_FLOAT_VEC4:
- switch(y.type)
- {
- case GL_FLOAT_MAT4: return false;
- case GL_FLOAT_MAT2: return false;
- case GL_FLOAT_VEC4: return true;
- case GL_FLOAT_MAT3: return true;
- case GL_FLOAT_VEC3: return true;
- case GL_FLOAT_VEC2: return true;
- case GL_FLOAT: return true;
- default: UNREACHABLE();
- }
- break;
- case GL_FLOAT_MAT3:
- switch(y.type)
- {
- case GL_FLOAT_MAT4: return false;
- case GL_FLOAT_MAT2: return false;
- case GL_FLOAT_VEC4: return false;
- case GL_FLOAT_MAT3: return true;
- case GL_FLOAT_VEC3: return true;
- case GL_FLOAT_VEC2: return true;
- case GL_FLOAT: return true;
- default: UNREACHABLE();
- }
- break;
- case GL_FLOAT_VEC3:
- switch(y.type)
- {
- case GL_FLOAT_MAT4: return false;
- case GL_FLOAT_MAT2: return false;
- case GL_FLOAT_VEC4: return false;
- case GL_FLOAT_MAT3: return false;
- case GL_FLOAT_VEC3: return true;
- case GL_FLOAT_VEC2: return true;
- case GL_FLOAT: return true;
- default: UNREACHABLE();
- }
- break;
- case GL_FLOAT_VEC2:
- switch(y.type)
- {
- case GL_FLOAT_MAT4: return false;
- case GL_FLOAT_MAT2: return false;
- case GL_FLOAT_VEC4: return false;
- case GL_FLOAT_MAT3: return false;
- case GL_FLOAT_VEC3: return false;
- case GL_FLOAT_VEC2: return true;
- case GL_FLOAT: return true;
- default: UNREACHABLE();
- }
- break;
- case GL_FLOAT: return false;
- default: UNREACHABLE();
- }
-
- return false;
-}
-
-VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
- : Shader(manager, renderer, handle)
-{
-}
-
-VertexShader::~VertexShader()
-{
-}
-
-GLenum VertexShader::getType()
-{
- return GL_VERTEX_SHADER;
+ return mShader->getUniforms();
}
-void VertexShader::uncompile()
+std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks()
{
- Shader::uncompile();
-
- // set by ParseAttributes
- mAttributes.clear();
+ return mShader->getInterfaceBlocks();
}
-void VertexShader::compile()
+std::vector<sh::Attribute> &Shader::getActiveAttributes()
{
- uncompile();
-
- compileToHLSL(mVertexCompiler);
- parseAttributes();
- parseVaryings();
+ return mShader->getActiveAttributes();
}
-int VertexShader::getSemanticIndex(const std::string &attributeName)
+std::vector<sh::Attribute> &Shader::getActiveOutputVariables()
{
- if (!attributeName.empty())
- {
- int semanticIndex = 0;
- for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++)
- {
- if (attribute->name == attributeName)
- {
- return semanticIndex;
- }
-
- semanticIndex += VariableRowCount(attribute->type);
- }
- }
-
- return -1;
+ return mShader->getActiveOutputVariables();
}
-void VertexShader::parseAttributes()
-{
- const char *hlsl = getHLSL();
- if (hlsl)
- {
- const char *input = strstr(hlsl, "// Attributes") + 14;
-
- while(true)
- {
- char attributeType[256];
- char attributeName[256];
-
- int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName);
-
- if (matches != 2)
- {
- break;
- }
-
- mAttributes.push_back(Attribute(parseType(attributeType), attributeName));
-
- input = strstr(input, ";") + 2;
- }
- }
-}
-
-FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
- : Shader(manager, renderer, handle)
-{
-}
-
-FragmentShader::~FragmentShader()
-{
-}
-
-GLenum FragmentShader::getType()
-{
- return GL_FRAGMENT_SHADER;
-}
-
-void FragmentShader::compile()
-{
- uncompile();
-
- compileToHLSL(mFragmentCompiler);
- parseVaryings();
- mVaryings.sort(compareVarying);
-}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h
index 2015addd11..7ba3bd165c 100644
--- a/src/3rdparty/angle/src/libGLESv2/Shader.h
+++ b/src/3rdparty/angle/src/libGLESv2/Shader.h
@@ -12,68 +12,70 @@
#ifndef LIBGLESV2_SHADER_H_
#define LIBGLESV2_SHADER_H_
-#define GL_APICALL
-#include <GLES2/gl2.h>
+
#include <string>
#include <list>
#include <vector>
-#include "compiler/translator/Uniform.h"
+#include "angle_gl.h"
+#include <GLSLANG/ShaderLang.h>
+
#include "common/angleutils.h"
+#include "libGLESv2/angletypes.h"
namespace rx
{
-class Renderer;
+class ShaderImpl;
}
namespace gl
{
class ResourceManager;
-struct Varying
+struct PackedVarying : public sh::Varying
{
- Varying(GLenum type, const std::string &name, int size, bool array)
- : type(type), name(name), size(size), array(array), reg(-1), col(-1)
- {
- }
+ unsigned int registerIndex; // Assigned during link
+ unsigned int columnIndex; // Assigned during link, defaults to 0
- GLenum type;
- std::string name;
- int size; // Number of 'type' elements
- bool array;
+ PackedVarying(const sh::Varying &varying)
+ : sh::Varying(varying),
+ registerIndex(GL_INVALID_INDEX),
+ columnIndex(0)
+ {}
- int reg; // First varying register, assigned during link
- int col; // First register element, assigned during link
-};
+ bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; }
+ bool isBuiltIn() const { return name.compare(0, 3, "gl_") == 0; }
-typedef std::list<Varying> VaryingList;
+ void resetRegisterAssignment()
+ {
+ registerIndex = GL_INVALID_INDEX;
+ }
+};
class Shader
{
- friend class ProgramBinary;
-
public:
- Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle);
+ Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle);
virtual ~Shader();
- virtual GLenum getType() = 0;
+ GLenum getType() const { return mType; }
GLuint getHandle() const;
+ rx::ShaderImpl *getImplementation() { return mShader; }
+ const rx::ShaderImpl *getImplementation() const { return mShader; }
+
void deleteSource();
- void setSource(GLsizei count, const char **string, const GLint *length);
+ void setSource(GLsizei count, const char *const *string, const GLint *length);
int getInfoLogLength() const;
- void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
+ void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
int getSourceLength() const;
- void getSource(GLsizei bufSize, GLsizei *length, char *buffer);
+ void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
int getTranslatedSourceLength() const;
- void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer);
- const sh::ActiveUniforms &getUniforms();
+ void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
- virtual void compile() = 0;
- virtual void uncompile();
- bool isCompiled();
- const char *getHLSL();
+ void compile();
+ bool isCompiled() const { return mCompiled; }
void addRef();
void release();
@@ -81,105 +83,34 @@ class Shader
bool isFlaggedForDeletion() const;
void flagForDeletion();
- static void releaseCompiler();
-
- protected:
- void parseVaryings();
- void resetVaryingsRegisterAssignment();
-
- void compileToHLSL(void *compiler);
+ const std::vector<gl::PackedVarying> &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::Attribute> &getActiveOutputVariables() const;
- void getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer);
-
- static GLenum parseType(const std::string &type);
- static bool compareVarying(const Varying &x, const Varying &y);
-
- const rx::Renderer *const mRenderer;
-
- VaryingList mVaryings;
-
- bool mUsesMultipleRenderTargets;
- bool mUsesFragColor;
- bool mUsesFragData;
- bool mUsesFragCoord;
- bool mUsesFrontFacing;
- bool mUsesPointSize;
- bool mUsesPointCoord;
- bool mUsesDepthRange;
- bool mUsesFragDepth;
- bool mUsesDiscardRewriting;
-
- static void *mFragmentCompiler;
- static void *mVertexCompiler;
+ std::vector<gl::PackedVarying> &getVaryings();
+ std::vector<sh::Uniform> &getUniforms();
+ std::vector<sh::InterfaceBlock> &getInterfaceBlocks();
+ std::vector<sh::Attribute> &getActiveAttributes();
+ std::vector<sh::Attribute> &getActiveOutputVariables();
private:
DISALLOW_COPY_AND_ASSIGN(Shader);
- void initializeCompiler();
+ static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer);
+ rx::ShaderImpl *mShader;
const GLuint mHandle;
+ const GLenum mType;
+ std::string mSource;
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
-
- char *mSource;
- char *mHlsl;
- char *mInfoLog;
- sh::ActiveUniforms mActiveUniforms;
+ bool mCompiled; // Indicates if this shader has been successfully compiled
ResourceManager *mResourceManager;
};
-struct Attribute
-{
- Attribute() : type(GL_NONE), name("")
- {
- }
-
- Attribute(GLenum type, const std::string &name) : type(type), name(name)
- {
- }
-
- GLenum type;
- std::string name;
-};
-
-typedef std::vector<Attribute> AttributeArray;
-
-class VertexShader : public Shader
-{
- friend class ProgramBinary;
-
- public:
- VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle);
-
- ~VertexShader();
-
- virtual GLenum getType();
- virtual void compile();
- virtual void uncompile();
- int getSemanticIndex(const std::string &attributeName);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(VertexShader);
-
- void parseAttributes();
-
- AttributeArray mAttributes;
-};
-
-class FragmentShader : public Shader
-{
- public:
- FragmentShader(ResourceManager *manager,const rx::Renderer *renderer, GLuint handle);
-
- ~FragmentShader();
-
- virtual GLenum getType();
- virtual void compile();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FragmentShader);
-};
}
#endif // LIBGLESV2_SHADER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libGLESv2/State.cpp
new file mode 100644
index 0000000000..3c03b90e56
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/State.cpp
@@ -0,0 +1,1455 @@
+//
+// 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 "libGLESv2/State.h"
+
+#include "libGLESv2/Context.h"
+#include "libGLESv2/Caps.h"
+#include "libGLESv2/VertexArray.h"
+#include "libGLESv2/Query.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
+#include "libGLESv2/renderer/RenderTarget.h"
+#include "libGLESv2/formatutils.h"
+
+namespace gl
+{
+
+State::State()
+{
+}
+
+State::~State()
+{
+ reset();
+}
+
+void State::initialize(const Caps& caps, GLuint clientVersion)
+{
+ mContext = NULL;
+
+ setClearColor(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 = -1;
+ mDepthStencil.stencilWritemask = -1;
+ mDepthStencil.stencilBackFunc = GL_ALWAYS;
+ mDepthStencil.stencilBackMask = -1;
+ mDepthStencil.stencilBackWritemask = -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;
+
+ 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;
+
+ const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+ for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++)
+ {
+ mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
+ }
+
+ mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits);
+ mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits);
+ if (clientVersion >= 3)
+ {
+ // TODO: These could also be enabled via extension
+ mSamplerTextures[GL_TEXTURE_2D_ARRAY].resize(caps.maxCombinedTextureImageUnits);
+ mSamplerTextures[GL_TEXTURE_3D].resize(caps.maxCombinedTextureImageUnits);
+ }
+
+ mSamplers.resize(caps.maxCombinedTextureImageUnits);
+
+ mActiveQueries[GL_ANY_SAMPLES_PASSED].set(NULL);
+ mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL);
+ mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(NULL);
+
+ mCurrentProgramId = 0;
+ mCurrentProgramBinary.set(NULL);
+
+ mReadFramebuffer = NULL;
+ mDrawFramebuffer = NULL;
+}
+
+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);
+ }
+
+ const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+ for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++)
+ {
+ mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
+ }
+
+ mArrayBuffer.set(NULL);
+ mRenderbuffer.set(NULL);
+
+ mTransformFeedback.set(NULL);
+
+ for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++)
+ {
+ i->second.set(NULL);
+ }
+
+ mGenericUniformBuffer.set(NULL);
+ for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++)
+ {
+ mUniformBuffers[i].set(NULL);
+ }
+
+ mGenericTransformFeedbackBuffer.set(NULL);
+ for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
+ {
+ mTransformFeedbackBuffers[i].set(NULL);
+ }
+
+ mCopyReadBuffer.set(NULL);
+ mCopyWriteBuffer.set(NULL);
+
+ mPack.pixelBuffer.set(NULL);
+ mUnpack.pixelBuffer.set(NULL);
+}
+
+const RasterizerState &State::getRasterizerState() const
+{
+ return mRasterizer;
+}
+
+const BlendState &State::getBlendState() const
+{
+ return mBlend;
+}
+
+const DepthStencilState &State::getDepthStencilState() const
+{
+ return mDepthStencil;
+}
+
+void State::setClearColor(float red, float green, float blue, float alpha)
+{
+ mColorClearValue.red = red;
+ mColorClearValue.green = green;
+ mColorClearValue.blue = blue;
+ mColorClearValue.alpha = alpha;
+}
+
+void State::setClearDepth(float depth)
+{
+ mDepthClearValue = depth;
+}
+
+void State::setClearStencil(int stencil)
+{
+ mStencilClearValue = stencil;
+}
+
+ClearParameters State::getClearParameters(GLbitfield mask) const
+{
+ ClearParameters clearParams = { 0 };
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = false;
+ }
+ clearParams.colorFClearValue = mColorClearValue;
+ clearParams.colorClearType = GL_FLOAT;
+ clearParams.colorMaskRed = mBlend.colorMaskRed;
+ clearParams.colorMaskGreen = mBlend.colorMaskGreen;
+ clearParams.colorMaskBlue = mBlend.colorMaskBlue;
+ clearParams.colorMaskAlpha = mBlend.colorMaskAlpha;
+ clearParams.clearDepth = false;
+ clearParams.depthClearValue = mDepthClearValue;
+ clearParams.clearStencil = false;
+ clearParams.stencilClearValue = mStencilClearValue;
+ clearParams.stencilWriteMask = mDepthStencil.stencilWritemask;
+ clearParams.scissorEnabled = mScissorTest;
+ clearParams.scissor = mScissor;
+
+ const Framebuffer *framebufferObject = getDrawFramebuffer();
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ if (framebufferObject->hasEnabledColorAttachment())
+ {
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = true;
+ }
+ }
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT)
+ {
+ if (mDepthStencil.depthMask && framebufferObject->getDepthbuffer() != NULL)
+ {
+ clearParams.clearDepth = true;
+ }
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT)
+ {
+ if (framebufferObject->getStencilbuffer() != NULL)
+ {
+ GLenum stencilActualFormat = framebufferObject->getStencilbuffer()->getActualFormat();
+ if (GetInternalFormatInfo(stencilActualFormat).stencilBits > 0)
+ {
+ clearParams.clearStencil = true;
+ }
+ }
+ }
+
+ return clearParams;
+}
+
+void State::setColorMask(bool red, bool green, bool blue, bool alpha)
+{
+ mBlend.colorMaskRed = red;
+ mBlend.colorMaskGreen = green;
+ mBlend.colorMaskBlue = blue;
+ mBlend.colorMaskAlpha = alpha;
+}
+
+void State::setDepthMask(bool mask)
+{
+ mDepthStencil.depthMask = mask;
+}
+
+bool State::isRasterizerDiscardEnabled() const
+{
+ return mRasterizer.rasterizerDiscard;
+}
+
+void State::setRasterizerDiscard(bool enabled)
+{
+ mRasterizer.rasterizerDiscard = enabled;
+}
+
+bool State::isCullFaceEnabled() const
+{
+ return mRasterizer.cullFace;
+}
+
+void State::setCullFace(bool enabled)
+{
+ mRasterizer.cullFace = enabled;
+}
+
+void State::setCullMode(GLenum mode)
+{
+ mRasterizer.cullMode = mode;
+}
+
+void State::setFrontFace(GLenum front)
+{
+ mRasterizer.frontFace = front;
+}
+
+bool State::isDepthTestEnabled() const
+{
+ return mDepthStencil.depthTest;
+}
+
+void State::setDepthTest(bool enabled)
+{
+ mDepthStencil.depthTest = enabled;
+}
+
+void State::setDepthFunc(GLenum depthFunc)
+{
+ mDepthStencil.depthFunc = depthFunc;
+}
+
+void State::setDepthRange(float zNear, float zFar)
+{
+ mNearZ = zNear;
+ mFarZ = zFar;
+}
+
+void State::getDepthRange(float *zNear, float *zFar) const
+{
+ *zNear = mNearZ;
+ *zFar = mFarZ;
+}
+
+bool State::isBlendEnabled() const
+{
+ return mBlend.blend;
+}
+
+void State::setBlend(bool enabled)
+{
+ mBlend.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;
+}
+
+void State::setBlendColor(float red, float green, float blue, float alpha)
+{
+ mBlendColor.red = red;
+ mBlendColor.green = green;
+ mBlendColor.blue = blue;
+ mBlendColor.alpha = alpha;
+}
+
+void State::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
+{
+ mBlend.blendEquationRGB = rgbEquation;
+ mBlend.blendEquationAlpha = alphaEquation;
+}
+
+const ColorF &State::getBlendColor() const
+{
+ return mBlendColor;
+}
+
+bool State::isStencilTestEnabled() const
+{
+ return mDepthStencil.stencilTest;
+}
+
+void State::setStencilTest(bool enabled)
+{
+ mDepthStencil.stencilTest = enabled;
+}
+
+void State::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
+{
+ mDepthStencil.stencilFunc = stencilFunc;
+ mStencilRef = (stencilRef > 0) ? stencilRef : 0;
+ mDepthStencil.stencilMask = stencilMask;
+}
+
+void State::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
+{
+ mDepthStencil.stencilBackFunc = stencilBackFunc;
+ mStencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
+ mDepthStencil.stencilBackMask = stencilBackMask;
+}
+
+void State::setStencilWritemask(GLuint stencilWritemask)
+{
+ mDepthStencil.stencilWritemask = stencilWritemask;
+}
+
+void State::setStencilBackWritemask(GLuint stencilBackWritemask)
+{
+ mDepthStencil.stencilBackWritemask = stencilBackWritemask;
+}
+
+void State::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
+{
+ mDepthStencil.stencilFail = stencilFail;
+ mDepthStencil.stencilPassDepthFail = stencilPassDepthFail;
+ mDepthStencil.stencilPassDepthPass = stencilPassDepthPass;
+}
+
+void State::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
+{
+ mDepthStencil.stencilBackFail = stencilBackFail;
+ mDepthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail;
+ mDepthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass;
+}
+
+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;
+}
+
+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;
+}
+
+bool State::isSampleAlphaToCoverageEnabled() const
+{
+ return mBlend.sampleAlphaToCoverage;
+}
+
+void State::setSampleAlphaToCoverage(bool enabled)
+{
+ mBlend.sampleAlphaToCoverage = enabled;
+}
+
+bool State::isSampleCoverageEnabled() const
+{
+ return mSampleCoverage;
+}
+
+void State::setSampleCoverage(bool enabled)
+{
+ mSampleCoverage = enabled;
+}
+
+void State::setSampleCoverageParams(GLclampf value, bool invert)
+{
+ mSampleCoverageValue = value;
+ mSampleCoverageInvert = invert;
+}
+
+void State::getSampleCoverageParams(GLclampf *value, bool *invert)
+{
+ ASSERT(value != NULL && invert != NULL);
+
+ *value = mSampleCoverageValue;
+ *invert = mSampleCoverageInvert;
+}
+
+bool State::isScissorTestEnabled() const
+{
+ return mScissorTest;
+}
+
+void State::setScissorTest(bool enabled)
+{
+ mScissorTest = enabled;
+}
+
+void State::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ mScissor.x = x;
+ mScissor.y = y;
+ mScissor.width = width;
+ mScissor.height = height;
+}
+
+const Rectangle &State::getScissor() const
+{
+ return mScissor;
+}
+
+bool State::isDitherEnabled() const
+{
+ return mBlend.dither;
+}
+
+void State::setDither(bool enabled)
+{
+ mBlend.dither = enabled;
+}
+
+void State::setEnableFeature(GLenum feature, bool enabled)
+{
+ switch (feature)
+ {
+ 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: UNIMPLEMENTED(); break;
+ case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break;
+ default: UNREACHABLE();
+ }
+}
+
+bool State::getEnableFeature(GLenum feature)
+{
+ switch (feature)
+ {
+ 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: UNIMPLEMENTED(); return false;
+ case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled();
+ default: UNREACHABLE(); return false;
+ }
+}
+
+void State::setLineWidth(GLfloat width)
+{
+ mLineWidth = width;
+}
+
+void State::setGenerateMipmapHint(GLenum hint)
+{
+ mGenerateMipmapHint = hint;
+}
+
+void State::setFragmentShaderDerivativeHint(GLenum hint)
+{
+ mFragmentShaderDerivativeHint = hint;
+ // TODO: Propagate the hint to shader translator so we can write
+ // ddx, ddx_coarse, or ddx_fine depending on the hint.
+ // Ignore for now. It is valid for implementations to ignore hint.
+}
+
+void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ mViewport.x = x;
+ mViewport.y = y;
+ mViewport.width = width;
+ mViewport.height = height;
+}
+
+const Rectangle &State::getViewport() const
+{
+ return mViewport;
+}
+
+void State::setActiveSampler(unsigned int active)
+{
+ mActiveSampler = active;
+}
+
+unsigned int State::getActiveSampler() const
+{
+ return mActiveSampler;
+}
+
+void State::setSamplerTexture(GLenum type, Texture *texture)
+{
+ mSamplerTextures[type][mActiveSampler].set(texture);
+}
+
+Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const
+{
+ const BindingPointer<Texture>& binding = mSamplerTextures.at(type)[sampler];
+
+ if (binding.id() == 0) // Special case: 0 refers to default textures held by Context
+ {
+ return NULL;
+ }
+
+ return binding.get();
+}
+
+GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const
+{
+ return mSamplerTextures.at(type)[sampler].id();
+}
+
+void State::detachTexture(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 (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++)
+ {
+ TextureBindingVector &textureVector = bindingVec->second;
+ for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
+ {
+ BindingPointer<Texture> &binding = textureVector[textureIdx];
+ if (binding.id() == texture)
+ {
+ binding.set(NULL);
+ }
+ }
+ }
+
+ // [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::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()
+{
+ 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)
+{
+ mReadFramebuffer = framebuffer;
+}
+
+void State::setDrawFramebufferBinding(Framebuffer *framebuffer)
+{
+ mDrawFramebuffer = 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()
+{
+ return mReadFramebuffer;
+}
+
+Framebuffer *State::getDrawFramebuffer()
+{
+ return mDrawFramebuffer;
+}
+
+const Framebuffer *State::getReadFramebuffer() const
+{
+ return mReadFramebuffer;
+}
+
+const Framebuffer *State::getDrawFramebuffer() const
+{
+ return mDrawFramebuffer;
+}
+
+bool State::removeReadFramebufferBinding(GLuint framebuffer)
+{
+ if (mReadFramebuffer->id() == framebuffer)
+ {
+ mReadFramebuffer = NULL;
+ return true;
+ }
+
+ return false;
+}
+
+bool State::removeDrawFramebufferBinding(GLuint framebuffer)
+{
+ if (mDrawFramebuffer->id() == framebuffer)
+ {
+ mDrawFramebuffer = NULL;
+ return true;
+ }
+
+ return false;
+}
+
+void State::setVertexArrayBinding(VertexArray *vertexArray)
+{
+ mVertexArray = vertexArray;
+}
+
+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;
+ return true;
+ }
+
+ return false;
+}
+
+void State::setCurrentProgram(GLuint programId, Program *newProgram)
+{
+ mCurrentProgramId = programId; // set new ID before trying to delete program binary; otherwise it will only be flagged for deletion
+ mCurrentProgramBinary.set(NULL);
+
+ if (newProgram)
+ {
+ newProgram->addRef();
+ mCurrentProgramBinary.set(newProgram->getProgramBinary());
+ }
+}
+
+void State::setCurrentProgramBinary(ProgramBinary *binary)
+{
+ mCurrentProgramBinary.set(binary);
+}
+
+GLuint State::getCurrentProgramId() const
+{
+ return mCurrentProgramId;
+}
+
+ProgramBinary *State::getCurrentProgramBinary() const
+{
+ return mCurrentProgramBinary.get();
+}
+
+void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback)
+{
+ mTransformFeedback.set(transformFeedback);
+}
+
+TransformFeedback *State::getCurrentTransformFeedback() const
+{
+ return mTransformFeedback.get();
+}
+
+void State::detachTransformFeedback(GLuint transformFeedback)
+{
+ if (mTransformFeedback.id() == transformFeedback)
+ {
+ mTransformFeedback.set(NULL);
+ }
+}
+
+bool State::isQueryActive() const
+{
+ for (State::ActiveQueryMap::const_iterator i = mActiveQueries.begin();
+ i != mActiveQueries.end(); i++)
+ {
+ if (i->second.get() != NULL)
+ {
+ 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
+{
+ // All query types should already exist in the activeQueries map
+ ASSERT(mActiveQueries.find(target) != mActiveQueries.end());
+
+ return mActiveQueries.at(target).get();
+}
+
+void State::setArrayBufferBinding(Buffer *buffer)
+{
+ mArrayBuffer.set(buffer);
+}
+
+GLuint State::getArrayBufferId() const
+{
+ return mArrayBuffer.id();
+}
+
+bool State::removeArrayBufferBinding(GLuint buffer)
+{
+ if (mArrayBuffer.id() == buffer)
+ {
+ mArrayBuffer.set(NULL);
+ return true;
+ }
+
+ return false;
+}
+
+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);
+}
+
+GLuint State::getIndexedUniformBufferId(GLuint index) const
+{
+ ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
+
+ return mUniformBuffers[index].id();
+}
+
+Buffer *State::getIndexedUniformBuffer(GLuint index) const
+{
+ ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
+
+ return mUniformBuffers[index].get();
+}
+
+void State::setGenericTransformFeedbackBufferBinding(Buffer *buffer)
+{
+ mGenericTransformFeedbackBuffer.set(buffer);
+}
+
+void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size)
+{
+ mTransformFeedbackBuffers[index].set(buffer, offset, size);
+}
+
+GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const
+{
+ ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
+
+ return mTransformFeedbackBuffers[index].id();
+}
+
+Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const
+{
+ ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
+
+ return mTransformFeedbackBuffers[index].get();
+}
+
+GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const
+{
+ ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
+
+ return mTransformFeedbackBuffers[index].getOffset();
+}
+
+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);
+}
+
+void State::setPixelUnpackBufferBinding(Buffer *buffer)
+{
+ mUnpack.pixelBuffer.set(buffer);
+}
+
+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();
+ case GL_PIXEL_PACK_BUFFER: return mPack.pixelBuffer.get();
+ case GL_PIXEL_UNPACK_BUFFER: return mUnpack.pixelBuffer.get();
+ case GL_TRANSFORM_FEEDBACK_BUFFER: return mGenericTransformFeedbackBuffer.get();
+ case GL_UNIFORM_BUFFER: return mGenericUniformBuffer.get();
+ default: UNREACHABLE(); return NULL;
+ }
+}
+
+void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
+{
+ getVertexArray()->enableAttribute(attribNum, enabled);
+}
+
+void State::setVertexAttribf(GLuint index, const GLfloat values[4])
+{
+ ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
+ mVertexAttribCurrentValues[index].setFloatValues(values);
+}
+
+void State::setVertexAttribu(GLuint index, const GLuint values[4])
+{
+ ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
+ mVertexAttribCurrentValues[index].setUnsignedIntValues(values);
+}
+
+void State::setVertexAttribi(GLuint index, const GLint values[4])
+{
+ ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
+ mVertexAttribCurrentValues[index].setIntValues(values);
+}
+
+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);
+}
+
+const VertexAttribute &State::getVertexAttribState(unsigned int attribNum) const
+{
+ return getVertexArray()->getVertexAttribute(attribNum);
+}
+
+const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const
+{
+ ASSERT(attribNum < MAX_VERTEX_ATTRIBS);
+ return mVertexAttribCurrentValues[attribNum];
+}
+
+const VertexAttribCurrentValueData *State::getVertexAttribCurrentValues() const
+{
+ return mVertexAttribCurrentValues;
+}
+
+const void *State::getVertexAttribPointer(unsigned int attribNum) const
+{
+ return getVertexArray()->getVertexAttribute(attribNum).pointer;
+}
+
+void State::setPackAlignment(GLint alignment)
+{
+ mPack.alignment = alignment;
+}
+
+GLint State::getPackAlignment() const
+{
+ return mPack.alignment;
+}
+
+void State::setPackReverseRowOrder(bool reverseRowOrder)
+{
+ mPack.reverseRowOrder = reverseRowOrder;
+}
+
+bool State::getPackReverseRowOrder() const
+{
+ return mPack.reverseRowOrder;
+}
+
+const PixelPackState &State::getPackState() const
+{
+ return mPack;
+}
+
+void State::setUnpackAlignment(GLint alignment)
+{
+ mUnpack.alignment = alignment;
+}
+
+GLint State::getUnpackAlignment() const
+{
+ return mUnpack.alignment;
+}
+
+const PixelUnpackState &State::getUnpackState() const
+{
+ return mUnpack;
+}
+
+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()->isStarted(); break;
+ case GL_TRANSFORM_FEEDBACK_PAUSED: *params = getCurrentTransformFeedback()->isPaused(); 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;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void State::getIntegerv(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 < mContext->getCaps().maxDrawBuffers);
+ 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()->getElementArrayBufferId(); 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 = mCurrentProgramId; break;
+ case GL_PACK_ALIGNMENT: *params = mPack.alignment; break;
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mPack.reverseRowOrder; break;
+ case GL_UNPACK_ALIGNMENT: *params = mUnpack.alignment; break;
+ case GL_GENERATE_MIPMAP_HINT: *params = mGenerateMipmapHint; break;
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mFragmentShaderDerivativeHint; break;
+ case GL_ACTIVE_TEXTURE: *params = (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_SAMPLE_BUFFERS:
+ case GL_SAMPLES:
+ {
+ gl::Framebuffer *framebuffer = mDrawFramebuffer;
+ if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
+ {
+ switch (pname)
+ {
+ case GL_SAMPLE_BUFFERS:
+ if (framebuffer->getSamples() != 0)
+ {
+ *params = 1;
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+ case GL_SAMPLES:
+ *params = framebuffer->getSamples();
+ 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();
+ 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:
+ {
+ gl::Framebuffer *framebuffer = getDrawFramebuffer();
+ gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer();
+
+ if (depthbuffer)
+ {
+ *params = depthbuffer->getDepthSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ break;
+ case GL_STENCIL_BITS:
+ {
+ gl::Framebuffer *framebuffer = getDrawFramebuffer();
+ gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer();
+
+ if (stencilbuffer)
+ {
+ *params = stencilbuffer->getStencilSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
+ *params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id();
+ break;
+ case GL_TEXTURE_BINDING_CUBE_MAP:
+ ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
+ *params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id();
+ break;
+ case GL_TEXTURE_BINDING_3D:
+ ASSERT(mActiveSampler <mContext->getCaps().maxCombinedTextureImageUnits);
+ *params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id();
+ break;
+ case GL_TEXTURE_BINDING_2D_ARRAY:
+ ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
+ *params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id();
+ break;
+ case GL_UNIFORM_BUFFER_BINDING:
+ *params = mGenericUniformBuffer.id();
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ *params = mGenericTransformFeedbackBuffer.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;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
+{
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS)
+ {
+ *data = mTransformFeedbackBuffers[index].id();
+ }
+ break;
+ case GL_UNIFORM_BUFFER_BINDING:
+ if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS)
+ {
+ *data = mUniformBuffers[index].id();
+ }
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
+{
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS)
+ {
+ *data = mTransformFeedbackBuffers[index].getOffset();
+ }
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS)
+ {
+ *data = mTransformFeedbackBuffers[index].getSize();
+ }
+ break;
+ case GL_UNIFORM_BUFFER_START:
+ if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS)
+ {
+ *data = mUniformBuffers[index].getOffset();
+ }
+ break;
+ case GL_UNIFORM_BUFFER_SIZE:
+ if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS)
+ {
+ *data = mUniformBuffers[index].getSize();
+ }
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool State::hasMappedBuffer(GLenum target) const
+{
+ if (target == GL_ARRAY_BUFFER)
+ {
+ for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++)
+ {
+ const gl::VertexAttribute &vertexAttrib = getVertexAttribState(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());
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/State.h b/src/3rdparty/angle/src/libGLESv2/State.h
new file mode 100644
index 0000000000..5f0433136c
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/State.h
@@ -0,0 +1,319 @@
+//
+// 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 LIBGLESV2_STATE_H_
+#define LIBGLESV2_STATE_H_
+
+#include "common/angleutils.h"
+#include "common/RefCountObject.h"
+#include "libGLESv2/angletypes.h"
+#include "libGLESv2/VertexAttribute.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/TransformFeedback.h"
+#include "libGLESv2/Program.h"
+#include "libGLESv2/Sampler.h"
+
+namespace gl
+{
+class Query;
+class VertexArray;
+class Context;
+struct Caps;
+
+class State
+{
+ public:
+ State();
+ ~State();
+
+ void initialize(const Caps& caps, GLuint clientVersion);
+ void reset();
+
+ void setContext(Context *context) { mContext = context; }
+
+ // State chunk getters
+ const RasterizerState &getRasterizerState() const;
+ const BlendState &getBlendState() const;
+ const DepthStencilState &getDepthStencilState() const;
+
+ // Clear behavior setters & state parameter block generation function
+ void setClearColor(float red, float green, float blue, float alpha);
+ void setClearDepth(float depth);
+ void setClearStencil(int stencil);
+ ClearParameters getClearParameters(GLbitfield mask) const;
+
+ // 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);
+
+ // 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);
+ void getDepthRange(float *zNear, float *zFar) 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);
+ void getSampleCoverageParams(GLclampf *value, bool *invert);
+
+ // 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);
+
+ // Line width state setter
+ void setLineWidth(GLfloat width);
+
+ // Hint setters
+ void setGenerateMipmapHint(GLenum hint);
+ void setFragmentShaderDerivativeHint(GLenum hint);
+
+ // 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 *getSamplerTexture(unsigned int sampler, GLenum type) const;
+ GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const;
+ void detachTexture(GLuint texture);
+
+ // 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();
+ void detachRenderbuffer(GLuint renderbuffer);
+
+ // Framebuffer binding manipulation
+ void setReadFramebufferBinding(Framebuffer *framebuffer);
+ void setDrawFramebufferBinding(Framebuffer *framebuffer);
+ Framebuffer *getTargetFramebuffer(GLenum target) const;
+ Framebuffer *getReadFramebuffer();
+ Framebuffer *getDrawFramebuffer();
+ const Framebuffer *getReadFramebuffer() const;
+ 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 setCurrentProgram(GLuint programId, Program *newProgram);
+ void setCurrentProgramBinary(ProgramBinary *binary);
+ GLuint getCurrentProgramId() const;
+ ProgramBinary *getCurrentProgramBinary() const;
+
+ // Transform feedback object (not buffer) binding manipulation
+ void setTransformFeedbackBinding(TransformFeedback *transformFeedback);
+ TransformFeedback *getCurrentTransformFeedback() const;
+ void detachTransformFeedback(GLuint transformFeedback);
+
+ // Query binding manipulation
+ bool isQueryActive() 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;
+ bool removeArrayBufferBinding(GLuint buffer);
+
+ // GL_UNIFORM_BUFFER - Both indexed and generic targets
+ void setGenericUniformBufferBinding(Buffer *buffer);
+ void setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size);
+ GLuint getIndexedUniformBufferId(GLuint index) const;
+ Buffer *getIndexedUniformBuffer(GLuint index) const;
+
+ // GL_TRANSFORM_FEEDBACK_BUFFER - Both indexed and generic targets
+ void setGenericTransformFeedbackBufferBinding(Buffer *buffer);
+ void setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size);
+ GLuint getIndexedTransformFeedbackBufferId(GLuint index) const;
+ Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const;
+ GLuint getIndexedTransformFeedbackBufferOffset(GLuint 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;
+
+ // 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);
+ const VertexAttribute &getVertexAttribState(unsigned int attribNum) const;
+ const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const;
+ const VertexAttribCurrentValueData *getVertexAttribCurrentValues() 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;
+ const PixelPackState &getPackState() const;
+
+ // Pixel unpack state manipulation
+ void setUnpackAlignment(GLint alignment);
+ GLint getUnpackAlignment() const;
+ const PixelUnpackState &getUnpackState() const;
+
+ // State query functions
+ void getBooleanv(GLenum pname, GLboolean *params);
+ void getFloatv(GLenum pname, GLfloat *params);
+ void getIntegerv(GLenum pname, GLint *params);
+ bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data);
+ bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data);
+
+ bool hasMappedBuffer(GLenum target) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(State);
+
+ Context *mContext;
+
+ 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;
+
+ Rectangle mViewport;
+ float mNearZ;
+ float mFarZ;
+
+ BindingPointer<Buffer> mArrayBuffer;
+ Framebuffer *mReadFramebuffer;
+ Framebuffer *mDrawFramebuffer;
+ BindingPointer<Renderbuffer> mRenderbuffer;
+ GLuint mCurrentProgramId;
+ BindingPointer<ProgramBinary> mCurrentProgramBinary;
+
+ VertexAttribCurrentValueData mVertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // 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;
+ OffsetBindingPointer<Buffer> mUniformBuffers[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
+
+ BindingPointer<TransformFeedback> mTransformFeedback;
+ BindingPointer<Buffer> mGenericTransformFeedbackBuffer;
+ OffsetBindingPointer<Buffer> mTransformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
+
+ BindingPointer<Buffer> mCopyReadBuffer;
+ BindingPointer<Buffer> mCopyWriteBuffer;
+
+ PixelUnpackState mUnpack;
+ PixelPackState mPack;
+};
+
+}
+
+#endif // LIBGLESV2_STATE_H_
+
diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp
index 3257d05dd4..3ec492de07 100644
--- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp
@@ -1,6 +1,5 @@
-#include "precompiled.h"
//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -10,350 +9,195 @@
// functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
#include "libGLESv2/Texture.h"
-
#include "libGLESv2/main.h"
-#include "libGLESv2/mathutil.h"
-#include "libGLESv2/utilities.h"
-#if defined(ANGLE_ENABLE_D3D9)
-# include "libGLESv2/renderer/d3d9/Blit.h"
-#else
-# define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN
-#endif
+#include "libGLESv2/Context.h"
+#include "libGLESv2/formatutils.h"
+#include "libGLESv2/ImageIndex.h"
#include "libGLESv2/Renderbuffer.h"
#include "libGLESv2/renderer/Image.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/TextureStorage.h"
-#include "libEGL/Surface.h"
-
-namespace gl
-{
+#include "libGLESv2/renderer/d3d/TextureStorage.h"
-Texture::Texture(rx::Renderer *renderer, GLuint id) : RefCountObject(id)
-{
- mRenderer = renderer;
+#include "libEGL/Surface.h"
- mSamplerState.minFilter = GL_NEAREST_MIPMAP_LINEAR;
- mSamplerState.magFilter = GL_LINEAR;
- mSamplerState.wrapS = GL_REPEAT;
- mSamplerState.wrapT = GL_REPEAT;
- mSamplerState.maxAnisotropy = 1.0f;
- mSamplerState.lodOffset = 0;
- mUsage = GL_NONE;
-
- mDirtyImages = true;
+#include "common/mathutil.h"
+#include "common/utilities.h"
- mImmutable = false;
-}
-
-Texture::~Texture()
+namespace gl
{
-}
-// Returns true on successful filter state update (valid enum parameter)
-bool Texture::setMinFilter(GLenum filter)
+bool IsMipmapFiltered(const gl::SamplerState &samplerState)
{
- switch (filter)
+ 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:
- mSamplerState.minFilter = filter;
return true;
- default:
+ default: UNREACHABLE();
return false;
}
}
-// Returns true on successful filter state update (valid enum parameter)
-bool Texture::setMagFilter(GLenum filter)
+bool IsPointSampled(const gl::SamplerState &samplerState)
{
- switch (filter)
- {
- case GL_NEAREST:
- case GL_LINEAR:
- mSamplerState.magFilter = filter;
- return true;
- default:
- return false;
- }
+ return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
}
-// Returns true on successful wrap state update (valid enum parameter)
-bool Texture::setWrapS(GLenum wrap)
+Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
+ : RefCountObject(id),
+ mTexture(impl),
+ mUsage(GL_NONE),
+ mImmutable(false),
+ mTarget(target)
{
- switch (wrap)
- {
- case GL_REPEAT:
- case GL_CLAMP_TO_EDGE:
- case GL_MIRRORED_REPEAT:
- mSamplerState.wrapS = wrap;
- return true;
- default:
- return false;
- }
}
-// Returns true on successful wrap state update (valid enum parameter)
-bool Texture::setWrapT(GLenum wrap)
+Texture::~Texture()
{
- switch (wrap)
- {
- case GL_REPEAT:
- case GL_CLAMP_TO_EDGE:
- case GL_MIRRORED_REPEAT:
- mSamplerState.wrapT = wrap;
- return true;
- default:
- return false;
- }
+ SafeDelete(mTexture);
}
-// Returns true on successful max anisotropy update (valid anisotropy value)
-bool Texture::setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy)
+GLenum Texture::getTarget() const
{
- textureMaxAnisotropy = std::min(textureMaxAnisotropy, contextMaxAnisotropy);
- if (textureMaxAnisotropy < 1.0f)
- {
- return false;
- }
-
- mSamplerState.maxAnisotropy = textureMaxAnisotropy;
-
- return true;
+ return mTarget;
}
-// Returns true on successful usage state update (valid enum parameter)
-bool Texture::setUsage(GLenum usage)
+void Texture::setUsage(GLenum usage)
{
- switch (usage)
- {
- case GL_NONE:
- case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
- mUsage = usage;
- return true;
- default:
- return false;
- }
+ mUsage = usage;
+ getImplementation()->setUsage(usage);
}
-GLenum Texture::getMinFilter() const
+void Texture::getSamplerStateWithNativeOffset(SamplerState *sampler)
{
- return mSamplerState.minFilter;
-}
+ *sampler = mSamplerState;
-GLenum Texture::getMagFilter() const
-{
- return mSamplerState.magFilter;
+ // Offset the effective base level by the texture storage's top level
+ rx::TextureStorage *texture = getNativeTexture();
+ int topLevel = texture ? texture->getTopLevel() : 0;
+ sampler->baseLevel = topLevel + mSamplerState.baseLevel;
}
-GLenum Texture::getWrapS() const
+GLenum Texture::getUsage() const
{
- return mSamplerState.wrapS;
+ return mUsage;
}
-GLenum Texture::getWrapT() const
+GLint Texture::getBaseLevelWidth() const
{
- return mSamplerState.wrapT;
+ const rx::Image *baseImage = getBaseLevelImage();
+ return (baseImage ? baseImage->getWidth() : 0);
}
-float Texture::getMaxAnisotropy() const
+GLint Texture::getBaseLevelHeight() const
{
- return mSamplerState.maxAnisotropy;
+ const rx::Image *baseImage = getBaseLevelImage();
+ return (baseImage ? baseImage->getHeight() : 0);
}
-int Texture::getLodOffset()
+GLint Texture::getBaseLevelDepth() const
{
- rx::TextureStorageInterface *texture = getStorage(false);
- return texture ? texture->getLodOffset() : 0;
+ const rx::Image *baseImage = getBaseLevelImage();
+ return (baseImage ? baseImage->getDepth() : 0);
}
-void Texture::getSamplerState(SamplerState *sampler)
+// 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 Texture::getBaseLevelInternalFormat() const
{
- *sampler = mSamplerState;
- sampler->lodOffset = getLodOffset();
+ const rx::Image *baseImage = getBaseLevelImage();
+ return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
}
-GLenum Texture::getUsage() const
+GLsizei Texture::getWidth(const ImageIndex &index) const
{
- return mUsage;
+ rx::Image *image = mTexture->getImage(index);
+ return image->getWidth();
}
-bool Texture::isMipmapFiltered() const
+GLsizei Texture::getHeight(const ImageIndex &index) const
{
- switch (mSamplerState.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;
- }
+ rx::Image *image = mTexture->getImage(index);
+ return image->getHeight();
}
-void Texture::setImage(GLint unpackAlignment, const void *pixels, rx::Image *image)
+GLenum Texture::getInternalFormat(const ImageIndex &index) const
{
- if (pixels != NULL)
- {
- image->loadData(0, 0, image->getWidth(), image->getHeight(), unpackAlignment, pixels);
- mDirtyImages = true;
- }
+ rx::Image *image = mTexture->getImage(index);
+ return image->getInternalFormat();
}
-void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image)
+GLenum Texture::getActualFormat(const ImageIndex &index) const
{
- if (pixels != NULL)
- {
- image->loadCompressedData(0, 0, image->getWidth(), image->getHeight(), pixels);
- mDirtyImages = true;
- }
+ rx::Image *image = mTexture->getImage(index);
+ return image->getActualFormat();
}
-bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image)
+rx::TextureStorage *Texture::getNativeTexture()
{
- if (pixels != NULL)
- {
- image->loadData(xoffset, yoffset, width, height, unpackAlignment, pixels);
- mDirtyImages = true;
- }
-
- return true;
+ return getImplementation()->getNativeTexture();
}
-bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image)
+void Texture::generateMipmaps()
{
- if (pixels != NULL)
- {
- image->loadCompressedData(xoffset, yoffset, width, height, pixels);
- mDirtyImages = true;
- }
-
- return true;
+ getImplementation()->generateMipmaps();
}
-rx::TextureStorageInterface *Texture::getNativeTexture()
+void Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
{
- // ensure the underlying texture is created
-
- rx::TextureStorageInterface *storage = getStorage(false);
- if (storage)
- {
- updateTexture();
- }
-
- return storage;
-}
-
-bool Texture::hasDirtyImages() const
-{
- return mDirtyImages;
-}
-
-void Texture::resetDirty()
-{
- mDirtyImages = false;
+ getImplementation()->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
}
unsigned int Texture::getTextureSerial()
{
- rx::TextureStorageInterface *texture = getStorage(false);
+ rx::TextureStorage *texture = getNativeTexture();
return texture ? texture->getTextureSerial() : 0;
}
-unsigned int Texture::getRenderTargetSerial(GLenum target)
+bool Texture::isImmutable() const
{
- rx::TextureStorageInterface *texture = getStorage(true);
- return texture ? texture->getRenderTargetSerial(target) : 0;
+ return mImmutable;
}
-bool Texture::isImmutable() const
+int Texture::immutableLevelCount()
{
- return mImmutable;
+ return (mImmutable ? getNativeTexture()->getLevelCount() : 0);
}
-GLint Texture::creationLevels(GLsizei width, GLsizei height) const
+int Texture::mipLevels() const
{
- if ((isPow2(width) && isPow2(height)) || mRenderer->getNonPower2TextureSupport())
- {
- return 0; // Maximum number of levels
- }
- else
- {
- // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
- return 1;
- }
+ return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
}
-GLint Texture::creationLevels(GLsizei size) const
+const rx::Image *Texture::getBaseLevelImage() const
{
- return creationLevels(size, size);
+ return (getImplementation()->getLayerCount(0) > 0 ? getImplementation()->getImage(0, 0) : NULL);
}
-Texture2D::Texture2D(rx::Renderer *renderer, GLuint id) : Texture(renderer, id)
+Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id)
+ : Texture(impl, id, GL_TEXTURE_2D)
{
- mTexStorage = NULL;
mSurface = NULL;
- mColorbufferProxy = NULL;
- mProxyRefs = 0;
-
- for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
- {
- mImageArray[i] = renderer->createImage();
- }
}
Texture2D::~Texture2D()
{
- mColorbufferProxy = NULL;
-
- delete mTexStorage;
- mTexStorage = NULL;
-
if (mSurface)
{
mSurface->setBoundTexture(NULL);
mSurface = NULL;
}
-
- for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
- {
- delete mImageArray[i];
- }
-}
-
-// We need to maintain a count of references to renderbuffers acting as
-// proxies for this texture, so that we do not attempt to use a pointer
-// to a renderbuffer proxy which has been deleted.
-void Texture2D::addProxyRef(const Renderbuffer *proxy)
-{
- mProxyRefs++;
-}
-
-void Texture2D::releaseProxy(const Renderbuffer *proxy)
-{
- if (mProxyRefs > 0)
- mProxyRefs--;
-
- if (mProxyRefs == 0)
- mColorbufferProxy = NULL;
-}
-
-GLenum Texture2D::getTarget() const
-{
- return GL_TEXTURE_2D;
}
GLsizei Texture2D::getWidth(GLint level) const
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mImageArray[level]->getWidth();
+ return mTexture->getImage(level, 0)->getWidth();
else
return 0;
}
@@ -361,7 +205,7 @@ GLsizei Texture2D::getWidth(GLint level) const
GLsizei Texture2D::getHeight(GLint level) const
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mImageArray[level]->getHeight();
+ return mTexture->getImage(level, 0)->getHeight();
else
return 0;
}
@@ -369,7 +213,7 @@ GLsizei Texture2D::getHeight(GLint level) const
GLenum Texture2D::getInternalFormat(GLint level) const
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mImageArray[level]->getInternalFormat();
+ return mTexture->getImage(level, 0)->getInternalFormat();
else
return GL_NONE;
}
@@ -377,63 +221,24 @@ GLenum Texture2D::getInternalFormat(GLint level) const
GLenum Texture2D::getActualFormat(GLint level) const
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mImageArray[level]->getActualFormat();
+ return mTexture->getImage(level, 0)->getActualFormat();
else
- return D3DFMT_UNKNOWN;
+ return GL_NONE;
}
-void Texture2D::redefineImage(GLint level, GLint internalformat, GLsizei width, GLsizei height)
+void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
releaseTexImage();
- // If there currently is a corresponding storage texture image, it has these parameters
- const int storageWidth = std::max(1, mImageArray[0]->getWidth() >> level);
- const int storageHeight = std::max(1, mImageArray[0]->getHeight() >> level);
- const int storageFormat = mImageArray[0]->getInternalFormat();
-
- mImageArray[level]->redefine(mRenderer, internalformat, width, height, false);
-
- if (mTexStorage)
- {
- const int storageLevels = mTexStorage->levelCount();
-
- if ((level >= storageLevels && storageLevels != 0) ||
- width != storageWidth ||
- height != storageHeight ||
- internalformat != storageFormat) // Discard mismatched storage
- {
- for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
- {
- mImageArray[i]->markDirty();
- }
-
- delete mTexStorage;
- mTexStorage = NULL;
- mDirtyImages = true;
- }
- }
-}
-
-void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
-{
- GLint internalformat = ConvertSizedInternalFormat(format, type);
- redefineImage(level, internalformat, width, height);
-
- Texture::setImage(unpackAlignment, pixels, mImageArray[level]);
+ mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels);
}
void Texture2D::bindTexImage(egl::Surface *surface)
{
releaseTexImage();
- GLint internalformat = surface->getFormat();
-
- mImageArray[0]->redefine(mRenderer, internalformat, surface->getWidth(), surface->getHeight(), true);
+ mTexture->bindTexImage(surface);
- delete mTexStorage;
- mTexStorage = new rx::TextureStorageInterface2D(mRenderer, surface->getSwapChain());
-
- mDirtyImages = true;
mSurface = surface;
mSurface->setBoundTexture(this);
}
@@ -445,192 +250,73 @@ void Texture2D::releaseTexImage()
mSurface->setBoundTexture(NULL);
mSurface = NULL;
- if (mTexStorage)
- {
- delete mTexStorage;
- mTexStorage = NULL;
- }
-
- for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
- {
- mImageArray[i]->redefine(mRenderer, GL_NONE, 0, 0, true);
- }
+ mTexture->releaseTexImage();
}
}
void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
{
- // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
- redefineImage(level, format, width, height);
+ releaseTexImage();
- Texture::setCompressedImage(imageSize, pixels, mImageArray[level]);
+ mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, pixels);
}
-void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
- if (level < levelCount())
- {
- rx::Image *image = mImageArray[level];
- if (image->updateSurface(mTexStorage, level, xoffset, yoffset, width, height))
- {
- image->markClean();
- }
- }
-}
-
-void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
-{
- if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, mImageArray[level]))
- {
- commitRect(level, xoffset, yoffset, width, height);
- }
+ mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
}
void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
{
- if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, mImageArray[level]))
- {
- commitRect(level, xoffset, yoffset, width, height);
- }
+ mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels);
}
void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
{
- GLint internalformat = ConvertSizedInternalFormat(format, GL_UNSIGNED_BYTE);
- redefineImage(level, internalformat, width, height);
-
- if (!mImageArray[level]->isRenderableFormat())
- {
- mImageArray[level]->copy(0, 0, x, y, width, height, source);
- mDirtyImages = true;
- }
- else
- {
- if (!mTexStorage || !mTexStorage->isRenderTarget())
- {
- convertToRenderTarget();
- }
-
- mImageArray[level]->markClean();
-
- if (width != 0 && height != 0 && level < levelCount())
- {
- gl::Rectangle sourceRect;
- sourceRect.x = x;
- sourceRect.width = width;
- sourceRect.y = y;
- sourceRect.height = height;
-
- mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, level);
- }
- }
-}
-
-void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
-{
- if (xoffset + width > mImageArray[level]->getWidth() || yoffset + height > mImageArray[level]->getHeight())
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !isSamplerComplete()))
- {
- mImageArray[level]->copy(xoffset, yoffset, x, y, width, height, source);
- mDirtyImages = true;
- }
- else
- {
- if (!mTexStorage || !mTexStorage->isRenderTarget())
- {
- convertToRenderTarget();
- }
-
- updateTexture();
+ releaseTexImage();
- if (level < levelCount())
- {
- gl::Rectangle sourceRect;
- sourceRect.x = x;
- sourceRect.width = width;
- sourceRect.y = y;
- sourceRect.height = height;
-
- mRenderer->copyImage(source, sourceRect,
- gl::ExtractFormat(mImageArray[0]->getInternalFormat()),
- xoffset, yoffset, mTexStorage, level);
- }
- }
+ mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source);
}
void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
{
- delete mTexStorage;
- mTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, mUsage, false, width, height);
mImmutable = true;
- for (int level = 0; level < levels; level++)
- {
- mImageArray[level]->redefine(mRenderer, internalformat, width, height, true);
- width = std::max(1, width >> 1);
- height = std::max(1, height >> 1);
- }
-
- for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
- {
- mImageArray[level]->redefine(mRenderer, GL_NONE, 0, 0, true);
- }
-
- if (mTexStorage->isManaged())
- {
- int levels = levelCount();
-
- for (int level = 0; level < levels; level++)
- {
- mImageArray[level]->setManagedSurface(mTexStorage, level);
- }
- }
+ mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1);
}
// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
-bool Texture2D::isSamplerComplete() const
+bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
{
- GLsizei width = mImageArray[0]->getWidth();
- GLsizei height = mImageArray[0]->getHeight();
+ GLsizei width = getBaseLevelWidth();
+ GLsizei height = getBaseLevelHeight();
if (width <= 0 || height <= 0)
{
return false;
}
- bool mipmapping = isMipmapFiltered();
- bool filtering, renderable;
-
- if ((IsFloat32Format(getInternalFormat(0)) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) ||
- (IsFloat16Format(getInternalFormat(0)) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable)))
+ if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
{
- if (mSamplerState.magFilter != GL_NEAREST ||
- (mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
- {
- return false;
- }
+ return false;
}
- bool npotSupport = mRenderer->getNonPower2TextureSupport();
+ bool npotSupport = extensions.textureNPOT;
if (!npotSupport)
{
- if ((mSamplerState.wrapS != GL_CLAMP_TO_EDGE && !isPow2(width)) ||
- (mSamplerState.wrapT != GL_CLAMP_TO_EDGE && !isPow2(height)))
+ if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) ||
+ (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height)))
{
return false;
}
}
- if (mipmapping)
+ if (IsMipmapFiltered(samplerState))
{
if (!npotSupport)
{
- if (!isPow2(width) || !isPow2(height))
+ if (!gl::isPow2(width) || !gl::isPow2(height))
{
return false;
}
@@ -642,42 +328,21 @@ bool Texture2D::isSamplerComplete() const
}
}
- return true;
-}
-
-// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool Texture2D::isMipmapComplete() const
-{
- if (isImmutable())
- {
- return true;
- }
-
- GLsizei width = mImageArray[0]->getWidth();
- GLsizei height = mImageArray[0]->getHeight();
-
- if (width <= 0 || height <= 0)
+ // 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.
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(0));
+ if (formatInfo.depthBits > 0 && clientVersion > 2)
{
- return false;
- }
-
- int q = log2(std::max(width, height));
-
- for (int level = 1; level <= q; level++)
- {
- if (mImageArray[level]->getInternalFormat() != mImageArray[0]->getInternalFormat())
- {
- return false;
- }
-
- if (mImageArray[level]->getWidth() != std::max(1, width >> level))
- {
- return false;
- }
-
- if (mImageArray[level]->getHeight() != std::max(1, height >> level))
+ if (samplerState.compareMode == GL_NONE)
{
- return false;
+ if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
+ samplerState.magFilter != GL_NEAREST)
+ {
+ return false;
+ }
}
}
@@ -686,272 +351,94 @@ bool Texture2D::isMipmapComplete() const
bool Texture2D::isCompressed(GLint level) const
{
- return IsCompressed(getInternalFormat(level));
+ return GetInternalFormatInfo(getInternalFormat(level)).compressed;
}
bool Texture2D::isDepth(GLint level) const
{
- return IsDepthTexture(getInternalFormat(level));
+ return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
-// Constructs a native texture resource from the texture images
-void Texture2D::createTexture()
-{
- GLsizei width = mImageArray[0]->getWidth();
- GLsizei height = mImageArray[0]->getHeight();
-
- if (!(width > 0 && height > 0))
- return; // do not attempt to create native textures for nonexistant data
-
- GLint levels = creationLevels(width, height);
- GLenum internalformat = mImageArray[0]->getInternalFormat();
-
- delete mTexStorage;
- mTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, mUsage, false, width, height);
-
- if (mTexStorage->isManaged())
- {
- int levels = levelCount();
-
- for (int level = 0; level < levels; level++)
- {
- mImageArray[level]->setManagedSurface(mTexStorage, level);
- }
- }
-
- mDirtyImages = true;
-}
-
-void Texture2D::updateTexture()
+void Texture2D::generateMipmaps()
{
- bool mipmapping = (isMipmapFiltered() && isMipmapComplete());
-
- int levels = (mipmapping ? levelCount() : 1);
-
- for (int level = 0; level < levels; level++)
- {
- rx::Image *image = mImageArray[level];
+ releaseTexImage();
- if (image->isDirty())
- {
- commitRect(level, 0, 0, mImageArray[level]->getWidth(), mImageArray[level]->getHeight());
- }
- }
+ mTexture->generateMipmaps();
}
-void Texture2D::convertToRenderTarget()
+// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool Texture2D::isMipmapComplete() const
{
- rx::TextureStorageInterface2D *newTexStorage = NULL;
-
- if (mImageArray[0]->getWidth() != 0 && mImageArray[0]->getHeight() != 0)
- {
- GLsizei width = mImageArray[0]->getWidth();
- GLsizei height = mImageArray[0]->getHeight();
- GLint levels = mTexStorage != NULL ? mTexStorage->levelCount() : creationLevels(width, height);
- GLenum internalformat = mImageArray[0]->getInternalFormat();
-
- newTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true, width, height);
-
- if (mTexStorage != NULL)
- {
- if (!mRenderer->copyToRenderTarget(newTexStorage, mTexStorage))
- {
- delete newTexStorage;
- return gl::error(GL_OUT_OF_MEMORY);
- }
- }
- }
-
- delete mTexStorage;
- mTexStorage = newTexStorage;
-
- mDirtyImages = true;
-}
+ int levelCount = mipLevels();
-void Texture2D::generateMipmaps()
-{
- if (!mRenderer->getNonPower2TextureSupport())
+ for (int level = 0; level < levelCount; level++)
{
- if (!isPow2(mImageArray[0]->getWidth()) || !isPow2(mImageArray[0]->getHeight()))
+ if (!isLevelComplete(level))
{
- return gl::error(GL_INVALID_OPERATION);
+ return false;
}
}
- // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
- unsigned int q = log2(std::max(mImageArray[0]->getWidth(), mImageArray[0]->getHeight()));
- for (unsigned int i = 1; i <= q; i++)
- {
- redefineImage(i, mImageArray[0]->getInternalFormat(),
- std::max(mImageArray[0]->getWidth() >> i, 1),
- std::max(mImageArray[0]->getHeight() >> i, 1));
- }
-
- if (mTexStorage && mTexStorage->isRenderTarget())
- {
- for (unsigned int i = 1; i <= q; i++)
- {
- mTexStorage->generateMipmap(i);
-
- mImageArray[i]->markClean();
- }
- }
- else
- {
- for (unsigned int i = 1; i <= q; i++)
- {
- mRenderer->generateMipmap(mImageArray[i], mImageArray[i - 1]);
- }
- }
+ return true;
}
-Renderbuffer *Texture2D::getRenderbuffer(GLenum target)
+bool Texture2D::isLevelComplete(int level) const
{
- if (target != GL_TEXTURE_2D)
- {
- return gl::error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
- }
-
- if (mColorbufferProxy == NULL)
+ if (isImmutable())
{
- mColorbufferProxy = new Renderbuffer(mRenderer, id(), new RenderbufferTexture2D(this, target));
+ return true;
}
- return mColorbufferProxy;
-}
+ const rx::Image *baseImage = getBaseLevelImage();
-rx::RenderTarget *Texture2D::getRenderTarget(GLenum target)
-{
- ASSERT(target == GL_TEXTURE_2D);
+ GLsizei width = baseImage->getWidth();
+ GLsizei height = baseImage->getHeight();
- // ensure the underlying texture is created
- if (getStorage(true) == NULL)
+ if (width <= 0 || height <= 0)
{
- return NULL;
+ return false;
}
- updateTexture();
-
- // ensure this is NOT a depth texture
- if (isDepth(0))
+ // The base image level is complete if the width and height are positive
+ if (level == 0)
{
- return NULL;
+ return true;
}
- return mTexStorage->getRenderTarget();
-}
+ ASSERT(level >= 1 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
+ rx::Image *image = mTexture->getImage(level, 0);
-rx::RenderTarget *Texture2D::getDepthStencil(GLenum target)
-{
- ASSERT(target == GL_TEXTURE_2D);
-
- // ensure the underlying texture is created
- if (getStorage(true) == NULL)
+ if (image->getInternalFormat() != baseImage->getInternalFormat())
{
- return NULL;
+ return false;
}
- updateTexture();
-
- // ensure this is actually a depth texture
- if (!isDepth(0))
+ if (image->getWidth() != std::max(1, width >> level))
{
- return NULL;
+ return false;
}
- return mTexStorage->getRenderTarget();
-}
-
-int Texture2D::levelCount()
-{
- return mTexStorage ? mTexStorage->levelCount() : 0;
-}
-rx::TextureStorageInterface *Texture2D::getStorage(bool renderTarget)
-{
- if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget()))
+ if (image->getHeight() != std::max(1, height >> level))
{
- if (renderTarget)
- {
- convertToRenderTarget();
- }
- else
- {
- createTexture();
- }
+ return false;
}
- return mTexStorage;
+ return true;
}
-TextureCubeMap::TextureCubeMap(rx::Renderer *renderer, GLuint id) : Texture(renderer, id)
+TextureCubeMap::TextureCubeMap(rx::TextureImpl *impl, GLuint id)
+ : Texture(impl, id, GL_TEXTURE_CUBE_MAP)
{
- mTexStorage = NULL;
- for (int i = 0; i < 6; i++)
- {
- mFaceProxies[i] = NULL;
- mFaceProxyRefs[i] = 0;
-
- for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
- {
- mImageArray[i][j] = renderer->createImage();
- }
- }
}
TextureCubeMap::~TextureCubeMap()
{
- for (int i = 0; i < 6; i++)
- {
- mFaceProxies[i] = NULL;
-
- for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
- {
- delete mImageArray[i][j];
- }
- }
-
- delete mTexStorage;
- mTexStorage = NULL;
-}
-
-// We need to maintain a count of references to renderbuffers acting as
-// proxies for this texture, so that the texture is not deleted while
-// proxy references still exist. If the reference count drops to zero,
-// we set our proxy pointer NULL, so that a new attempt at referencing
-// will cause recreation.
-void TextureCubeMap::addProxyRef(const Renderbuffer *proxy)
-{
- for (int i = 0; i < 6; i++)
- {
- if (mFaceProxies[i] == proxy)
- mFaceProxyRefs[i]++;
- }
-}
-
-void TextureCubeMap::releaseProxy(const Renderbuffer *proxy)
-{
- for (int i = 0; i < 6; i++)
- {
- if (mFaceProxies[i] == proxy)
- {
- if (mFaceProxyRefs[i] > 0)
- mFaceProxyRefs[i]--;
-
- if (mFaceProxyRefs[i] == 0)
- mFaceProxies[i] = NULL;
- }
- }
-}
-
-GLenum TextureCubeMap::getTarget() const
-{
- return GL_TEXTURE_CUBE_MAP;
}
GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mImageArray[faceIndex(target)][level]->getWidth();
+ return mTexture->getImage(level, targetToLayerIndex(target))->getWidth();
else
return 0;
}
@@ -959,7 +446,7 @@ GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mImageArray[faceIndex(target)][level]->getHeight();
+ return mTexture->getImage(level, targetToLayerIndex(target))->getHeight();
else
return 0;
}
@@ -967,7 +454,7 @@ GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mImageArray[faceIndex(target)][level]->getInternalFormat();
+ return mTexture->getImage(level, targetToLayerIndex(target))->getInternalFormat();
else
return GL_NONE;
}
@@ -975,96 +462,120 @@ GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mImageArray[faceIndex(target)][level]->getActualFormat();
+ return mTexture->getImage(level, targetToLayerIndex(target))->getActualFormat();
else
- return D3DFMT_UNKNOWN;
+ return GL_NONE;
}
-void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
- setImage(0, level, width, height, format, type, unpackAlignment, pixels);
+ mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels);
}
-void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
- setImage(1, level, width, height, format, type, unpackAlignment, pixels);
+ mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels);
}
-void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
- setImage(2, level, width, height, format, type, unpackAlignment, pixels);
+ mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels);
}
-void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
- setImage(3, level, width, height, format, type, unpackAlignment, pixels);
+ mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels);
}
-void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
- setImage(4, level, width, height, format, type, unpackAlignment, pixels);
+ mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels);
}
-void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
- setImage(5, level, width, height, format, type, unpackAlignment, pixels);
+ mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels);
}
-void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
+void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
{
- // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
- redefineImage(faceIndex(face), level, format, width, height);
+ mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, pixels);
+}
- Texture::setCompressedImage(imageSize, pixels, mImageArray[faceIndex(face)][level]);
+void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+{
+ mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
}
-void TextureCubeMap::commitRect(int face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
{
- if (level < levelCount())
- {
- rx::Image *image = mImageArray[face][level];
- if (image->updateSurface(mTexStorage, face, level, xoffset, yoffset, width, height))
- image->markClean();
- }
+ mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels);
}
-void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool TextureCubeMap::isCubeComplete() const
{
- if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, mImageArray[faceIndex(target)][level]))
+ int baseWidth = getBaseLevelWidth();
+ int baseHeight = getBaseLevelHeight();
+ GLenum baseFormat = getBaseLevelInternalFormat();
+
+ if (baseWidth <= 0 || baseWidth != baseHeight)
{
- commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
+ return false;
}
-}
-void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
-{
- if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, mImageArray[faceIndex(target)][level]))
+ for (int faceIndex = 1; faceIndex < 6; faceIndex++)
{
- commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
+ const rx::Image *faceBaseImage = mTexture->getImage(0, faceIndex);
+
+ if (faceBaseImage->getWidth() != baseWidth ||
+ faceBaseImage->getHeight() != baseHeight ||
+ faceBaseImage->getInternalFormat() != baseFormat )
+ {
+ return false;
+ }
}
+
+ return true;
+}
+
+bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
+{
+ return GetInternalFormatInfo(getInternalFormat(target, level)).compressed;
}
-// Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86.
-bool TextureCubeMap::isSamplerComplete() const
+bool TextureCubeMap::isDepth(GLenum target, GLint level) const
+{
+ return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0;
+}
+
+void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
{
- int size = mImageArray[0][0]->getWidth();
+ mTexture->copyImage(target, level, format, x, y, width, height, source);
+}
- bool mipmapping = isMipmapFiltered();
- bool filtering, renderable;
+void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
+{
+ mImmutable = true;
- if ((gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)) == GL_FLOAT && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) ||
- (gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0) == GL_HALF_FLOAT_OES) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable)))
+ mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1);
+}
+
+// Tests for texture sampling completeness
+bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
+{
+ int size = getBaseLevelWidth();
+
+ bool mipmapping = IsMipmapFiltered(samplerState);
+
+ if (!textureCaps.get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable && !IsPointSampled(samplerState))
{
- if (mSamplerState.magFilter != GL_NEAREST ||
- (mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
- {
- return false;
- }
+ return false;
}
- if (!isPow2(size) && !mRenderer->getNonPower2TextureSupport())
+ if (!gl::isPow2(size) && !extensions.textureNPOT)
{
- if (mSamplerState.wrapS != GL_CLAMP_TO_EDGE || mSamplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping)
+ if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping)
{
return false;
}
@@ -1079,7 +590,7 @@ bool TextureCubeMap::isSamplerComplete() const
}
else
{
- if (!isMipmapCubeComplete()) // Also tests for isCubeComplete()
+ if (!isMipmapComplete()) // Also tests for isCubeComplete()
{
return false;
}
@@ -1088,28 +599,29 @@ bool TextureCubeMap::isSamplerComplete() const
return true;
}
-// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool TextureCubeMap::isCubeComplete() const
+int TextureCubeMap::targetToLayerIndex(GLenum target)
{
- if (mImageArray[0][0]->getWidth() <= 0 || mImageArray[0][0]->getHeight() != mImageArray[0][0]->getWidth())
- {
- return false;
- }
+ META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
+ META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
+ META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
+ META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
+ META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
- for (unsigned int face = 1; face < 6; face++)
- {
- if (mImageArray[face][0]->getWidth() != mImageArray[0][0]->getWidth() ||
- mImageArray[face][0]->getWidth() != mImageArray[0][0]->getHeight() ||
- mImageArray[face][0]->getInternalFormat() != mImageArray[0][0]->getInternalFormat())
- {
- return false;
- }
- }
+ return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+}
- return true;
+GLenum TextureCubeMap::layerIndexToTarget(GLint layer)
+{
+ META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
+ META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
+ META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
+ META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
+ META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
+
+ return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
}
-bool TextureCubeMap::isMipmapCubeComplete() const
+bool TextureCubeMap::isMipmapComplete() const
{
if (isImmutable())
{
@@ -1121,20 +633,13 @@ bool TextureCubeMap::isMipmapCubeComplete() const
return false;
}
- GLsizei size = mImageArray[0][0]->getWidth();
-
- int q = log2(size);
+ int levelCount = mipLevels();
for (int face = 0; face < 6; face++)
{
- for (int level = 1; level <= q; level++)
+ for (int level = 1; level < levelCount; level++)
{
- if (mImageArray[face][level]->getInternalFormat() != mImageArray[0][0]->getInternalFormat())
- {
- return false;
- }
-
- if (mImageArray[face][level]->getWidth() != std::max(1, size >> level))
+ if (!isFaceLevelComplete(face, level))
{
return false;
}
@@ -1144,356 +649,359 @@ bool TextureCubeMap::isMipmapCubeComplete() const
return true;
}
-bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
+bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const
{
- return IsCompressed(getInternalFormat(target, level));
-}
+ ASSERT(level >= 0 && faceIndex < 6 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, faceIndex) != NULL);
-// Constructs a native texture resource from the texture images, or returns an existing one
-void TextureCubeMap::createTexture()
-{
- GLsizei size = mImageArray[0][0]->getWidth();
+ if (isImmutable())
+ {
+ return true;
+ }
+
+ int baseSize = getBaseLevelWidth();
- if (!(size > 0))
- return; // do not attempt to create native textures for nonexistant data
+ if (baseSize <= 0)
+ {
+ return false;
+ }
- GLint levels = creationLevels(size);
- GLenum internalformat = mImageArray[0][0]->getInternalFormat();
+ // "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;
+ }
- delete mTexStorage;
- mTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, mUsage, false, size);
+ // Check that non-zero levels are consistent with the base level.
+ const rx::Image *faceLevelImage = mTexture->getImage(level, faceIndex);
- if (mTexStorage->isManaged())
+ if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
{
- int levels = levelCount();
+ return false;
+ }
- for (int face = 0; face < 6; face++)
- {
- for (int level = 0; level < levels; level++)
- {
- mImageArray[face][level]->setManagedSurface(mTexStorage, face, level);
- }
- }
+ if (faceLevelImage->getWidth() != std::max(1, baseSize >> level))
+ {
+ return false;
}
- mDirtyImages = true;
+ return true;
}
-void TextureCubeMap::updateTexture()
-{
- bool mipmapping = isMipmapFiltered() && isMipmapCubeComplete();
- for (int face = 0; face < 6; face++)
- {
- int levels = (mipmapping ? levelCount() : 1);
+Texture3D::Texture3D(rx::TextureImpl *impl, GLuint id)
+ : Texture(impl, id, GL_TEXTURE_3D)
+{
+}
- for (int level = 0; level < levels; level++)
- {
- rx::Image *image = mImageArray[face][level];
+Texture3D::~Texture3D()
+{
+}
- if (image->isDirty())
- {
- commitRect(face, level, 0, 0, image->getWidth(), image->getHeight());
- }
- }
- }
+GLsizei Texture3D::getWidth(GLint level) const
+{
+ return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getWidth() : 0;
}
-void TextureCubeMap::convertToRenderTarget()
+GLsizei Texture3D::getHeight(GLint level) const
{
- rx::TextureStorageInterfaceCube *newTexStorage = NULL;
+ return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getHeight() : 0;
+}
- if (mImageArray[0][0]->getWidth() != 0)
- {
- GLsizei size = mImageArray[0][0]->getWidth();
- GLint levels = mTexStorage != NULL ? mTexStorage->levelCount() : creationLevels(size);
- GLenum internalformat = mImageArray[0][0]->getInternalFormat();
+GLsizei Texture3D::getDepth(GLint level) const
+{
+ return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getDepth() : 0;
+}
- newTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true, size);
+GLenum Texture3D::getInternalFormat(GLint level) const
+{
+ return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE;
+}
- if (mTexStorage != NULL)
- {
- if (!mRenderer->copyToRenderTarget(newTexStorage, mTexStorage))
- {
- delete newTexStorage;
- return gl::error(GL_OUT_OF_MEMORY);
- }
- }
- }
+GLenum Texture3D::getActualFormat(GLint level) const
+{
+ return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE;
+}
- delete mTexStorage;
- mTexStorage = newTexStorage;
+bool Texture3D::isCompressed(GLint level) const
+{
+ return GetInternalFormatInfo(getInternalFormat(level)).compressed;
+}
- mDirtyImages = true;
+bool Texture3D::isDepth(GLint level) const
+{
+ return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
-void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
- GLint internalformat = ConvertSizedInternalFormat(format, type);
- redefineImage(faceIndex, level, internalformat, width, height);
+ mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels);
+}
- Texture::setImage(unpackAlignment, pixels, mImageArray[faceIndex][level]);
+void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+{
+ mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, pixels);
}
-unsigned int TextureCubeMap::faceIndex(GLenum face)
+void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
- META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
- META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
- META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
- META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
- META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
+ mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
+}
- return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
+{
+ mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
}
-void TextureCubeMap::redefineImage(int face, GLint level, GLint internalformat, GLsizei width, GLsizei height)
+void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
{
- // If there currently is a corresponding storage texture image, it has these parameters
- const int storageWidth = std::max(1, mImageArray[0][0]->getWidth() >> level);
- const int storageHeight = std::max(1, mImageArray[0][0]->getHeight() >> level);
- const int storageFormat = mImageArray[0][0]->getInternalFormat();
+ mImmutable = true;
- mImageArray[face][level]->redefine(mRenderer, internalformat, width, height, false);
+ mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth);
+}
+
+bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
+{
+ GLsizei width = getBaseLevelWidth();
+ GLsizei height = getBaseLevelHeight();
+ GLsizei depth = getBaseLevelDepth();
- if (mTexStorage)
+ if (width <= 0 || height <= 0 || depth <= 0)
{
- const int storageLevels = mTexStorage->levelCount();
-
- if ((level >= storageLevels && storageLevels != 0) ||
- width != storageWidth ||
- height != storageHeight ||
- internalformat != storageFormat) // Discard mismatched storage
- {
- for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
- {
- for (int f = 0; f < 6; f++)
- {
- mImageArray[f][i]->markDirty();
- }
- }
+ return false;
+ }
- delete mTexStorage;
- mTexStorage = NULL;
+ if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
+ {
+ return false;
+ }
- mDirtyImages = true;
- }
+ if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
+ {
+ return false;
}
+
+ return true;
}
-void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
+bool Texture3D::isMipmapComplete() const
{
- unsigned int faceindex = faceIndex(target);
- GLint internalformat = gl::ConvertSizedInternalFormat(format, GL_UNSIGNED_BYTE);
- redefineImage(faceindex, level, internalformat, width, height);
+ int levelCount = mipLevels();
- if (!mImageArray[faceindex][level]->isRenderableFormat())
+ for (int level = 0; level < levelCount; level++)
{
- mImageArray[faceindex][level]->copy(0, 0, x, y, width, height, source);
- mDirtyImages = true;
- }
- else
- {
- if (!mTexStorage || !mTexStorage->isRenderTarget())
- {
- convertToRenderTarget();
- }
-
- mImageArray[faceindex][level]->markClean();
-
- ASSERT(width == height);
-
- if (width > 0 && level < levelCount())
+ if (!isLevelComplete(level))
{
- gl::Rectangle sourceRect;
- sourceRect.x = x;
- sourceRect.width = width;
- sourceRect.y = y;
- sourceRect.height = height;
-
- mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, target, level);
+ return false;
}
}
+
+ return true;
}
-void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
+bool Texture3D::isLevelComplete(int level) const
{
- GLsizei size = mImageArray[faceIndex(target)][level]->getWidth();
+ ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
- if (xoffset + width > size || yoffset + height > size)
+ if (isImmutable())
{
- return gl::error(GL_INVALID_VALUE);
+ return true;
}
- unsigned int faceindex = faceIndex(target);
+ GLsizei width = getBaseLevelWidth();
+ GLsizei height = getBaseLevelHeight();
+ GLsizei depth = getBaseLevelDepth();
- if (!mImageArray[faceindex][level]->isRenderableFormat() || (!mTexStorage && !isSamplerComplete()))
+ if (width <= 0 || height <= 0 || depth <= 0)
{
- mImageArray[faceindex][level]->copy(0, 0, x, y, width, height, source);
- mDirtyImages = true;
+ return false;
}
- else
- {
- if (!mTexStorage || !mTexStorage->isRenderTarget())
- {
- convertToRenderTarget();
- }
-
- updateTexture();
- if (level < levelCount())
- {
- gl::Rectangle sourceRect;
- sourceRect.x = x;
- sourceRect.width = width;
- sourceRect.y = y;
- sourceRect.height = height;
-
- mRenderer->copyImage(source, sourceRect, gl::ExtractFormat(mImageArray[0][0]->getInternalFormat()),
- xoffset, yoffset, mTexStorage, target, level);
- }
+ if (level == 0)
+ {
+ return true;
}
-}
-void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
-{
- delete mTexStorage;
- mTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, mUsage, false, size);
- mImmutable = true;
+ rx::Image *levelImage = mTexture->getImage(level, 0);
- for (int level = 0; level < levels; level++)
+ if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
{
- GLsizei mipSize = std::max(1, size >> level);
- for (int face = 0; face < 6; face++)
- {
- mImageArray[face][level]->redefine(mRenderer, internalformat, mipSize, mipSize, true);
- }
+ return false;
}
- for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ if (levelImage->getWidth() != std::max(1, width >> level))
{
- for (int face = 0; face < 6; face++)
- {
- mImageArray[face][level]->redefine(mRenderer, GL_NONE, 0, 0, true);
- }
+ return false;
}
- if (mTexStorage->isManaged())
+ if (levelImage->getHeight() != std::max(1, height >> level))
{
- int levels = levelCount();
+ return false;
+ }
- for (int face = 0; face < 6; face++)
- {
- for (int level = 0; level < levels; level++)
- {
- mImageArray[face][level]->setManagedSurface(mTexStorage, face, level);
- }
- }
+ if (levelImage->getDepth() != std::max(1, depth >> level))
+ {
+ return false;
}
+
+ return true;
}
-void TextureCubeMap::generateMipmaps()
+Texture2DArray::Texture2DArray(rx::TextureImpl *impl, GLuint id)
+ : Texture(impl, id, GL_TEXTURE_2D_ARRAY)
{
- if (!isCubeComplete())
+}
+
+Texture2DArray::~Texture2DArray()
+{
+}
+
+GLsizei Texture2DArray::getWidth(GLint level) const
+{
+ return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getWidth() : 0;
+}
+
+GLsizei Texture2DArray::getHeight(GLint level) const
+{
+ return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getHeight() : 0;
+}
+
+GLsizei Texture2DArray::getLayers(GLint level) const
+{
+ return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getLayerCount(level) : 0;
+}
+
+GLenum Texture2DArray::getInternalFormat(GLint level) const
+{
+ return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE;
+}
+
+GLenum Texture2DArray::getActualFormat(GLint level) const
+{
+ return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE;
+}
+
+bool Texture2DArray::isCompressed(GLint level) const
+{
+ return GetInternalFormatInfo(getInternalFormat(level)).compressed;
+}
+
+bool Texture2DArray::isDepth(GLint level) const
+{
+ return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+}
+
+void Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+{
+ mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels);
+}
+
+void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+{
+ mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, pixels);
+}
+
+void Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+{
+ mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
+}
+
+void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
+{
+ mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
+}
+
+void Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+{
+ mImmutable = true;
+
+ mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth);
+}
+
+bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
+{
+ GLsizei width = getBaseLevelWidth();
+ GLsizei height = getBaseLevelHeight();
+ GLsizei depth = getLayers(0);
+
+ if (width <= 0 || height <= 0 || depth <= 0)
{
- return gl::error(GL_INVALID_OPERATION);
+ return false;
}
- if (!mRenderer->getNonPower2TextureSupport())
+ if (!textureCaps.get(getBaseLevelInternalFormat()).filterable && !IsPointSampled(samplerState))
{
- if (!isPow2(mImageArray[0][0]->getWidth()))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ return false;
}
- // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
- unsigned int q = log2(mImageArray[0][0]->getWidth());
- for (unsigned int f = 0; f < 6; f++)
+ if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
{
- for (unsigned int i = 1; i <= q; i++)
- {
- redefineImage(f, i, mImageArray[f][0]->getInternalFormat(),
- std::max(mImageArray[f][0]->getWidth() >> i, 1),
- std::max(mImageArray[f][0]->getWidth() >> i, 1));
- }
+ return false;
}
- if (mTexStorage && mTexStorage->isRenderTarget())
- {
- for (unsigned int f = 0; f < 6; f++)
- {
- for (unsigned int i = 1; i <= q; i++)
- {
- mTexStorage->generateMipmap(f, i);
+ return true;
+}
- mImageArray[f][i]->markClean();
- }
- }
- }
- else
+bool Texture2DArray::isMipmapComplete() const
+{
+ int levelCount = mipLevels();
+
+ for (int level = 1; level < levelCount; level++)
{
- for (unsigned int f = 0; f < 6; f++)
+ if (!isLevelComplete(level))
{
- for (unsigned int i = 1; i <= q; i++)
- {
- mRenderer->generateMipmap(mImageArray[f][i], mImageArray[f][i - 1]);
- }
+ return false;
}
}
+
+ return true;
}
-Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target)
+bool Texture2DArray::isLevelComplete(int level) const
{
- if (!IsCubemapTextureTarget(target))
+ ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+ if (isImmutable())
{
- return gl::error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
+ return true;
}
- unsigned int face = faceIndex(target);
+ GLsizei width = getBaseLevelWidth();
+ GLsizei height = getBaseLevelHeight();
+ GLsizei layers = getLayers(0);
- if (mFaceProxies[face] == NULL)
+ if (width <= 0 || height <= 0 || layers <= 0)
{
- mFaceProxies[face] = new Renderbuffer(mRenderer, id(), new RenderbufferTextureCubeMap(this, target));
+ return false;
}
- return mFaceProxies[face];
-}
-
-rx::RenderTarget *TextureCubeMap::getRenderTarget(GLenum target)
-{
- ASSERT(IsCubemapTextureTarget(target));
+ if (level == 0)
+ {
+ return true;
+ }
- // ensure the underlying texture is created
- if (getStorage(true) == NULL)
+ if (getInternalFormat(level) != getInternalFormat(0))
{
- return NULL;
+ return false;
}
- updateTexture();
-
- return mTexStorage->getRenderTarget(target);
-}
+ if (getWidth(level) != std::max(1, width >> level))
+ {
+ return false;
+ }
-int TextureCubeMap::levelCount()
-{
- return mTexStorage ? mTexStorage->levelCount() - getLodOffset() : 0;
-}
+ if (getHeight(level) != std::max(1, height >> level))
+ {
+ return false;
+ }
-rx::TextureStorageInterface *TextureCubeMap::getStorage(bool renderTarget)
-{
- if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget()))
+ if (getLayers(level) != layers)
{
- if (renderTarget)
- {
- convertToRenderTarget();
- }
- else
- {
- createTexture();
- }
+ return false;
}
- return mTexStorage;
+ return true;
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.h b/src/3rdparty/angle/src/libGLESv2/Texture.h
index 4f5fab28d0..ca5686fde3 100644
--- a/src/3rdparty/angle/src/libGLESv2/Texture.h
+++ b/src/3rdparty/angle/src/libGLESv2/Texture.h
@@ -11,14 +11,16 @@
#ifndef LIBGLESV2_TEXTURE_H_
#define LIBGLESV2_TEXTURE_H_
-#include <vector>
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-
#include "common/debug.h"
#include "common/RefCountObject.h"
#include "libGLESv2/angletypes.h"
+#include "libGLESv2/constants.h"
+#include "libGLESv2/renderer/TextureImpl.h"
+#include "libGLESv2/Caps.h"
+
+#include "angle_gl.h"
+
+#include <vector>
namespace egl
{
@@ -27,119 +29,85 @@ class Surface;
namespace rx
{
-class Renderer;
class TextureStorageInterface;
-class TextureStorageInterface2D;
-class TextureStorageInterfaceCube;
-class RenderTarget;
class Image;
}
namespace gl
{
class Framebuffer;
-class Renderbuffer;
-
-enum
-{
- // 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_TEXTURE_SIZE = 16384,
- IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384,
+class FramebufferAttachment;
+struct ImageIndex;
- IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE
-};
+bool IsMipmapFiltered(const gl::SamplerState &samplerState);
class Texture : public RefCountObject
{
public:
- Texture(rx::Renderer *renderer, GLuint id);
+ Texture(rx::TextureImpl *impl, GLuint id, GLenum target);
virtual ~Texture();
- virtual void addProxyRef(const Renderbuffer *proxy) = 0;
- virtual void releaseProxy(const Renderbuffer *proxy) = 0;
-
- virtual GLenum getTarget() const = 0;
-
- bool setMinFilter(GLenum filter);
- bool setMagFilter(GLenum filter);
- bool setWrapS(GLenum wrap);
- bool setWrapT(GLenum wrap);
- bool setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy);
- bool setUsage(GLenum usage);
-
- GLenum getMinFilter() const;
- GLenum getMagFilter() const;
- GLenum getWrapS() const;
- GLenum getWrapT() const;
- float getMaxAnisotropy() const;
- int getLodOffset();
- void getSamplerState(SamplerState *sampler);
+ GLenum getTarget() const;
+
+ const SamplerState &getSamplerState() const { return mSamplerState; }
+ SamplerState &getSamplerState() { return mSamplerState; }
+ void getSamplerStateWithNativeOffset(SamplerState *sampler);
+
+ void setUsage(GLenum usage);
GLenum getUsage() const;
- bool isMipmapFiltered() const;
- virtual bool isSamplerComplete() const = 0;
+ GLint getBaseLevelWidth() const;
+ GLint getBaseLevelHeight() const;
+ GLint getBaseLevelDepth() const;
+ GLenum getBaseLevelInternalFormat() const;
+
+ GLsizei getWidth(const ImageIndex &index) const;
+ GLsizei getHeight(const ImageIndex &index) const;
+ GLenum getInternalFormat(const ImageIndex &index) const;
+ GLenum getActualFormat(const ImageIndex &index) const;
- rx::TextureStorageInterface *getNativeTexture();
- virtual Renderbuffer *getRenderbuffer(GLenum target) = 0;
+ virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const = 0;
- virtual void generateMipmaps() = 0;
- virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0;
+ rx::TextureStorage *getNativeTexture();
+
+ virtual void generateMipmaps();
+ virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
- bool hasDirtyParameters() const;
- bool hasDirtyImages() const;
- void resetDirty();
unsigned int getTextureSerial();
- unsigned int getRenderTargetSerial(GLenum target);
bool isImmutable() const;
+ int immutableLevelCount();
+
+ rx::TextureImpl *getImplementation() { return mTexture; }
+ const rx::TextureImpl *getImplementation() const { return mTexture; }
static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
protected:
- void setImage(GLint unpackAlignment, const void *pixels, rx::Image *image);
- bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image);
- void setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image);
- bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image);
-
- GLint creationLevels(GLsizei width, GLsizei height) const;
- GLint creationLevels(GLsizei size) const;
-
- virtual void createTexture() = 0;
- virtual void updateTexture() = 0;
- virtual void convertToRenderTarget() = 0;
- virtual rx::RenderTarget *getRenderTarget(GLenum target) = 0;
-
- virtual int levelCount() = 0;
+ int mipLevels() const;
- rx::Renderer *mRenderer;
+ rx::TextureImpl *mTexture;
SamplerState mSamplerState;
GLenum mUsage;
- bool mDirtyImages;
-
bool mImmutable;
+ GLenum mTarget;
+
+ const rx::Image *getBaseLevelImage() const;
+
private:
DISALLOW_COPY_AND_ASSIGN(Texture);
-
- virtual rx::TextureStorageInterface *getStorage(bool renderTarget) = 0;
};
class Texture2D : public Texture
{
public:
- Texture2D(rx::Renderer *renderer, GLuint id);
-
- ~Texture2D();
+ Texture2D(rx::TextureImpl *impl, GLuint id);
- void addProxyRef(const Renderbuffer *proxy);
- void releaseProxy(const Renderbuffer *proxy);
-
- virtual GLenum getTarget() const;
+ virtual ~Texture2D();
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
@@ -148,128 +116,130 @@ class Texture2D : public Texture
bool isCompressed(GLint level) const;
bool isDepth(GLint level) const;
- void setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
- void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
- virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
- virtual bool isSamplerComplete() const;
+ virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
virtual void bindTexImage(egl::Surface *surface);
virtual void releaseTexImage();
virtual void generateMipmaps();
- virtual Renderbuffer *getRenderbuffer(GLenum target);
-
- protected:
- friend class RenderbufferTexture2D;
- virtual rx::RenderTarget *getRenderTarget(GLenum target);
- virtual rx::RenderTarget *getDepthStencil(GLenum target);
- virtual int levelCount();
-
private:
DISALLOW_COPY_AND_ASSIGN(Texture2D);
- virtual void createTexture();
- virtual void updateTexture();
- virtual void convertToRenderTarget();
- virtual rx::TextureStorageInterface *getStorage(bool renderTarget);
-
bool isMipmapComplete() const;
+ bool isLevelComplete(int level) const;
- void redefineImage(GLint level, GLint internalformat, GLsizei width, GLsizei height);
- void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-
- rx::Image *mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
-
- rx::TextureStorageInterface2D *mTexStorage;
egl::Surface *mSurface;
-
- // A specific internal reference count is kept for colorbuffer proxy references,
- // because, as the renderbuffer acting as proxy will maintain a binding pointer
- // back to this texture, there would be a circular reference if we used a binding
- // pointer here. This reference count will cause the pointer to be set to NULL if
- // the count drops to zero, but will not cause deletion of the Renderbuffer.
- Renderbuffer *mColorbufferProxy;
- unsigned int mProxyRefs;
};
class TextureCubeMap : public Texture
{
public:
- TextureCubeMap(rx::Renderer *renderer, GLuint id);
+ TextureCubeMap(rx::TextureImpl *impl, GLuint id);
- ~TextureCubeMap();
+ virtual ~TextureCubeMap();
- void addProxyRef(const Renderbuffer *proxy);
- void releaseProxy(const Renderbuffer *proxy);
-
- virtual GLenum getTarget() const;
-
GLsizei getWidth(GLenum target, GLint level) const;
GLsizei getHeight(GLenum target, GLint level) const;
GLenum getInternalFormat(GLenum target, GLint level) const;
GLenum getActualFormat(GLenum target, GLint level) const;
bool isCompressed(GLenum target, GLint level) const;
+ bool isDepth(GLenum target, GLint level) const;
- void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+ void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+ void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+ void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+ void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+ void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
- void setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
+ void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
- void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
- virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
void storage(GLsizei levels, GLenum internalformat, GLsizei size);
- virtual bool isSamplerComplete() const;
+ virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
- virtual void generateMipmaps();
+ bool isCubeComplete() const;
- virtual Renderbuffer *getRenderbuffer(GLenum target);
+ static int targetToLayerIndex(GLenum target);
+ static GLenum layerIndexToTarget(GLint layer);
- static unsigned int faceIndex(GLenum face);
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
- protected:
- friend class RenderbufferTextureCubeMap;
- virtual rx::RenderTarget *getRenderTarget(GLenum target);
- virtual int levelCount();
+ bool isMipmapComplete() const;
+ bool isFaceLevelComplete(int faceIndex, int level) const;
+};
+
+class Texture3D : public Texture
+{
+ public:
+ Texture3D(rx::TextureImpl *impl, GLuint id);
+
+ virtual ~Texture3D();
+
+ GLsizei getWidth(GLint level) const;
+ GLsizei getHeight(GLint level) const;
+ GLsizei getDepth(GLint level) const;
+ GLenum getInternalFormat(GLint level) const;
+ GLenum getActualFormat(GLint level) const;
+ bool isCompressed(GLint level) const;
+ bool isDepth(GLint level) const;
+
+ void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+ void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
+ void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+ void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
+ void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+
+ virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
private:
- DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
+ DISALLOW_COPY_AND_ASSIGN(Texture3D);
- virtual void createTexture();
- virtual void updateTexture();
- virtual void convertToRenderTarget();
- virtual rx::TextureStorageInterface *getStorage(bool renderTarget);
+ bool isMipmapComplete() const;
+ bool isLevelComplete(int level) const;
+};
- bool isCubeComplete() const;
- bool isMipmapCubeComplete() const;
+class Texture2DArray : public Texture
+{
+ public:
+ Texture2DArray(rx::TextureImpl *impl, GLuint id);
- void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
- void redefineImage(int faceIndex, GLint level, GLint internalformat, GLsizei width, GLsizei height);
+ virtual ~Texture2DArray();
- rx::Image *mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ GLsizei getWidth(GLint level) const;
+ GLsizei getHeight(GLint level) const;
+ GLsizei getLayers(GLint level) const;
+ GLenum getInternalFormat(GLint level) const;
+ GLenum getActualFormat(GLint level) const;
+ bool isCompressed(GLint level) const;
+ bool isDepth(GLint level) const;
+
+ void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+ void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
+ void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+ void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
+ void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
- rx::TextureStorageInterfaceCube *mTexStorage;
+ virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
- // A specific internal reference count is kept for colorbuffer proxy references,
- // because, as the renderbuffer acting as proxy will maintain a binding pointer
- // back to this texture, there would be a circular reference if we used a binding
- // pointer here. This reference count will cause the pointer to be set to NULL if
- // the count drops to zero, but will not cause deletion of the Renderbuffer.
- Renderbuffer *mFaceProxies[6];
- unsigned int *mFaceProxyRefs[6];
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Texture2DArray);
+
+ bool isMipmapComplete() const;
+ bool isLevelComplete(int level) const;
};
+
}
#endif // LIBGLESV2_TEXTURE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp
new file mode 100644
index 0000000000..bfa7072326
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp
@@ -0,0 +1,71 @@
+//
+// 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 "libGLESv2/TransformFeedback.h"
+#include "libGLESv2/renderer/TransformFeedbackImpl.h"
+
+namespace gl
+{
+
+TransformFeedback::TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id)
+ : RefCountObject(id),
+ mTransformFeedback(impl),
+ mStarted(GL_FALSE),
+ mPrimitiveMode(GL_NONE),
+ mPaused(GL_FALSE)
+{
+ ASSERT(impl != NULL);
+}
+
+TransformFeedback::~TransformFeedback()
+{
+ SafeDelete(mTransformFeedback);
+}
+
+void TransformFeedback::start(GLenum primitiveMode)
+{
+ mStarted = GL_TRUE;
+ mPrimitiveMode = primitiveMode;
+ mPaused = GL_FALSE;
+ mTransformFeedback->begin(primitiveMode);
+}
+
+void TransformFeedback::stop()
+{
+ mStarted = GL_FALSE;
+ mPrimitiveMode = GL_NONE;
+ mPaused = GL_FALSE;
+ mTransformFeedback->end();
+}
+
+GLboolean TransformFeedback::isStarted() const
+{
+ return mStarted;
+}
+
+GLenum TransformFeedback::getDrawMode() const
+{
+ return mPrimitiveMode;
+}
+
+void TransformFeedback::pause()
+{
+ mPaused = GL_TRUE;
+ mTransformFeedback->pause();
+}
+
+void TransformFeedback::resume()
+{
+ mPaused = GL_FALSE;
+ mTransformFeedback->resume();
+}
+
+GLboolean TransformFeedback::isPaused() const
+{
+ return mPaused;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h
new file mode 100644
index 0000000000..885a4fe172
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h
@@ -0,0 +1,51 @@
+//
+// 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 LIBGLESV2_TRANSFORM_FEEDBACK_H_
+#define LIBGLESV2_TRANSFORM_FEEDBACK_H_
+
+#include "common/angleutils.h"
+#include "common/RefCountObject.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+class TransformFeedbackImpl;
+}
+
+namespace gl
+{
+
+class TransformFeedback : public RefCountObject
+{
+ public:
+ TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id);
+ virtual ~TransformFeedback();
+
+ void start(GLenum primitiveMode);
+ void stop();
+ GLboolean isStarted() const;
+
+ GLenum getDrawMode() const;
+
+ void pause();
+ void resume();
+ GLboolean isPaused() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TransformFeedback);
+
+ rx::TransformFeedbackImpl* mTransformFeedback;
+
+ GLboolean mStarted;
+ GLenum mPrimitiveMode;
+ GLboolean mPaused;
+};
+
+}
+
+#endif // LIBGLESV2_TRANSFORM_FEEDBACK_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp b/src/3rdparty/angle/src/libGLESv2/Uniform.cpp
index 5424e271b5..bd0cd2eeec 100644
--- a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Uniform.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -7,37 +6,100 @@
#include "libGLESv2/Uniform.h"
-#include "libGLESv2/utilities.h"
+#include "common/utilities.h"
namespace gl
{
-Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize)
- : type(type), precision(precision), name(name), arraySize(arraySize)
+LinkedUniform::LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize,
+ const int blockIndex, const sh::BlockMemberInfo &blockInfo)
+ : type(type),
+ precision(precision),
+ name(name),
+ arraySize(arraySize),
+ blockIndex(blockIndex),
+ blockInfo(blockInfo),
+ data(NULL),
+ dirty(true),
+ psRegisterIndex(GL_INVALID_INDEX),
+ vsRegisterIndex(GL_INVALID_INDEX),
+ registerCount(0),
+ registerElement(0)
{
- int bytes = gl::UniformInternalSize(type) * elementCount();
- data = new unsigned char[bytes];
- memset(data, 0, bytes);
- dirty = true;
-
- psRegisterIndex = -1;
- vsRegisterIndex = -1;
- registerCount = VariableRowCount(type) * elementCount();
+ // 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 (isInDefaultBlock())
+ {
+ size_t bytes = dataSize();
+ data = new unsigned char[bytes];
+ memset(data, 0, bytes);
+ registerCount = VariableRowCount(type) * elementCount();
+ }
}
-Uniform::~Uniform()
+LinkedUniform::~LinkedUniform()
{
delete[] data;
}
-bool Uniform::isArray() const
+bool LinkedUniform::isArray() const
{
return arraySize > 0;
}
-unsigned int Uniform::elementCount() const
+unsigned int LinkedUniform::elementCount() const
{
return arraySize > 0 ? arraySize : 1;
}
+bool LinkedUniform::isReferencedByVertexShader() const
+{
+ return vsRegisterIndex != GL_INVALID_INDEX;
+}
+
+bool LinkedUniform::isReferencedByFragmentShader() const
+{
+ return psRegisterIndex != GL_INVALID_INDEX;
+}
+
+bool LinkedUniform::isInDefaultBlock() const
+{
+ return blockIndex == -1;
+}
+
+size_t LinkedUniform::dataSize() const
+{
+ ASSERT(type != GL_STRUCT_ANGLEX);
+ return VariableInternalSize(type) * elementCount();
+}
+
+bool LinkedUniform::isSampler() const
+{
+ return IsSampler(type);
+}
+
+UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize)
+ : name(name),
+ elementIndex(elementIndex),
+ dataSize(dataSize),
+ psRegisterIndex(GL_INVALID_INDEX),
+ vsRegisterIndex(GL_INVALID_INDEX)
+{
+}
+
+bool UniformBlock::isArrayElement() const
+{
+ return elementIndex != GL_INVALID_INDEX;
+}
+
+bool UniformBlock::isReferencedByVertexShader() const
+{
+ return vsRegisterIndex != GL_INVALID_INDEX;
+}
+
+bool UniformBlock::isReferencedByFragmentShader() const
+{
+ return psRegisterIndex != GL_INVALID_INDEX;
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.h b/src/3rdparty/angle/src/libGLESv2/Uniform.h
index 8ab0fbe234..633d70bb19 100644
--- a/src/3rdparty/angle/src/libGLESv2/Uniform.h
+++ b/src/3rdparty/angle/src/libGLESv2/Uniform.h
@@ -7,41 +7,72 @@
#ifndef LIBGLESV2_UNIFORM_H_
#define LIBGLESV2_UNIFORM_H_
-#include <string>
-#include <vector>
+#include "common/debug.h"
+#include "common/blocklayout.h"
-#define GL_APICALL
-#include <GLES2/gl2.h>
+#include "libGLESv2/angletypes.h"
-#include "common/debug.h"
+#include "angle_gl.h"
+
+#include <string>
+#include <vector>
namespace gl
{
// Helper struct representing a single shader uniform
-struct Uniform
+struct LinkedUniform
{
- Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize);
+ LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo);
- ~Uniform();
+ ~LinkedUniform();
bool isArray() const;
unsigned int elementCount() const;
+ bool isReferencedByVertexShader() const;
+ bool isReferencedByFragmentShader() const;
+ bool isInDefaultBlock() const;
+ size_t dataSize() const;
+ bool isSampler() const;
const GLenum type;
const GLenum precision;
const std::string name;
const unsigned int arraySize;
+ const int blockIndex;
+ const sh::BlockMemberInfo blockInfo;
unsigned char *data;
bool dirty;
- int psRegisterIndex;
- int vsRegisterIndex;
+ unsigned int psRegisterIndex;
+ unsigned int vsRegisterIndex;
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;
};
-typedef std::vector<Uniform*> UniformArray;
+// Helper struct representing a single shader uniform block
+struct UniformBlock
+{
+ // use GL_INVALID_INDEX for non-array elements
+ UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize);
+
+ bool isArrayElement() const;
+ bool isReferencedByVertexShader() const;
+ bool isReferencedByFragmentShader() const;
+
+ const std::string name;
+ const unsigned int elementIndex;
+ const unsigned int dataSize;
+
+ std::vector<unsigned int> memberUniformIndexes;
+
+ unsigned int psRegisterIndex;
+ unsigned int vsRegisterIndex;
+};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp b/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp
new file mode 100644
index 0000000000..f8ca661062
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp
@@ -0,0 +1,96 @@
+//
+// 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 "libGLESv2/VertexArray.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/renderer/VertexArrayImpl.h"
+
+namespace gl
+{
+
+VertexArray::VertexArray(rx::VertexArrayImpl *impl, GLuint id, size_t maxAttribs)
+ : mId(id),
+ mVertexArray(impl),
+ mVertexAttributes(maxAttribs)
+{
+ ASSERT(impl != NULL);
+}
+
+VertexArray::~VertexArray()
+{
+ SafeDelete(mVertexArray);
+
+ for (size_t i = 0; i < getMaxAttribs(); i++)
+ {
+ mVertexAttributes[i].buffer.set(NULL);
+ }
+ mElementArrayBuffer.set(NULL);
+}
+
+GLuint VertexArray::id() const
+{
+ return mId;
+}
+
+void VertexArray::detachBuffer(GLuint bufferName)
+{
+ for (size_t attribute = 0; attribute < getMaxAttribs(); attribute++)
+ {
+ if (mVertexAttributes[attribute].buffer.id() == bufferName)
+ {
+ mVertexAttributes[attribute].buffer.set(NULL);
+ }
+ }
+
+ if (mElementArrayBuffer.id() == bufferName)
+ {
+ mElementArrayBuffer.set(NULL);
+ }
+}
+
+const VertexAttribute& VertexArray::getVertexAttribute(size_t attributeIndex) const
+{
+ ASSERT(attributeIndex < getMaxAttribs());
+ return mVertexAttributes[attributeIndex];
+}
+
+void VertexArray::setVertexAttribDivisor(GLuint index, GLuint divisor)
+{
+ ASSERT(index < getMaxAttribs());
+ mVertexAttributes[index].divisor = divisor;
+ mVertexArray->setAttributeDivisor(index, divisor);
+}
+
+void VertexArray::enableAttribute(unsigned int attributeIndex, bool enabledState)
+{
+ ASSERT(attributeIndex < getMaxAttribs());
+ mVertexAttributes[attributeIndex].enabled = enabledState;
+ mVertexArray->enableAttribute(attributeIndex, enabledState);
+}
+
+void VertexArray::setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type,
+ bool normalized, bool pureInteger, GLsizei stride, const void *pointer)
+{
+ ASSERT(attributeIndex < getMaxAttribs());
+ mVertexAttributes[attributeIndex].buffer.set(boundBuffer);
+ mVertexAttributes[attributeIndex].size = size;
+ mVertexAttributes[attributeIndex].type = type;
+ mVertexAttributes[attributeIndex].normalized = normalized;
+ mVertexAttributes[attributeIndex].pureInteger = pureInteger;
+ mVertexAttributes[attributeIndex].stride = stride;
+ mVertexAttributes[attributeIndex].pointer = pointer;
+ mVertexArray->setAttribute(attributeIndex, mVertexAttributes[attributeIndex]);
+}
+
+void VertexArray::setElementArrayBuffer(Buffer *buffer)
+{
+ mElementArrayBuffer.set(buffer);
+ mVertexArray->setElementArrayBuffer(buffer);
+}
+
+} \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.h b/src/3rdparty/angle/src/libGLESv2/VertexArray.h
new file mode 100644
index 0000000000..993ba042cf
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/VertexArray.h
@@ -0,0 +1,63 @@
+//
+// 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 LIBGLESV2_VERTEXARRAY_H_
+#define LIBGLESV2_VERTEXARRAY_H_
+
+#include "common/RefCountObject.h"
+#include "libGLESv2/constants.h"
+#include "libGLESv2/VertexAttribute.h"
+
+#include <vector>
+
+namespace rx
+{
+class Renderer;
+class VertexArrayImpl;
+}
+
+namespace gl
+{
+class Buffer;
+
+class VertexArray
+{
+ public:
+ VertexArray(rx::VertexArrayImpl *impl, GLuint id, size_t maxAttribs);
+ ~VertexArray();
+
+ GLuint id() const;
+
+ const VertexAttribute& getVertexAttribute(size_t attributeIndex) const;
+ void detachBuffer(GLuint bufferName);
+ void setVertexAttribDivisor(GLuint index, GLuint divisor);
+ void enableAttribute(unsigned int attributeIndex, bool enabledState);
+ void setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type,
+ bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
+
+ const VertexAttribute* getVertexAttributes() const { return mVertexAttributes.data(); }
+ Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); }
+ void setElementArrayBuffer(Buffer *buffer);
+ GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); }
+ size_t getMaxAttribs() const { return mVertexAttributes.size(); }
+
+ private:
+ GLuint mId;
+
+ rx::VertexArrayImpl *mVertexArray;
+ std::vector<VertexAttribute> mVertexAttributes;
+ BindingPointer<Buffer> mElementArrayBuffer;
+};
+
+}
+
+#endif // LIBGLESV2_VERTEXARRAY_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp b/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp
new file mode 100644
index 0000000000..1096856b8a
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp
@@ -0,0 +1,55 @@
+//
+// 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 "libGLESv2/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);
+}
+
+} \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.h b/src/3rdparty/angle/src/libGLESv2/VertexAttribute.h
new file mode 100644
index 0000000000..e9757b618b
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/VertexAttribute.h
@@ -0,0 +1,119 @@
+//
+// 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 LIBGLESV2_VERTEXATTRIBUTE_H_
+#define LIBGLESV2_VERTEXATTRIBUTE_H_
+
+#include "libGLESv2/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();
+};
+
+template <typename T>
+T QuerySingleVertexAttributeParameter(const VertexAttribute& attrib, GLenum pname)
+{
+ switch (pname)
+ {
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+ return static_cast<T>(attrib.enabled ? GL_TRUE : GL_FALSE);
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+ return static_cast<T>(attrib.size);
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+ return static_cast<T>(attrib.stride);
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+ return static_cast<T>(attrib.type);
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+ return static_cast<T>(attrib.normalized ? GL_TRUE : GL_FALSE);
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+ return static_cast<T>(attrib.buffer.id());
+ case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
+ return static_cast<T>(attrib.divisor);
+ case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
+ return static_cast<T>(attrib.pureInteger ? GL_TRUE : GL_FALSE);
+ default:
+ UNREACHABLE();
+ return static_cast<T>(0);
+ }
+}
+
+size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib);
+size_t ComputeVertexAttributeStride(const VertexAttribute& attrib);
+
+struct VertexAttribCurrentValueData
+{
+ union
+ {
+ GLfloat FloatValues[4];
+ GLint IntValues[4];
+ GLuint UnsignedIntValues[4];
+ };
+ GLenum Type;
+
+ void setFloatValues(const GLfloat floatValues[4])
+ {
+ for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+ {
+ FloatValues[valueIndex] = floatValues[valueIndex];
+ }
+ Type = GL_FLOAT;
+ }
+
+ void setIntValues(const GLint intValues[4])
+ {
+ for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+ {
+ IntValues[valueIndex] = intValues[valueIndex];
+ }
+ Type = GL_INT;
+ }
+
+ void setUnsignedIntValues(const GLuint unsignedIntValues[4])
+ {
+ for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+ {
+ UnsignedIntValues[valueIndex] = unsignedIntValues[valueIndex];
+ }
+ Type = GL_UNSIGNED_INT;
+ }
+
+ bool operator==(const VertexAttribCurrentValueData &other)
+ {
+ return (Type == other.Type && memcmp(FloatValues, other.FloatValues, sizeof(float) * 4) == 0);
+ }
+
+ bool operator!=(const VertexAttribCurrentValueData &other)
+ {
+ return !(*this == other);
+ }
+};
+
+}
+
+#endif // LIBGLESV2_VERTEXATTRIBUTE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp
new file mode 100644
index 0000000000..bb6425df64
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp
@@ -0,0 +1,195 @@
+//
+// 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 "libGLESv2/angletypes.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/VertexAttribute.h"
+
+namespace gl
+{
+
+SamplerState::SamplerState()
+ : minFilter(GL_NEAREST_MIPMAP_LINEAR),
+ magFilter(GL_LINEAR),
+ wrapS(GL_REPEAT),
+ wrapT(GL_REPEAT),
+ wrapR(GL_REPEAT),
+ maxAnisotropy(1.0f),
+ baseLevel(0),
+ maxLevel(1000),
+ minLod(-FLT_MAX),
+ maxLod(FLT_MAX),
+ compareMode(GL_NONE),
+ compareFunc(GL_LEQUAL),
+ swizzleRed(GL_RED),
+ swizzleGreen(GL_GREEN),
+ swizzleBlue(GL_BLUE),
+ swizzleAlpha(GL_ALPHA)
+{}
+
+bool SamplerState::swizzleRequired() const
+{
+ return swizzleRed != GL_RED || swizzleGreen != GL_GREEN ||
+ swizzleBlue != GL_BLUE || swizzleAlpha != GL_ALPHA;
+}
+
+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;
+ }
+}
+
+VertexFormat::VertexFormat()
+ : mType(GL_NONE),
+ mNormalized(GL_FALSE),
+ mComponents(0),
+ mPureInteger(false)
+{}
+
+VertexFormat::VertexFormat(GLenum type, GLboolean normalized, GLuint components, bool pureInteger)
+ : mType(type),
+ mNormalized(normalized),
+ mComponents(components),
+ mPureInteger(pureInteger)
+{
+ // Float data can not be normalized, so ignore the user setting
+ if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED)
+ {
+ mNormalized = GL_FALSE;
+ }
+}
+
+VertexFormat::VertexFormat(const VertexAttribute &attrib)
+ : mType(attrib.type),
+ mNormalized(attrib.normalized ? GL_TRUE : GL_FALSE),
+ mComponents(attrib.size),
+ mPureInteger(attrib.pureInteger)
+{
+ // Ensure we aren't initializing a vertex format which should be using
+ // the current-value type
+ ASSERT(attrib.enabled);
+
+ // Float data can not be normalized, so ignore the user setting
+ if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED)
+ {
+ mNormalized = GL_FALSE;
+ }
+}
+
+VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueType)
+ : mType(attrib.type),
+ mNormalized(attrib.normalized ? GL_TRUE : GL_FALSE),
+ mComponents(attrib.size),
+ mPureInteger(attrib.pureInteger)
+{
+ if (!attrib.enabled)
+ {
+ mType = currentValueType;
+ mNormalized = GL_FALSE;
+ mComponents = 4;
+ mPureInteger = (currentValueType != GL_FLOAT);
+ }
+
+ // Float data can not be normalized, so ignore the user setting
+ if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED)
+ {
+ mNormalized = GL_FALSE;
+ }
+}
+
+void VertexFormat::GetInputLayout(VertexFormat *inputLayout,
+ ProgramBinary *programBinary,
+ const VertexAttribute *attributes,
+ const gl::VertexAttribCurrentValueData *currentValues)
+{
+ for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ int semanticIndex = programBinary->getSemanticIndex(attributeIndex);
+
+ if (semanticIndex != -1)
+ {
+ inputLayout[semanticIndex] = VertexFormat(attributes[attributeIndex], currentValues[attributeIndex].Type);
+ }
+ }
+}
+
+bool VertexFormat::operator==(const VertexFormat &other) const
+{
+ return (mType == other.mType &&
+ mComponents == other.mComponents &&
+ mNormalized == other.mNormalized &&
+ mPureInteger == other.mPureInteger );
+}
+
+bool VertexFormat::operator!=(const VertexFormat &other) const
+{
+ return !(*this == other);
+}
+
+bool VertexFormat::operator<(const VertexFormat& other) const
+{
+ if (mType != other.mType)
+ {
+ return mType < other.mType;
+ }
+ if (mNormalized != other.mNormalized)
+ {
+ return mNormalized < other.mNormalized;
+ }
+ if (mComponents != other.mComponents)
+ {
+ return mComponents < other.mComponents;
+ }
+ return mPureInteger < other.mPureInteger;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libGLESv2/angletypes.h
index b2f0cad265..642a6ec266 100644
--- a/src/3rdparty/angle/src/libGLESv2/angletypes.h
+++ b/src/3rdparty/angle/src/libGLESv2/angletypes.h
@@ -9,17 +9,16 @@
#ifndef LIBGLESV2_ANGLETYPES_H_
#define LIBGLESV2_ANGLETYPES_H_
-namespace gl
-{
+#include "libGLESv2/constants.h"
+#include "common/RefCountObject.h"
+#include <float.h>
-enum TextureType
+namespace gl
{
- TEXTURE_2D,
- TEXTURE_CUBE,
-
- TEXTURE_TYPE_COUNT,
- TEXTURE_UNKNOWN
-};
+class Buffer;
+class ProgramBinary;
+struct VertexAttribute;
+struct VertexAttribCurrentValueData;
enum SamplerType
{
@@ -27,20 +26,56 @@ enum SamplerType
SAMPLER_VERTEX
};
+template <typename T>
struct Color
{
- float red;
- float green;
- float blue;
- float alpha;
+ T red;
+ T green;
+ T blue;
+ T alpha;
+
+ Color() : red(0), green(0), blue(0), alpha(0) { }
+ Color(T r, T g, T b, T a) : red(r), green(g), blue(b), alpha(a) { }
};
+typedef Color<float> ColorF;
+typedef Color<int> ColorI;
+typedef Color<unsigned int> ColorUI;
+
struct Rectangle
{
int x;
int y;
int width;
int height;
+
+ 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) { }
+};
+
+bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection);
+
+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) { }
+};
+
+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_) { }
};
struct RasterizerState
@@ -55,6 +90,8 @@ struct RasterizerState
bool pointDrawMode;
bool multiSample;
+
+ bool rasterizerDiscard;
};
struct BlendState
@@ -100,28 +137,125 @@ struct DepthStencilState
struct SamplerState
{
+ SamplerState();
+
GLenum minFilter;
GLenum magFilter;
GLenum wrapS;
GLenum wrapT;
+ GLenum wrapR;
float maxAnisotropy;
- int lodOffset;
+
+ GLint baseLevel;
+ GLint maxLevel;
+ GLfloat minLod;
+ GLfloat maxLod;
+
+ GLenum compareMode;
+ GLenum compareFunc;
+
+ GLenum swizzleRed;
+ GLenum swizzleGreen;
+ GLenum swizzleBlue;
+ GLenum swizzleAlpha;
+
+ bool swizzleRequired() const;
};
struct ClearParameters
{
- GLbitfield mask;
-
- Color colorClearValue;
+ bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
+ ColorF colorFClearValue;
+ ColorI colorIClearValue;
+ ColorUI colorUIClearValue;
+ GLenum colorClearType;
bool colorMaskRed;
bool colorMaskGreen;
bool colorMaskBlue;
bool colorMaskAlpha;
+ bool clearDepth;
float depthClearValue;
+ bool clearStencil;
GLint stencilClearValue;
GLuint stencilWriteMask;
+
+ bool scissorEnabled;
+ Rectangle scissor;
+};
+
+struct PixelUnpackState
+{
+ BindingPointer<Buffer> pixelBuffer;
+ GLint alignment;
+
+ PixelUnpackState()
+ : alignment(4)
+ {}
+
+ explicit PixelUnpackState(GLint alignmentIn)
+ : alignment(alignmentIn)
+ {}
+};
+
+struct PixelPackState
+{
+ BindingPointer<Buffer> pixelBuffer;
+ GLint alignment;
+ bool reverseRowOrder;
+
+ PixelPackState()
+ : alignment(4),
+ reverseRowOrder(false)
+ {}
+
+ explicit PixelPackState(GLint alignmentIn, bool reverseRowOrderIn)
+ : alignment(alignmentIn),
+ reverseRowOrder(reverseRowOrderIn)
+ {}
+};
+
+struct VertexFormat
+{
+ GLenum mType;
+ GLboolean mNormalized;
+ GLuint mComponents;
+ bool mPureInteger;
+
+ VertexFormat();
+ VertexFormat(GLenum type, GLboolean normalized, GLuint components, bool pureInteger);
+ explicit VertexFormat(const VertexAttribute &attribute);
+ VertexFormat(const VertexAttribute &attribute, GLenum currentValueType);
+
+ static void GetInputLayout(VertexFormat *inputLayout,
+ ProgramBinary *programBinary,
+ const VertexAttribute *attributes,
+ const gl::VertexAttribCurrentValueData *currentValues);
+
+ bool operator==(const VertexFormat &other) const;
+ bool operator!=(const VertexFormat &other) const;
+ bool operator<(const VertexFormat& other) const;
+};
+
+}
+
+namespace rx
+{
+
+enum VertexConversionType
+{
+ VERTEX_CONVERT_NONE = 0,
+ VERTEX_CONVERT_CPU = 1,
+ VERTEX_CONVERT_GPU = 2,
+ VERTEX_CONVERT_BOTH = 3
+};
+
+enum D3DWorkaroundType
+{
+ ANGLE_D3D_WORKAROUND_NONE,
+ ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION,
+ ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION
};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/constants.h b/src/3rdparty/angle/src/libGLESv2/constants.h
index 9f24d66a7d..69c4823fb2 100644
--- a/src/3rdparty/angle/src/libGLESv2/constants.h
+++ b/src/3rdparty/angle/src/libGLESv2/constants.h
@@ -15,19 +15,29 @@ namespace gl
enum
{
MAX_VERTEX_ATTRIBS = 16,
- MAX_TEXTURE_IMAGE_UNITS = 16,
// Implementation upper limits, real maximums depend on the hardware
- IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 16,
- IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS = MAX_TEXTURE_IMAGE_UNITS + IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
-
IMPLEMENTATION_MAX_VARYING_VECTORS = 32,
- IMPLEMENTATION_MAX_DRAW_BUFFERS = 8
-};
+ 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,
-const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f;
-const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f;
-const float ALIASED_POINT_SIZE_RANGE_MIN = 1.0f;
+ 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
+};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/formatutils.cpp b/src/3rdparty/angle/src/libGLESv2/formatutils.cpp
new file mode 100644
index 0000000000..8674d5337f
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/formatutils.cpp
@@ -0,0 +1,629 @@
+//
+// 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 "libGLESv2/formatutils.h"
+#include "libGLESv2/Context.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/imageformats.h"
+#include "libGLESv2/renderer/copyimage.h"
+
+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.
+
+FormatType::FormatType()
+ : internalFormat(GL_NONE),
+ colorWriteFunction(NULL)
+{
+}
+
+typedef std::pair<GLenum, GLenum> FormatTypePair;
+typedef std::pair<FormatTypePair, FormatType> FormatPair;
+typedef std::map<FormatTypePair, FormatType> FormatMap;
+
+// A helper function to insert data into the format map with fewer characters.
+static inline void InsertFormatMapping(FormatMap *map, GLenum format, GLenum type, GLenum internalFormat, ColorWriteFunction writeFunc)
+{
+ FormatType info;
+ info.internalFormat = internalFormat;
+ info.colorWriteFunction = writeFunc;
+ map->insert(FormatPair(FormatTypePair(format, type), info));
+}
+
+FormatMap BuildFormatMap()
+{
+ FormatMap map;
+
+ using namespace rx;
+
+ // | Format | Type | Internal format | Color write function |
+ InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8, WriteColor<R8G8B8A8, GLfloat> );
+ InsertFormatMapping(&map, GL_RGBA, GL_BYTE, GL_RGBA8_SNORM, WriteColor<R8G8B8A8S, GLfloat> );
+ InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4, WriteColor<R4G4B4A4, GLfloat> );
+ InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1, WriteColor<R5G5B5A1, GLfloat> );
+ InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2, WriteColor<R10G10B10A2, GLfloat> );
+ InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F, WriteColor<R32G32B32A32F, GLfloat>);
+ InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F, WriteColor<R16G16B16A16F, GLfloat>);
+ InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F, WriteColor<R16G16B16A16F, GLfloat>);
+
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI, WriteColor<R8G8B8A8, GLuint> );
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I, WriteColor<R8G8B8A8S, GLint> );
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI, WriteColor<R16G16B16A16, GLuint> );
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I, WriteColor<R16G16B16A16S, GLint> );
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI, WriteColor<R32G32B32A32, GLuint> );
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_INT, GL_RGBA32I, WriteColor<R32G32B32A32S, GLint> );
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI, WriteColor<R10G10B10A2, GLuint> );
+
+ InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8, WriteColor<R8G8B8, GLfloat> );
+ InsertFormatMapping(&map, GL_RGB, GL_BYTE, GL_RGB8_SNORM, WriteColor<R8G8B8S, GLfloat> );
+ InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565, WriteColor<R5G6B5, GLfloat> );
+ InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F, WriteColor<R11G11B10F, GLfloat> );
+ InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5, WriteColor<R9G9B9E5, GLfloat> );
+ InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F, WriteColor<R32G32B32F, GLfloat> );
+ InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F, WriteColor<R16G16B16F, GLfloat> );
+ InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F, WriteColor<R16G16B16F, GLfloat> );
+
+ InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI, WriteColor<R8G8B8, GLuint> );
+ InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I, WriteColor<R8G8B8S, GLint> );
+ InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI, WriteColor<R16G16B16, GLuint> );
+ InsertFormatMapping(&map, GL_RGB_INTEGER, GL_SHORT, GL_RGB16I, WriteColor<R16G16B16S, GLint> );
+ InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI, WriteColor<R32G32B32, GLuint> );
+ InsertFormatMapping(&map, GL_RGB_INTEGER, GL_INT, GL_RGB32I, WriteColor<R32G32B32S, GLint> );
+
+ InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8, WriteColor<R8G8, GLfloat> );
+ InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM, WriteColor<R8G8S, GLfloat> );
+ InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F, WriteColor<R32G32F, GLfloat> );
+ InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F, WriteColor<R16G16F, GLfloat> );
+ InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F, WriteColor<R16G16F, GLfloat> );
+
+ InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI, WriteColor<R8G8, GLuint> );
+ InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I, WriteColor<R8G8S, GLint> );
+ InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI, WriteColor<R16G16, GLuint> );
+ InsertFormatMapping(&map, GL_RG_INTEGER, GL_SHORT, GL_RG16I, WriteColor<R16G16S, GLint> );
+ InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI, WriteColor<R32G32, GLuint> );
+ InsertFormatMapping(&map, GL_RG_INTEGER, GL_INT, GL_RG32I, WriteColor<R32G32S, GLint> );
+
+ InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8, WriteColor<R8, GLfloat> );
+ InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM, WriteColor<R8S, GLfloat> );
+ InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F, WriteColor<R32F, GLfloat> );
+ InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F, WriteColor<R16F, GLfloat> );
+ InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F, WriteColor<R16F, GLfloat> );
+
+ InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI, WriteColor<R8, GLuint> );
+ InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I, WriteColor<R8S, GLint> );
+ InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI, WriteColor<R16, GLuint> );
+ InsertFormatMapping(&map, GL_RED_INTEGER, GL_SHORT, GL_R16I, WriteColor<R16S, GLint> );
+ InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI, WriteColor<R32, GLuint> );
+ InsertFormatMapping(&map, GL_RED_INTEGER, GL_INT, GL_R32I, WriteColor<R32S, GLint> );
+
+ InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT, WriteColor<L8A8, GLfloat> );
+ InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT, WriteColor<L8, GLfloat> );
+ InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT, WriteColor<A8, GLfloat> );
+ InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT, WriteColor<L32A32F, GLfloat> );
+ InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT, WriteColor<L32F, GLfloat> );
+ InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT, WriteColor<A32F, GLfloat> );
+ InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT, WriteColor<L16A16F, GLfloat> );
+ InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT, WriteColor<L16A16F, GLfloat> );
+ InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT, WriteColor<L16F, GLfloat> );
+ InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT, WriteColor<L16F, GLfloat> );
+ InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT, WriteColor<A16F, GLfloat> );
+ InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT, WriteColor<A16F, GLfloat> );
+
+ InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT, WriteColor<B8G8R8A8, GLfloat> );
+ InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX, WriteColor<B4G4R4A4, GLfloat> );
+ InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX, WriteColor<B5G5R5A1, GLfloat> );
+
+ InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8, WriteColor<R8G8B8, GLfloat> );
+ InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8, WriteColor<R8G8B8A8, GLfloat> );
+
+ InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, NULL );
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL );
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL );
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL );
+
+ InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16, NULL );
+ InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES, NULL );
+ InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F, NULL );
+
+ InsertFormatMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, GL_STENCIL_INDEX8, NULL );
+
+ InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8, NULL );
+ InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8, NULL );
+
+ return map;
+}
+
+Type::Type()
+ : bytes(0),
+ specialInterpretation(false)
+{
+}
+
+// Map of sizes of input types
+typedef std::pair<GLenum, Type> TypeInfoPair;
+typedef std::map<GLenum, Type> TypeInfoMap;
+
+static inline void InsertTypeInfo(TypeInfoMap *map, GLenum type, GLuint bytes, bool specialInterpretation)
+{
+ Type info;
+ info.bytes = bytes;
+ info.specialInterpretation = specialInterpretation;
+
+ map->insert(std::make_pair(type, info));
+}
+
+bool operator<(const Type& a, const Type& b)
+{
+ return memcmp(&a, &b, sizeof(Type)) < 0;
+}
+
+static TypeInfoMap BuildTypeInfoMap()
+{
+ TypeInfoMap map;
+
+ InsertTypeInfo(&map, GL_UNSIGNED_BYTE, 1, false);
+ InsertTypeInfo(&map, GL_BYTE, 1, false);
+ InsertTypeInfo(&map, GL_UNSIGNED_SHORT, 2, false);
+ InsertTypeInfo(&map, GL_SHORT, 2, false);
+ InsertTypeInfo(&map, GL_UNSIGNED_INT, 4, false);
+ InsertTypeInfo(&map, GL_INT, 4, false);
+ InsertTypeInfo(&map, GL_HALF_FLOAT, 2, false);
+ InsertTypeInfo(&map, GL_HALF_FLOAT_OES, 2, false);
+ InsertTypeInfo(&map, GL_FLOAT, 4, false);
+ InsertTypeInfo(&map, GL_UNSIGNED_SHORT_5_6_5, 2, true );
+ InsertTypeInfo(&map, GL_UNSIGNED_SHORT_4_4_4_4, 2, true );
+ InsertTypeInfo(&map, GL_UNSIGNED_SHORT_5_5_5_1, 2, true );
+ InsertTypeInfo(&map, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, 2, true );
+ InsertTypeInfo(&map, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, 2, true );
+ InsertTypeInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, true );
+ InsertTypeInfo(&map, GL_UNSIGNED_INT_24_8, 4, true );
+ InsertTypeInfo(&map, GL_UNSIGNED_INT_10F_11F_11F_REV, 4, true );
+ InsertTypeInfo(&map, GL_UNSIGNED_INT_5_9_9_9_REV, 4, true );
+ InsertTypeInfo(&map, GL_UNSIGNED_INT_24_8_OES, 4, true );
+ InsertTypeInfo(&map, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8, true );
+
+ return map;
+}
+
+// Information about internal formats
+static bool AlwaysSupported(GLuint, const Extensions &)
+{
+ return true;
+}
+
+static bool UnimplementedSupport(GLuint, const Extensions &)
+{
+ return false;
+}
+
+static bool NeverSupported(GLuint, const Extensions &)
+{
+ return false;
+}
+
+template <GLuint minCoreGLVersion>
+static bool RequireES(GLuint clientVersion, const Extensions &)
+{
+ return clientVersion >= minCoreGLVersion;
+}
+
+// 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(GLuint, const Extensions & extensions)
+{
+ return extensions.*bool1;
+}
+
+// Check for a minimum client version or a single extension
+template <GLuint minCoreGLVersion, ExtensionBool bool1>
+static bool RequireESOrExt(GLuint clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= minCoreGLVersion || extensions.*bool1;
+}
+
+// Check for a minimum client version or two extensions
+template <GLuint minCoreGLVersion, ExtensionBool bool1, ExtensionBool bool2>
+static bool RequireESOrExtAndExt(GLuint clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= minCoreGLVersion || (extensions.*bool1 && extensions.*bool2);
+}
+
+// Check for a minimum client version or at least one of two extensions
+template <GLuint minCoreGLVersion, ExtensionBool bool1, ExtensionBool bool2>
+static bool RequireESOrExtOrExt(GLuint clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= minCoreGLVersion || extensions.*bool1 || extensions.*bool2;
+}
+
+// Check support for two extensions
+template <ExtensionBool bool1, ExtensionBool bool2>
+static bool RequireExtAndExt(GLuint, const Extensions &extensions)
+{
+ return extensions.*bool1 && extensions.*bool2;
+}
+
+InternalFormat::InternalFormat()
+ : redBits(0),
+ greenBits(0),
+ blueBits(0),
+ luminanceBits(0),
+ alphaBits(0),
+ sharedBits(0),
+ depthBits(0),
+ stencilBits(0),
+ pixelBytes(0),
+ componentCount(0),
+ compressedBlockWidth(0),
+ compressedBlockHeight(0),
+ format(GL_NONE),
+ type(GL_NONE),
+ componentType(GL_NONE),
+ colorEncoding(GL_NONE),
+ compressed(false),
+ textureSupport(NeverSupported),
+ renderSupport(NeverSupported),
+ filterSupport(NeverSupported)
+{
+}
+
+static InternalFormat UnsizedFormat(GLenum format, InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction renderSupport,
+ InternalFormat::SupportCheckFunction filterSupport)
+{
+ InternalFormat formatInfo;
+ formatInfo.format = format;
+ formatInfo.textureSupport = textureSupport;
+ formatInfo.renderSupport = renderSupport;
+ formatInfo.filterSupport = filterSupport;
+ return formatInfo;
+}
+
+static InternalFormat RGBAFormat(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.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;
+ return 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.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;
+}
+
+static InternalFormat DepthStencilFormat(GLuint depthBits, GLuint stencilBits, GLuint unusedBits, GLenum format,
+ GLenum type, GLenum componentType, InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction renderSupport,
+ InternalFormat::SupportCheckFunction filterSupport)
+{
+ InternalFormat formatInfo;
+ 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;
+ return 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.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;
+}
+
+typedef std::pair<GLenum, InternalFormat> InternalFormatInfoPair;
+typedef std::map<GLenum, InternalFormat> InternalFormatInfoMap;
+
+static InternalFormatInfoMap BuildInternalFormatInfoMap()
+{
+ InternalFormatInfoMap map;
+
+ // From ES 3.0.1 spec, table 3.12
+ map.insert(InternalFormatInfoPair(GL_NONE, InternalFormat()));
+
+ // | Internal format | | R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Renderable | Filterable |
+ map.insert(InternalFormatInfoPair(GL_R8, RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::textureRG>, RequireESOrExt<3, &Extensions::textureRG>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_R8_SNORM, RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RG8, RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::textureRG>, RequireESOrExt<3, &Extensions::textureRG>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RG8_SNORM, RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB8, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::rgb8rgba8>, RequireESOrExt<3, &Extensions::rgb8rgba8>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB8_SNORM, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB565, RGBAFormat( 5, 6, 5, 0, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, RequireES<2>, RequireES<2>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGBA4, RGBAFormat( 4, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, RequireES<2>, RequireES<2>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB5_A1, RGBAFormat( 5, 5, 5, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, RequireES<2>, RequireES<2>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGBA8, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::rgb8rgba8>, RequireESOrExt<3, &Extensions::rgb8rgba8>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGBA8_SNORM, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB10_A2, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireES<3>, RequireES<3>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB10_A2UI, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_SRGB8, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_SRGB8_ALPHA8, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, &Extensions::sRGB>, RequireESOrExt<3, &Extensions::sRGB>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_R11F_G11F_B10F, RGBAFormat(11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, RequireES<3>, RequireExt<&Extensions::colorBufferFloat>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB9_E5, RGBAFormat( 9, 9, 9, 0, 5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT, false, RequireES<3>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_R8I, RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_R8UI, RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_R16I, RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_R16UI, RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_R32I, RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_INT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_R32UI, RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RG8I, RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RG8UI, RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RG16I, RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RG16UI, RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RG32I, RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_INT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RG32UI, RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB8I, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB8UI, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB16I, RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB16UI, RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB32I, RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_INT, GL_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB32UI, RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGBA8I, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGBA8UI, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGBA16I, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGBA16UI, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGBA32I, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGBA32UI, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
+
+ map.insert(InternalFormatInfoPair(GL_BGRA8_EXT, RGBAFormat( 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_BGRA4_ANGLEX, RGBAFormat( 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)));
+ map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX, RGBAFormat( 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)));
+
+ // 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 | | | | |
+ map.insert(InternalFormatInfoPair(GL_R16F, RGBAFormat(16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureHalfFloatLinear>)));
+ map.insert(InternalFormatInfoPair(GL_RG16F, RGBAFormat(16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureHalfFloatLinear>)));
+ map.insert(InternalFormatInfoPair(GL_RGB16F, RGBAFormat(16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireExt<&Extensions::textureHalfFloatLinear>)));
+ map.insert(InternalFormatInfoPair(GL_RGBA16F, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireExt<&Extensions::textureHalfFloatLinear>)));
+ map.insert(InternalFormatInfoPair(GL_R32F, RGBAFormat(32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureFloatLinear> )));
+ map.insert(InternalFormatInfoPair(GL_RG32F, RGBAFormat(32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureFloatLinear> )));
+ map.insert(InternalFormatInfoPair(GL_RGB32F, RGBAFormat(32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureFloat>, RequireESOrExt<3, &Extensions::textureFloat>, RequireExt<&Extensions::textureFloatLinear> )));
+ map.insert(InternalFormatInfoPair(GL_RGBA32F, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureFloat>, RequireESOrExt<3, &Extensions::textureFloat>, RequireExt<&Extensions::textureFloatLinear> )));
+
+ // Depth stencil formats
+ // | Internal format | | D |S | X | Format | Type | Component type | Supported | Renderable | Filterable |
+ map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16, DepthStencilFormat(16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireES<2>, RequireES<2>, RequireESOrExt<3, &Extensions::depthTextures>)));
+ map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT24, DepthStencilFormat(24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireES<3>, RequireES<3>, RequireESOrExt<3, &Extensions::depthTextures>)));
+ map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32F, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireES<3>, RequireES<3>, RequireESOrExt<3, &Extensions::depthTextures>)));
+ map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::depthTextures>, RequireExt<&Extensions::depthTextures>, AlwaysSupported )));
+ map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8, DepthStencilFormat(24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, &Extensions::depthTextures>, RequireESOrExtOrExt<3, &Extensions::depthTextures, &Extensions::packedDepthStencil>, AlwaysSupported )));
+ map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8, DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireES<3>, RequireES<3>, AlwaysSupported )));
+ map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, DepthStencilFormat( 0, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, RequireES<2>, RequireES<2>, NeverSupported )));
+
+ // 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 |
+ map.insert(InternalFormatInfoPair(GL_ALPHA, UnsizedFormat(GL_ALPHA, RequireES<2>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_LUMINANCE, UnsizedFormat(GL_LUMINANCE, RequireES<2>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA, UnsizedFormat(GL_LUMINANCE_ALPHA, RequireES<2>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RED, UnsizedFormat(GL_RED, RequireESOrExt<3, &Extensions::textureRG>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RG, UnsizedFormat(GL_RG, RequireESOrExt<3, &Extensions::textureRG>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGB, UnsizedFormat(GL_RGB, RequireES<2>, RequireES<2>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RGBA, UnsizedFormat(GL_RGBA, RequireES<2>, RequireES<2>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_RED_INTEGER, UnsizedFormat(GL_RED_INTEGER, RequireES<3>, NeverSupported, NeverSupported )));
+ map.insert(InternalFormatInfoPair(GL_RG_INTEGER, UnsizedFormat(GL_RG_INTEGER, RequireES<3>, NeverSupported, NeverSupported )));
+ map.insert(InternalFormatInfoPair(GL_RGB_INTEGER, UnsizedFormat(GL_RGB_INTEGER, RequireES<3>, NeverSupported, NeverSupported )));
+ map.insert(InternalFormatInfoPair(GL_RGBA_INTEGER, UnsizedFormat(GL_RGBA_INTEGER, RequireES<3>, NeverSupported, NeverSupported )));
+ map.insert(InternalFormatInfoPair(GL_BGRA_EXT, UnsizedFormat(GL_BGRA_EXT, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT, UnsizedFormat(GL_DEPTH_COMPONENT, RequireES<2>, RequireES<2>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_DEPTH_STENCIL, UnsizedFormat(GL_DEPTH_STENCIL, RequireESOrExt<3, &Extensions::packedDepthStencil>, RequireESOrExt<3, &Extensions::packedDepthStencil>, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_SRGB_EXT, UnsizedFormat(GL_RGB, RequireESOrExt<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported)));
+ map.insert(InternalFormatInfoPair(GL_SRGB_ALPHA_EXT, UnsizedFormat(GL_RGBA, RequireESOrExt<3, &Extensions::sRGB>, RequireESOrExt<3, &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, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
+ map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
+
+ // 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)));
+
+ return map;
+}
+
+static const InternalFormatInfoMap &GetInternalFormatMap()
+{
+ static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap();
+ return formatMap;
+}
+
+static FormatSet BuildAllSizedInternalFormatSet()
+{
+ FormatSet result;
+
+ const InternalFormatInfoMap &formats = GetInternalFormatMap();
+ for (InternalFormatInfoMap::const_iterator i = formats.begin(); i != formats.end(); i++)
+ {
+ if (i->second.pixelBytes > 0)
+ {
+ result.insert(i->first);
+ }
+ }
+
+ return result;
+}
+
+const FormatType &GetFormatTypeInfo(GLenum format, GLenum type)
+{
+ static const FormatMap formatMap = BuildFormatMap();
+ FormatMap::const_iterator iter = formatMap.find(FormatTypePair(format, type));
+ if (iter != formatMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ static const FormatType defaultInfo;
+ return defaultInfo;
+ }
+}
+
+const Type &GetTypeInfo(GLenum type)
+{
+ static const TypeInfoMap infoMap = BuildTypeInfoMap();
+ TypeInfoMap::const_iterator iter = infoMap.find(type);
+ if (iter != infoMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ static const Type defaultInfo;
+ return defaultInfo;
+ }
+}
+
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat)
+{
+ const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
+ InternalFormatInfoMap::const_iterator iter = formatMap.find(internalFormat);
+ if (iter != formatMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ static const InternalFormat defaultInternalFormat;
+ return defaultInternalFormat;
+ }
+}
+
+GLuint InternalFormat::computeRowPitch(GLenum type, GLsizei width, GLint alignment) const
+{
+ ASSERT(alignment > 0 && isPow2(alignment));
+ return rx::roundUp(computeBlockSize(type, width, 1), static_cast<GLuint>(alignment));
+}
+
+GLuint InternalFormat::computeDepthPitch(GLenum type, GLsizei width, GLsizei height, GLint alignment) const
+{
+ return computeRowPitch(type, width, alignment) * height;
+}
+
+GLuint InternalFormat::computeBlockSize(GLenum type, GLsizei width, GLsizei height) const
+{
+ if (compressed)
+ {
+ GLsizei numBlocksWide = (width + compressedBlockWidth - 1) / compressedBlockWidth;
+ GLsizei numBlocksHight = (height + compressedBlockHeight - 1) / compressedBlockHeight;
+ return (pixelBytes * numBlocksWide * numBlocksHight);
+ }
+ else
+ {
+ const Type &typeInfo = GetTypeInfo(type);
+ if (typeInfo.specialInterpretation)
+ {
+ return typeInfo.bytes * width * height;
+ }
+ else
+ {
+ return componentCount * typeInfo.bytes * width * height;
+ }
+ }
+}
+
+GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type)
+{
+ const InternalFormat& formatInfo = GetInternalFormatInfo(internalFormat);
+ return (formatInfo.pixelBytes > 0) ? internalFormat : GetFormatTypeInfo(internalFormat, type).internalFormat;
+}
+
+const FormatSet &GetAllSizedInternalFormats()
+{
+ static FormatSet formatSet = BuildAllSizedInternalFormatSet();
+ return formatSet;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/formatutils.h b/src/3rdparty/angle/src/libGLESv2/formatutils.h
new file mode 100644
index 0000000000..25106a52e5
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/formatutils.h
@@ -0,0 +1,106 @@
+//
+// 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 LIBGLESV2_FORMATUTILS_H_
+#define LIBGLESV2_FORMATUTILS_H_
+
+#include "libGLESv2/Caps.h"
+#include "libGLESv2/angletypes.h"
+
+#include "angle_gl.h"
+
+#include <cstddef>
+#include <cstdint>
+
+typedef void (*MipGenerationFunction)(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 (*LoadImageFunction)(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);
+
+typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth,
+ uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
+
+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);
+
+typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+namespace gl
+{
+
+struct FormatType
+{
+ FormatType();
+
+ GLenum internalFormat;
+ ColorWriteFunction colorWriteFunction;
+};
+const FormatType &GetFormatTypeInfo(GLenum format, GLenum type);
+
+struct Type
+{
+ Type();
+
+ GLuint bytes;
+ bool specialInterpretation;
+};
+const Type &GetTypeInfo(GLenum type);
+
+struct InternalFormat
+{
+ 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)(GLuint, const Extensions &);
+ SupportCheckFunction textureSupport;
+ SupportCheckFunction renderSupport;
+ SupportCheckFunction filterSupport;
+
+ GLuint computeRowPitch(GLenum type, GLsizei width, GLint alignment) const;
+ GLuint computeDepthPitch(GLenum type, GLsizei width, GLsizei height, GLint alignment) const;
+ GLuint computeBlockSize(GLenum type, GLsizei width, GLsizei height) const;
+};
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat);
+
+GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type);
+
+typedef std::set<GLenum> FormatSet;
+const FormatSet &GetAllSizedInternalFormats();
+
+}
+
+#endif // LIBGLESV2_FORMATUTILS_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
index 814dfbf965..07f5d47473 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
@@ -1,16 +1,20 @@
-#include "precompiled.h"
//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// 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.
//
// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
+#undef GL_APICALL
+#define GL_APICALL
+#define GL_GLEXT_PROTOTYPES
+
#include "common/version.h"
+#include "common/utilities.h"
#include "libGLESv2/main.h"
-#include "libGLESv2/utilities.h"
+#include "libGLESv2/formatutils.h"
#include "libGLESv2/Buffer.h"
#include "libGLESv2/Fence.h"
#include "libGLESv2/Framebuffer.h"
@@ -20,263 +24,36 @@
#include "libGLESv2/Texture.h"
#include "libGLESv2/Query.h"
#include "libGLESv2/Context.h"
+#include "libGLESv2/VertexArray.h"
+#include "libGLESv2/VertexAttribute.h"
+#include "libGLESv2/TransformFeedback.h"
+#include "libGLESv2/FramebufferAttachment.h"
-bool validImageSize(GLint level, GLsizei width, GLsizei height)
-{
- if (level < 0 || width < 0 || height < 0)
- {
- return false;
- }
-
- if (gl::getContext() && gl::getContext()->supportsNonPower2Texture())
- {
- return true;
- }
-
- if (level == 0)
- {
- return true;
- }
-
- if (gl::isPow2(width) && gl::isPow2(height))
- {
- return true;
- }
-
- return false;
-}
-
-// Verify that format/type are one of the combinations from table 3.4.
-bool checkTextureFormatType(GLenum format, GLenum type)
-{
- // validate <format> by itself (used as secondary key below)
- switch (format)
- {
- case GL_RGBA:
- case GL_BGRA_EXT:
- case GL_RGB:
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_STENCIL_OES:
- break;
- default:
- return gl::error(GL_INVALID_ENUM, false);
- }
-
- // invalid <type> -> sets INVALID_ENUM
- // invalid <format>+<type> combination -> sets INVALID_OPERATION
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- switch (format)
- {
- case GL_RGBA:
- case GL_BGRA_EXT:
- case GL_RGB:
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- return true;
- default:
- return gl::error(GL_INVALID_OPERATION, false);
- }
-
- case GL_FLOAT:
- case GL_HALF_FLOAT_OES:
- switch (format)
- {
- case GL_RGBA:
- case GL_RGB:
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- return true;
- default:
- return gl::error(GL_INVALID_OPERATION, false);
- }
-
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_5_5_5_1:
- switch (format)
- {
- case GL_RGBA:
- return true;
- default:
- return gl::error(GL_INVALID_OPERATION, false);
- }
-
- case GL_UNSIGNED_SHORT_5_6_5:
- switch (format)
- {
- case GL_RGB:
- return true;
- default:
- return gl::error(GL_INVALID_OPERATION, false);
- }
-
- case GL_UNSIGNED_SHORT:
- case GL_UNSIGNED_INT:
- switch (format)
- {
- case GL_DEPTH_COMPONENT:
- return true;
- default:
- return gl::error(GL_INVALID_OPERATION, false);
- }
-
- case GL_UNSIGNED_INT_24_8_OES:
- switch (format)
- {
- case GL_DEPTH_STENCIL_OES:
- return true;
- default:
- return gl::error(GL_INVALID_OPERATION, false);
- }
-
- default:
- return gl::error(GL_INVALID_ENUM, false);
- }
-}
-
-bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height,
- GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type,
- gl::Texture2D *texture)
-{
- if (!texture)
- {
- return gl::error(GL_INVALID_OPERATION, false);
- }
-
- if (compressed != texture->isCompressed(level))
- {
- return gl::error(GL_INVALID_OPERATION, false);
- }
-
- if (format != GL_NONE)
- {
- GLenum internalformat = gl::ConvertSizedInternalFormat(format, type);
- if (internalformat != texture->getInternalFormat(level))
- {
- return gl::error(GL_INVALID_OPERATION, false);
- }
- }
-
- if (compressed)
- {
- if ((width % 4 != 0 && width != texture->getWidth(0)) ||
- (height % 4 != 0 && height != texture->getHeight(0)))
- {
- return gl::error(GL_INVALID_OPERATION, false);
- }
- }
-
- if (xoffset + width > texture->getWidth(level) ||
- yoffset + height > texture->getHeight(level))
- {
- return gl::error(GL_INVALID_VALUE, false);
- }
-
- return true;
-}
-
-bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height,
- GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type,
- gl::TextureCubeMap *texture)
-{
- if (!texture)
- {
- return gl::error(GL_INVALID_OPERATION, false);
- }
-
- if (compressed != texture->isCompressed(target, level))
- {
- return gl::error(GL_INVALID_OPERATION, false);
- }
-
- if (format != GL_NONE)
- {
- GLenum internalformat = gl::ConvertSizedInternalFormat(format, type);
- if (internalformat != texture->getInternalFormat(target, level))
- {
- return gl::error(GL_INVALID_OPERATION, false);
- }
- }
-
- if (compressed)
- {
- if ((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
- (height % 4 != 0 && height != texture->getHeight(target, 0)))
- {
- return gl::error(GL_INVALID_OPERATION, false);
- }
- }
-
- if (xoffset + width > texture->getWidth(target, level) ||
- yoffset + height > texture->getHeight(target, level))
- {
- return gl::error(GL_INVALID_VALUE, false);
- }
+#include "libGLESv2/validationES.h"
+#include "libGLESv2/validationES2.h"
+#include "libGLESv2/validationES3.h"
+#include "libGLESv2/queryconversions.h"
- return true;
-}
-
-// check for combinations of format and type that are valid for ReadPixels
-bool validReadFormatType(GLenum format, GLenum type)
-{
- switch (format)
- {
- case GL_RGBA:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- break;
- default:
- return false;
- }
- break;
- case GL_BGRA_EXT:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
- break;
- default:
- return false;
- }
- break;
- default:
- return false;
- }
- return true;
-}
extern "C"
{
+// OpenGL ES 2.0 functions
+
void __stdcall glActiveTexture(GLenum texture)
{
EVENT("(GLenum texture = 0x%X)", texture);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
{
- if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1)
- {
- return gl::error(GL_INVALID_ENUM);
- }
-
- context->setActiveSampler(texture - GL_TEXTURE0);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ context->getState().setActiveSampler(texture - GL_TEXTURE0);
}
}
@@ -284,48 +61,45 @@ void __stdcall glAttachShader(GLuint program, GLuint shader)
{
EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
+ gl::Shader *shaderObject = context->getShader(shader);
- if (context)
+ if (!programObject)
{
- gl::Program *programObject = context->getProgram(program);
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!programObject)
+ if (context->getShader(program))
{
- if (context->getShader(program))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
-
- if (!shaderObject)
+ else
{
- if (context->getProgram(shader))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+ }
- if (!programObject->attachShader(shaderObject))
+ if (!shaderObject)
+ {
+ if (context->getProgram(shader))
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ if (!programObject->attachShader(shaderObject))
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
}
}
@@ -333,75 +107,59 @@ void __stdcall glBeginQueryEXT(GLenum target, GLuint id)
{
EVENT("(GLenum target = 0x%X, GLuint %d)", target, id);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- switch (target)
- {
- case GL_ANY_SAMPLES_PASSED_EXT:
- case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- if (id == 0)
+ if (!ValidateBeginQuery(context, target, id))
{
- return gl::error(GL_INVALID_OPERATION);
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ gl::Error error = context->beginQuery(target, id);
+ if (error.isError())
{
- context->beginQuery(target, id);
+ context->recordError(error);
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
{
EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (index >= gl::MAX_VERTEX_ATTRIBS)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context)
+ if (!programObject)
{
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
+ if (context->getShader(program))
{
- if (context->getShader(program))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
-
- if (strncmp(name, "gl_", 3) == 0)
+ else
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+ }
- programObject->bindAttributeLocation(index, name);
+ if (strncmp(name, "gl_", 3) == 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ programObject->bindAttributeLocation(index, name);
}
}
@@ -409,84 +167,88 @@ void __stdcall glBindBuffer(GLenum target, GLuint buffer)
{
EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ if (!gl::ValidBufferTarget(context, target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- if (context)
+ switch (target)
{
- switch (target)
- {
- case GL_ARRAY_BUFFER:
- context->bindArrayBuffer(buffer);
- return;
- case GL_ELEMENT_ARRAY_BUFFER:
- context->bindElementArrayBuffer(buffer);
- return;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
+ case GL_ARRAY_BUFFER:
+ context->bindArrayBuffer(buffer);
+ return;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ context->bindElementArrayBuffer(buffer);
+ return;
+ case GL_COPY_READ_BUFFER:
+ context->bindCopyReadBuffer(buffer);
+ return;
+ case GL_COPY_WRITE_BUFFER:
+ context->bindCopyWriteBuffer(buffer);
+ return;
+ case GL_PIXEL_PACK_BUFFER:
+ context->bindPixelPackBuffer(buffer);
+ return;
+ case GL_PIXEL_UNPACK_BUFFER:
+ context->bindPixelUnpackBuffer(buffer);
+ return;
+ case GL_UNIFORM_BUFFER:
+ context->bindGenericUniformBuffer(buffer);
+ return;
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ context->bindGenericTransformFeedbackBuffer(buffer);
+ return;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer)
{
EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+ if (!gl::ValidFramebufferTarget(target))
{
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
+ {
+ context->bindReadFramebuffer(framebuffer);
+ }
- if (context)
+ if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
{
- if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
- {
- context->bindReadFramebuffer(framebuffer);
- }
-
- if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
- {
- context->bindDrawFramebuffer(framebuffer);
- }
+ context->bindDrawFramebuffer(framebuffer);
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer)
{
EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (target != GL_RENDERBUFFER)
{
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->bindRenderbuffer(renderbuffer);
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ context->bindRenderbuffer(renderbuffer);
}
}
@@ -494,35 +256,38 @@ void __stdcall glBindTexture(GLenum target, GLuint texture)
{
EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Texture *textureObject = context->getTexture(texture);
- if (context)
+ if (textureObject && textureObject->getTarget() != target && texture != 0)
{
- gl::Texture *textureObject = context->getTexture(texture);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (textureObject && textureObject->getTarget() != target && texture != 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_CUBE_MAP:
+ break;
- switch (target)
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ if (context->getClientVersion() < 3)
{
- case GL_TEXTURE_2D:
- context->bindTexture2D(texture);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
return;
- case GL_TEXTURE_CUBE_MAP:
- context->bindTextureCubeMap(texture);
- return;
- default:
- return gl::error(GL_INVALID_ENUM);
}
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ context->bindTexture(target, texture);
}
}
@@ -531,18 +296,11 @@ void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp
EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
red, green, blue, alpha);
- try
- {
- gl::Context* context = gl::getNonLostContext();
+ gl::Context* context = gl::getNonLostContext();
- if (context)
- {
- context->setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha));
- }
- }
- catch(std::bad_alloc&)
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha));
}
}
@@ -555,16 +313,21 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
{
EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
switch (modeRGB)
{
case GL_FUNC_ADD:
case GL_FUNC_SUBTRACT:
case GL_FUNC_REVERSE_SUBTRACT:
+ case GL_MIN:
+ case GL_MAX:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
switch (modeAlpha)
@@ -572,21 +335,16 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
case GL_FUNC_ADD:
case GL_FUNC_SUBTRACT:
case GL_FUNC_REVERSE_SUBTRACT:
+ case GL_MIN:
+ case GL_MAX:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setBlendEquation(modeRGB, modeAlpha);
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setBlendEquation(modeRGB, modeAlpha);
}
}
@@ -600,7 +358,8 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha
EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
srcRGB, dstRGB, srcAlpha, dstAlpha);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
switch (srcRGB)
{
@@ -620,8 +379,10 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha
case GL_ONE_MINUS_CONSTANT_ALPHA:
case GL_SRC_ALPHA_SATURATE:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
switch (dstRGB)
@@ -641,8 +402,18 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha
case GL_CONSTANT_ALPHA:
case GL_ONE_MINUS_CONSTANT_ALPHA:
break;
+
+ case GL_SRC_ALPHA_SATURATE:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
switch (srcAlpha)
@@ -663,8 +434,10 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha
case GL_ONE_MINUS_CONSTANT_ALPHA:
case GL_SRC_ALPHA_SATURATE:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
switch (dstAlpha)
@@ -684,8 +457,18 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha
case GL_CONSTANT_ALPHA:
case GL_ONE_MINUS_CONSTANT_ALPHA:
break;
+
+ case GL_SRC_ALPHA_SATURATE:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
@@ -697,19 +480,11 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha
if (constantColorUsed && constantAlphaUsed)
{
ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL");
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
}
}
@@ -718,11 +493,13 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
target, size, data, usage);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (size < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
switch (usage)
@@ -731,40 +508,46 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
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->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (!gl::ValidBufferTarget(context, target))
{
- gl::Buffer *buffer;
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- switch (target)
- {
- case GL_ARRAY_BUFFER:
- buffer = context->getArrayBuffer();
- break;
- case GL_ELEMENT_ARRAY_BUFFER:
- buffer = context->getElementArrayBuffer();
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
+ gl::Buffer *buffer = context->getState().getTargetBuffer(target);
- if (!buffer)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ if (!buffer)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- buffer->bufferData(data, size, usage);
+ gl::Error error = buffer->bufferData(data, size, usage);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
@@ -772,11 +555,13 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
target, offset, size, data);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (size < 0 || offset < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
if (data == NULL)
@@ -784,74 +569,64 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
return;
}
- gl::Context *context = gl::getNonLostContext();
+ if (!gl::ValidBufferTarget(context, target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ gl::Buffer *buffer = context->getState().getTargetBuffer(target);
- if (context)
+ if (!buffer)
{
- gl::Buffer *buffer;
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- switch (target)
- {
- case GL_ARRAY_BUFFER:
- buffer = context->getArrayBuffer();
- break;
- case GL_ELEMENT_ARRAY_BUFFER:
- buffer = context->getElementArrayBuffer();
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
+ if (buffer->isMapped())
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (!buffer)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ // Check for possible overflow of size + offset
+ if (!rx::IsUnsignedAdditionSafe<size_t>(size, offset))
+ {
+ context->recordError(gl::Error(GL_OUT_OF_MEMORY));
+ return;
+ }
- if ((size_t)size + offset > buffer->size())
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ if (size + offset > buffer->getSize())
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- buffer->bufferSubData(data, size, offset);
+ gl::Error error = buffer->bufferSubData(data, size, offset);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
GLenum __stdcall glCheckFramebufferStatus(GLenum target)
{
EVENT("(GLenum target = 0x%X)", target);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+ if (!gl::ValidFramebufferTarget(target))
{
- return gl::error(GL_INVALID_ENUM, 0);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return 0;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- gl::Framebuffer *framebuffer = NULL;
- if (target == GL_READ_FRAMEBUFFER_ANGLE)
- {
- framebuffer = context->getReadFramebuffer();
- }
- else
- {
- framebuffer = context->getDrawFramebuffer();
- }
-
- return framebuffer->completeness();
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, 0);
+ gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+ return framebuffer->completeness();
}
return 0;
@@ -859,20 +634,31 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target)
void __stdcall glClear(GLbitfield mask)
{
- EVENT("(GLbitfield mask = %X)", mask);
+ EVENT("(GLbitfield mask = 0x%X)", mask);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
- if (context)
+ if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
{
- context->clear(mask);
+ context->recordError(gl::Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return;
+ }
+
+ if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ gl::Error error = context->clear(mask);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
}
}
@@ -881,18 +667,10 @@ void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp
EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
red, green, blue, alpha);
- try
- {
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setClearColor(red, green, blue, alpha);
- }
- }
- catch(std::bad_alloc&)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setClearColor(red, green, blue, alpha);
}
}
@@ -900,18 +678,10 @@ void __stdcall glClearDepthf(GLclampf depth)
{
EVENT("(GLclampf depth = %f)", depth);
- try
- {
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setClearDepth(depth);
- }
- }
- catch(std::bad_alloc&)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setClearDepth(depth);
}
}
@@ -919,38 +689,22 @@ void __stdcall glClearStencil(GLint s)
{
EVENT("(GLint s = %d)", s);
- try
- {
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setClearStencil(s);
- }
- }
- catch(std::bad_alloc&)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setClearStencil(s);
}
}
void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
{
- EVENT("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
+ EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)",
red, green, blue, alpha);
- try
- {
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
- }
- }
- catch(std::bad_alloc&)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
}
}
@@ -958,191 +712,85 @@ void __stdcall glCompileShader(GLuint shader)
{
EVENT("(GLuint shader = %d)", shader);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Shader *shaderObject = context->getShader(shader);
- if (context)
+ if (!shaderObject)
{
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!shaderObject)
+ if (context->getProgram(shader))
{
- if (context->getProgram(shader))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
-
- shaderObject->compile();
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ shaderObject->compile();
}
}
-void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
+void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
GLint border, GLsizei imageSize, const GLvoid* data)
{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
"GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
target, level, internalformat, width, height, border, imageSize, data);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (!validImageSize(level, width, height) || border != 0 || imageSize < 0)
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- 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:
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- if (border != 0)
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2TexImageParameters(context, target, level, internalformat, true, false,
+ 0, 0, width, height, border, GL_NONE, GL_NONE, data))
{
- return gl::error(GL_INVALID_OPERATION);
+ return;
}
- if (width != 1 && width != 2 && width % 4 != 0)
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3TexImageParameters(context, target, level, internalformat, true, false,
+ 0, 0, 0, width, height, 1, border, GL_NONE, GL_NONE, data))
{
- return gl::error(GL_INVALID_OPERATION);
+ return;
}
- if (height != 1 && height != 2 && height % 4 != 0)
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ switch (target)
{
- if (level > context->getMaximumTextureLevel())
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- if (width > (context->getMaximumTextureDimension() >> level) ||
- height > (context->getMaximumTextureDimension() >> level))
- {
- return gl::error(GL_INVALID_VALUE);
- }
- 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 (width != height)
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- if (width > (context->getMaximumCubeTextureDimension() >> level) ||
- height > (context->getMaximumCubeTextureDimension() >> level))
- {
- return gl::error(GL_INVALID_VALUE);
- }
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- switch (internalformat) {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (!context->supportsDXT1Textures())
- {
- return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (!context->supportsDXT3Textures())
- {
- return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (!context->supportsDXT5Textures())
- {
- return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
- }
- break;
- default: UNREACHABLE();
- }
-
- if (imageSize != gl::ComputeCompressedSize(width, height, internalformat))
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- if (target == GL_TEXTURE_2D)
+ case GL_TEXTURE_2D:
{
gl::Texture2D *texture = context->getTexture2D();
-
- if (!texture)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- if (texture->isImmutable())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
}
- else
+ 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:
{
gl::TextureCubeMap *texture = context->getTextureCubeMap();
-
- if (!texture)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- if (texture->isImmutable())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- switch (target)
- {
- 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:
- texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
- break;
- default: UNREACHABLE();
- }
+ texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
}
- }
+ break;
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
}
}
@@ -1154,103 +802,56 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs
"GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
target, level, xoffset, yoffset, width, height, format, imageSize, data);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (!gl::IsInternalTextureTarget(target))
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true,
+ xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data))
{
- return gl::error(GL_INVALID_ENUM);
- }
-
- if (xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
- {
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- switch (format)
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true,
+ xoffset, yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, data))
{
- 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:
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ return;
}
- if (width == 0 || height == 0 || data == NULL)
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
{
+ context->recordError(gl::Error(GL_INVALID_VALUE));
return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ switch (target)
{
- if (level > context->getMaximumTextureLevel())
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- switch (format) {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (!context->supportsDXT1Textures())
- {
- return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (!context->supportsDXT3Textures())
- {
- return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (!context->supportsDXT5Textures())
- {
- return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
- }
- break;
- default: UNREACHABLE();
- }
-
- if (imageSize != gl::ComputeCompressedSize(width, height, format))
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- if (xoffset % 4 != 0 || yoffset % 4 != 0)
- {
- return gl::error(GL_INVALID_OPERATION); // we wait to check the offsets until this point, because the multiple-of-four restriction
- // does not exist unless DXT textures are supported.
- }
-
- if (target == GL_TEXTURE_2D)
+ case GL_TEXTURE_2D:
{
gl::Texture2D *texture = context->getTexture2D();
- if (validateSubImageParams2D(true, width, height, xoffset, yoffset, level, format, GL_NONE, texture))
- {
- texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
- }
+ texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
}
- else if (gl::IsCubemapTextureTarget(target))
+ 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:
{
gl::TextureCubeMap *texture = context->getTextureCubeMap();
- if (validateSubImageParamsCube(true, width, height, xoffset, yoffset, target, level, format, GL_NONE, texture))
- {
- texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
- }
- }
- else
- {
- UNREACHABLE();
+ texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
}
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
@@ -1259,194 +860,51 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
"GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
target, level, internalformat, x, y, width, height, border);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (!validImageSize(level, width, height))
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2CopyTexImageParameters(context, target, level, internalformat, false,
+ 0, 0, x, y, width, height, border))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- if (border != 0)
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3CopyTexImageParameters(context, target, level, internalformat, false,
+ 0, 0, 0, x, y, width, height, border))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
- if (context)
+ switch (target)
{
- if (level > context->getMaximumTextureLevel())
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- if (width > (context->getMaximumTextureDimension() >> level) ||
- height > (context->getMaximumTextureDimension() >> level))
- {
- return gl::error(GL_INVALID_VALUE);
- }
- 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 (width != height)
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- if (width > (context->getMaximumCubeTextureDimension() >> level) ||
- height > (context->getMaximumCubeTextureDimension() >> level))
- {
- return gl::error(GL_INVALID_VALUE);
- }
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- gl::Framebuffer *framebuffer = context->getReadFramebuffer();
-
- if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
- {
- return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
- }
-
- if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- gl::Renderbuffer *source = framebuffer->getReadColorbuffer();
- GLenum colorbufferFormat = source->getInternalFormat();
-
- // [OpenGL ES 2.0.24] table 3.9
- 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)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- break;
- case GL_LUMINANCE:
- 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)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- break;
- case GL_LUMINANCE_ALPHA:
- case GL_RGBA:
- if (colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- break;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (context->supportsDXT1Textures())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (context->supportsDXT3Textures())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (context->supportsDXT5Textures())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_ENUM);
- }
- 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->supportsDepthTextures())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_ENUM);
- }
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- if (target == GL_TEXTURE_2D)
+ case GL_TEXTURE_2D:
{
gl::Texture2D *texture = context->getTexture2D();
-
- if (!texture)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- if (texture->isImmutable())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
}
- else if (gl::IsCubemapTextureTarget(target))
+ 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:
{
gl::TextureCubeMap *texture = context->getTextureCubeMap();
-
- if (!texture)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- if (texture->isImmutable())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
}
- else UNREACHABLE();
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
@@ -1455,148 +913,61 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
"GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
target, level, xoffset, yoffset, x, y, width, height);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (!gl::IsInternalTextureTarget(target))
- {
- return gl::error(GL_INVALID_ENUM);
- }
-
- if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true,
+ xoffset, yoffset, x, y, width, height, 0))
{
- return gl::error(GL_INVALID_VALUE);
- }
-
- if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
- {
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- if (width == 0 || height == 0)
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true,
+ xoffset, yoffset, 0, x, y, width, height, 0))
{
return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
- if (context)
+ switch (target)
{
- if (level > context->getMaximumTextureLevel())
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- gl::Framebuffer *framebuffer = context->getReadFramebuffer();
-
- if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
- {
- return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
- }
-
- if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- gl::Renderbuffer *source = framebuffer->getReadColorbuffer();
- GLenum colorbufferFormat = source->getInternalFormat();
- gl::Texture *texture = NULL;
- GLenum textureFormat = GL_RGBA;
-
- if (target == GL_TEXTURE_2D)
+ case GL_TEXTURE_2D:
{
- gl::Texture2D *tex2d = context->getTexture2D();
-
- if (!validateSubImageParams2D(false, width, height, xoffset, yoffset, level, GL_NONE, GL_NONE, tex2d))
- {
- return; // error already registered by validateSubImageParams
- }
- textureFormat = gl::ExtractFormat(tex2d->getInternalFormat(level));
- texture = tex2d;
- }
- else if (gl::IsCubemapTextureTarget(target))
- {
- gl::TextureCubeMap *texcube = context->getTextureCubeMap();
-
- if (!validateSubImageParamsCube(false, width, height, xoffset, yoffset, target, level, GL_NONE, GL_NONE, texcube))
- {
- return; // error already registered by validateSubImageParams
- }
- textureFormat = gl::ExtractFormat(texcube->getInternalFormat(target, level));
- texture = texcube;
+ gl::Texture2D *texture = context->getTexture2D();
+ texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
}
- else UNREACHABLE();
+ break;
- // [OpenGL ES 2.0.24] table 3.9
- switch (textureFormat)
+ 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:
{
- case GL_ALPHA:
- if (colorbufferFormat != GL_ALPHA8_EXT &&
- colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- break;
- case GL_LUMINANCE:
- case GL_RGB:
- if (colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- break;
- case GL_LUMINANCE_ALPHA:
- case GL_RGBA:
- if (colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- 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:
- return gl::error(GL_INVALID_OPERATION);
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_STENCIL_OES:
- return gl::error(GL_INVALID_OPERATION);
- default:
- return gl::error(GL_INVALID_OPERATION);
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+ texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
}
+ break;
- texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer);
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
-
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
GLuint __stdcall glCreateProgram(void)
{
EVENT("()");
- try
- {
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- return context->createProgram();
- }
- }
- catch(std::bad_alloc&)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY, 0);
+ return context->createProgram();
}
return 0;
@@ -1606,26 +977,20 @@ GLuint __stdcall glCreateShader(GLenum type)
{
EVENT("(GLenum type = 0x%X)", type);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ switch (type)
{
- switch (type)
- {
- case GL_FRAGMENT_SHADER:
- case GL_VERTEX_SHADER:
- return context->createShader(type);
- default:
- return gl::error(GL_INVALID_ENUM, 0);
- }
+ case GL_FRAGMENT_SHADER:
+ case GL_VERTEX_SHADER:
+ return context->createShader(type);
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return 0;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, 0);
- }
return 0;
}
@@ -1634,29 +999,22 @@ void __stdcall glCullFace(GLenum mode)
{
EVENT("(GLenum mode = 0x%X)", mode);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
switch (mode)
{
case GL_FRONT:
case GL_BACK:
case GL_FRONT_AND_BACK:
- {
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setCullMode(mode);
- }
- }
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ context->getState().setCullMode(mode);
}
}
@@ -1664,119 +1022,92 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers)
{
EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ for (int i = 0; i < n; i++)
{
- for (int i = 0; i < n; i++)
- {
- context->deleteBuffer(buffers[i]);
- }
+ context->deleteBuffer(buffers[i]);
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences)
{
EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ for (int i = 0; i < n; i++)
{
- for (int i = 0; i < n; i++)
- {
- context->deleteFence(fences[i]);
- }
+ context->deleteFenceNV(fences[i]);
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
{
EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ for (int i = 0; i < n; i++)
{
- for (int i = 0; i < n; i++)
+ if (framebuffers[i] != 0)
{
- if (framebuffers[i] != 0)
- {
- context->deleteFramebuffer(framebuffers[i]);
- }
+ context->deleteFramebuffer(framebuffers[i]);
}
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glDeleteProgram(GLuint program)
{
EVENT("(GLuint program = %d)", program);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (program == 0)
{
return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (!context->getProgram(program))
{
- if (!context->getProgram(program))
+ if(context->getShader(program))
{
- if(context->getShader(program))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
-
- context->deleteProgram(program);
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ context->deleteProgram(program);
}
}
@@ -1784,89 +1115,69 @@ void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
{
EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ for (int i = 0; i < n; i++)
{
- for (int i = 0; i < n; i++)
- {
- context->deleteQuery(ids[i]);
- }
+ context->deleteQuery(ids[i]);
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
{
EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ for (int i = 0; i < n; i++)
{
- for (int i = 0; i < n; i++)
- {
- context->deleteRenderbuffer(renderbuffers[i]);
- }
+ context->deleteRenderbuffer(renderbuffers[i]);
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glDeleteShader(GLuint shader)
{
EVENT("(GLuint shader = %d)", shader);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (shader == 0)
{
return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (!context->getShader(shader))
{
- if (!context->getShader(shader))
+ if(context->getProgram(shader))
{
- if(context->getProgram(shader))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
-
- context->deleteShader(shader);
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ context->deleteShader(shader);
}
}
@@ -1874,37 +1185,31 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures)
{
EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ for (int i = 0; i < n; i++)
{
- for (int i = 0; i < n; i++)
+ if (textures[i] != 0)
{
- if (textures[i] != 0)
- {
- context->deleteTexture(textures[i]);
- }
+ context->deleteTexture(textures[i]);
}
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glDepthFunc(GLenum func)
{
EVENT("(GLenum func = 0x%X)", func);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
switch (func)
{
@@ -1916,40 +1221,24 @@ void __stdcall glDepthFunc(GLenum func)
case GL_GREATER:
case GL_GEQUAL:
case GL_NOTEQUAL:
+ context->getState().setDepthFunc(func);
break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- context->setDepthFunc(func);
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glDepthMask(GLboolean flag)
{
- EVENT("(GLboolean flag = %d)", flag);
-
- try
- {
- gl::Context *context = gl::getNonLostContext();
+ EVENT("(GLboolean flag = %u)", flag);
- if (context)
- {
- context->setDepthMask(flag != GL_FALSE);
- }
- }
- catch(std::bad_alloc&)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setDepthMask(flag != GL_FALSE);
}
}
@@ -1957,18 +1246,10 @@ void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar)
{
EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
- try
- {
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setDepthRange(zNear, zFar);
- }
- }
- catch(std::bad_alloc&)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setDepthRange(zNear, zFar);
}
}
@@ -1976,52 +1257,48 @@ void __stdcall glDetachShader(GLuint program, GLuint shader)
{
EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
+ gl::Shader *shaderObject = context->getShader(shader);
- if (context)
+ if (!programObject)
{
-
- gl::Program *programObject = context->getProgram(program);
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!programObject)
+ gl::Shader *shaderByProgramHandle;
+ shaderByProgramHandle = context->getShader(program);
+ if (!shaderByProgramHandle)
{
- gl::Shader *shaderByProgramHandle;
- shaderByProgramHandle = context->getShader(program);
- if (!shaderByProgramHandle)
- {
- return gl::error(GL_INVALID_VALUE);
- }
- else
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
-
- if (!shaderObject)
+ else
{
- gl::Program *programByShaderHandle = context->getProgram(shader);
- if (!programByShaderHandle)
- {
- return gl::error(GL_INVALID_VALUE);
- }
- else
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
+ }
- if (!programObject->detachShader(shaderObject))
+ if (!shaderObject)
+ {
+ gl::Program *programByShaderHandle = context->getProgram(shader);
+ if (!programByShaderHandle)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ else
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ if (!programObject->detachShader(shaderObject))
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
}
}
@@ -2029,31 +1306,16 @@ void __stdcall glDisable(GLenum cap)
{
EVENT("(GLenum cap = 0x%X)", cap);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (!ValidCap(context, cap))
{
- switch (cap)
- {
- case GL_CULL_FACE: context->setCullFace(false); break;
- case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(false); break;
- case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break;
- case GL_SAMPLE_COVERAGE: context->setSampleCoverage(false); break;
- case GL_SCISSOR_TEST: context->setScissorTest(false); break;
- case GL_STENCIL_TEST: context->setStencilTest(false); break;
- case GL_DEPTH_TEST: context->setDepthTest(false); break;
- case GL_BLEND: context->setBlend(false); break;
- case GL_DITHER: context->setDither(false); break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ context->getState().setEnableFeature(cap, false);
}
}
@@ -2061,23 +1323,16 @@ void __stdcall glDisableVertexAttribArray(GLuint index)
{
EVENT("(GLuint index = %d)", index);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (index >= gl::MAX_VERTEX_ATTRIBS)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setEnableVertexAttribArray(index, false);
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setEnableVertexAttribArray(index, false);
}
}
@@ -2085,51 +1340,42 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
{
EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0 || first < 0)
+ if (!ValidateDrawArrays(context, mode, first, count, 0))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ gl::Error error = context->drawArrays(mode, first, count, 0);
+ if (error.isError())
{
- context->drawArrays(mode, first, count, 0);
+ context->recordError(error);
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
{
EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0 || first < 0 || primcount < 0)
+ if (!ValidateDrawArraysInstancedANGLE(context, mode, first, count, primcount))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- if (primcount > 0)
+ gl::Error error = context->drawArrays(mode, first, count, primcount);
+ if (error.isError())
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->drawArrays(mode, first, count, primcount);
- }
+ context->recordError(error);
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
@@ -2137,39 +1383,22 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv
EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
mode, count, type, indices);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0)
+ rx::RangeUI indexRange;
+ if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ gl::Error error = context->drawElements(mode, count, type, indices, 0, indexRange);
+ if (error.isError())
{
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT:
- break;
- case GL_UNSIGNED_INT:
- if (!context->supports32bitIndices())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- context->drawElements(mode, count, type, indices, 0);
+ context->recordError(error);
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount)
@@ -2177,73 +1406,38 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t
EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)",
mode, count, type, indices, primcount);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0 || primcount < 0)
+ rx::RangeUI indexRange;
+ if (!ValidateDrawElementsInstancedANGLE(context, mode, count, type, indices, primcount, &indexRange))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- if (primcount > 0)
+ gl::Error error = context->drawElements(mode, count, type, indices, primcount, indexRange);
+ if (error.isError())
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT:
- break;
- case GL_UNSIGNED_INT:
- if (!context->supports32bitIndices())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- context->drawElements(mode, count, type, indices, primcount);
- }
+ context->recordError(error);
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glEnable(GLenum cap)
{
EVENT("(GLenum cap = 0x%X)", cap);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (!ValidCap(context, cap))
{
- switch (cap)
- {
- case GL_CULL_FACE: context->setCullFace(true); break;
- case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(true); break;
- case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(true); break;
- case GL_SAMPLE_COVERAGE: context->setSampleCoverage(true); break;
- case GL_SCISSOR_TEST: context->setScissorTest(true); break;
- case GL_STENCIL_TEST: context->setStencilTest(true); break;
- case GL_DEPTH_TEST: context->setDepthTest(true); break;
- case GL_BLEND: context->setBlend(true); break;
- case GL_DITHER: context->setDither(true); break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ context->getState().setEnableFeature(cap, true);
}
}
@@ -2251,23 +1445,16 @@ void __stdcall glEnableVertexAttribArray(GLuint index)
{
EVENT("(GLuint index = %d)", index);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (index >= gl::MAX_VERTEX_ATTRIBS)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setEnableVertexAttribArray(index, true);
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setEnableVertexAttribArray(index, true);
}
}
@@ -2275,53 +1462,45 @@ void __stdcall glEndQueryEXT(GLenum target)
{
EVENT("GLenum target = 0x%X)", target);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- switch (target)
+ if (!ValidateEndQuery(context, target))
{
- case GL_ANY_SAMPLES_PASSED_EXT:
- case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ gl::Error error = context->endQuery(target);
+ if (error.isError())
{
- context->endQuery(target);
+ context->recordError(error);
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glFinishFenceNV(GLuint fence)
{
EVENT("(GLuint fence = %d)", fence);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::FenceNV *fenceObject = context->getFenceNV(fence);
- if (context)
+ if (fenceObject == NULL)
{
- gl::Fence* fenceObject = context->getFence(fence);
-
- if (fenceObject == NULL)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- fenceObject->finishFence();
+ if (fenceObject->isFence() != GL_TRUE)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ fenceObject->finishFence();
}
}
@@ -2329,18 +1508,10 @@ void __stdcall glFinish(void)
{
EVENT("()");
- try
- {
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->sync(true);
- }
- }
- catch(std::bad_alloc&)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ context->sync(true);
}
}
@@ -2348,18 +1519,10 @@ void __stdcall glFlush(void)
{
EVENT("()");
- try
- {
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->sync(false);
- }
- }
- catch(std::bad_alloc&)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ context->sync(false);
}
}
@@ -2368,67 +1531,47 @@ void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenu
EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
"GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if ((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
- || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
+ if (!gl::ValidFramebufferTarget(target) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
{
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (!gl::ValidateFramebufferRenderbufferParameters(context, target, attachment, renderbuffertarget, renderbuffer))
{
- gl::Framebuffer *framebuffer = NULL;
- GLuint framebufferHandle = 0;
- if (target == GL_READ_FRAMEBUFFER_ANGLE)
- {
- framebuffer = context->getReadFramebuffer();
- framebufferHandle = context->getReadFramebufferHandle();
- }
- else
- {
- framebuffer = context->getDrawFramebuffer();
- framebufferHandle = context->getDrawFramebufferHandle();
- }
-
- if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
- {
- const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
+ return;
+ }
- if (colorAttachment >= context->getMaximumRenderTargets())
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
- framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer);
- }
- else
+ if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+ {
+ unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
+ framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer, 0, 0);
+ }
+ else
+ {
+ switch (attachment)
{
- switch (attachment)
- {
- case GL_DEPTH_ATTACHMENT:
- framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
- break;
- case GL_STENCIL_ATTACHMENT:
- framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
+ case GL_DEPTH_ATTACHMENT:
+ framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0);
+ break;
+ case GL_STENCIL_ATTACHMENT:
+ framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0);
+ break;
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ framebuffer->setDepthStencilBuffer(GL_RENDERBUFFER, renderbuffer, 0, 0);
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
@@ -2436,247 +1579,149 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t
EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
"GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
+ if (!ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level))
{
- return gl::error(GL_INVALID_ENUM);
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (texture == 0)
{
- if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
- {
- const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
-
- if (colorAttachment >= context->getMaximumRenderTargets())
- {
- return gl::error(GL_INVALID_VALUE);
- }
- }
- else
- {
- switch (attachment)
- {
- case GL_DEPTH_ATTACHMENT:
- case GL_STENCIL_ATTACHMENT:
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
- }
-
- if (texture == 0)
- {
- textarget = GL_NONE;
- }
- else
- {
- gl::Texture *tex = context->getTexture(texture);
-
- if (tex == NULL)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- switch (textarget)
- {
- case GL_TEXTURE_2D:
- {
- if (tex->getTarget() != GL_TEXTURE_2D)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
- if (tex2d->isCompressed(0))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- 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 (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
- if (texcube->isCompressed(textarget, level))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- break;
- }
-
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- if (level != 0)
- {
- return gl::error(GL_INVALID_VALUE);
- }
- }
-
- gl::Framebuffer *framebuffer = NULL;
- GLuint framebufferHandle = 0;
- if (target == GL_READ_FRAMEBUFFER_ANGLE)
- {
- framebuffer = context->getReadFramebuffer();
- framebufferHandle = context->getReadFramebufferHandle();
- }
- else
- {
- framebuffer = context->getDrawFramebuffer();
- framebufferHandle = context->getDrawFramebufferHandle();
- }
+ textarget = GL_NONE;
+ }
- if (framebufferHandle == 0 || !framebuffer)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
- if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+ if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+ {
+ const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
+ framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, 0);
+ }
+ else
+ {
+ switch (attachment)
{
- const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
-
- if (colorAttachment >= context->getMaximumRenderTargets())
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- framebuffer->setColorbuffer(colorAttachment, textarget, texture);
- }
- else
- {
- switch (attachment)
- {
- case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
- case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
- }
+ case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level, 0); break;
+ case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level, 0); break;
+ case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, 0); break;
}
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glFrontFace(GLenum mode)
{
EVENT("(GLenum mode = 0x%X)", mode);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
switch (mode)
{
case GL_CW:
case GL_CCW:
- {
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setFrontFace(mode);
- }
- }
+ context->getState().setFrontFace(mode);
break;
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGenBuffers(GLsizei n, GLuint* buffers)
{
EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ for (int i = 0; i < n; i++)
{
- for (int i = 0; i < n; i++)
- {
- buffers[i] = context->createBuffer();
- }
+ buffers[i] = context->createBuffer();
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGenerateMipmap(GLenum target)
{
EVENT("(GLenum target = 0x%X)", target);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ if (!ValidTextureTarget(context, target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- if (context)
+ gl::Texture *texture = context->getTargetTexture(target);
+
+ if (texture == NULL)
{
- switch (target)
- {
- case GL_TEXTURE_2D:
- {
- gl::Texture2D *tex2d = context->getTexture2D();
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (tex2d->isCompressed(0))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- if (tex2d->isDepth(0))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ GLenum internalFormat = texture->getBaseLevelInternalFormat();
+ const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
- tex2d->generateMipmaps();
- break;
- }
+ // 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.
+ bool isLUMA = internalFormat == GL_LUMINANCE8_EXT ||
+ internalFormat == GL_LUMINANCE8_ALPHA8_EXT ||
+ internalFormat == GL_ALPHA8_EXT;
- case GL_TEXTURE_CUBE_MAP:
- {
- gl::TextureCubeMap *texcube = context->getTextureCubeMap();
+ if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0 || !formatCaps.filterable ||
+ (!formatCaps.renderable && !isLUMA) || formatInfo.compressed)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (texcube->isCompressed(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ // GL_EXT_sRGB does not support mipmap generation on sRGB textures
+ if (context->getClientVersion() == 2 && formatInfo.colorEncoding == GL_SRGB)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- texcube->generateMipmaps();
- break;
- }
+ // Non-power of 2 ES2 check
+ if (!context->getExtensions().textureNPOT && (!gl::isPow2(texture->getBaseLevelWidth()) || !gl::isPow2(texture->getBaseLevelHeight())))
+ {
+ ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- default:
- return gl::error(GL_INVALID_ENUM);
+ // Cube completeness check
+ if (target == GL_TEXTURE_CUBE_MAP)
+ {
+ gl::TextureCubeMap *textureCube = static_cast<gl::TextureCubeMap *>(texture);
+ if (!textureCube->isCubeComplete())
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ texture->generateMipmaps();
}
}
@@ -2684,135 +1729,100 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences)
{
EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ for (int i = 0; i < n; i++)
{
- for (int i = 0; i < n; i++)
- {
- fences[i] = context->createFence();
- }
+ fences[i] = context->createFenceNV();
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers)
{
EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ for (int i = 0; i < n; i++)
{
- for (int i = 0; i < n; i++)
- {
- framebuffers[i] = context->createFramebuffer();
- }
+ framebuffers[i] = context->createFramebuffer();
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids)
{
EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ for (GLsizei i = 0; i < n; i++)
{
- for (int i = 0; i < n; i++)
- {
- ids[i] = context->createQuery();
- }
+ ids[i] = context->createQuery();
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
{
EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ for (int i = 0; i < n; i++)
{
- for (int i = 0; i < n; i++)
- {
- renderbuffers[i] = context->createRenderbuffer();
- }
+ renderbuffers[i] = context->createRenderbuffer();
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGenTextures(GLsizei n, GLuint* textures)
{
- EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
+ EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ for (int i = 0; i < n; i++)
{
- for (int i = 0; i < n; i++)
- {
- textures[i] = context->createTexture();
- }
+ textures[i] = context->createTexture();
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
@@ -2821,42 +1831,38 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize,
"GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
program, index, bufsize, length, size, type, name);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (bufsize < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context)
+ if (!programObject)
{
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
+ if (context->getShader(program))
{
- if (context->getShader(program))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
-
- if (index >= (GLuint)programObject->getActiveAttributeCount())
+ else
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+ }
- programObject->getActiveAttribute(index, bufsize, length, size, type, name);
+ if (index >= (GLuint)programObject->getActiveAttributeCount())
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ programObject->getActiveAttribute(index, bufsize, length, size, type, name);
}
}
@@ -2866,42 +1872,39 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize,
"GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
program, index, bufsize, length, size, type, name);
- try
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (bufsize < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context)
+ if (!programObject)
{
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
+ if (context->getShader(program))
{
- if (context->getShader(program))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
-
- if (index >= (GLuint)programObject->getActiveUniformCount())
+ else
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+ }
- programObject->getActiveUniform(index, bufsize, length, size, type, name);
+ if (index >= (GLuint)programObject->getActiveUniformCount())
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ programObject->getActiveUniform(index, bufsize, length, size, type, name);
}
}
@@ -2910,77 +1913,66 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c
EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
program, maxcount, count, shaders);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (maxcount < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context)
+ if (!programObject)
{
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
+ if (context->getShader(program))
{
- if (context->getShader(program))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
-
- return programObject->getAttachedShaders(maxcount, count, shaders);
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ return programObject->getAttachedShaders(maxcount, count, shaders);
}
}
-int __stdcall glGetAttribLocation(GLuint program, const GLchar* name)
+GLint __stdcall glGetAttribLocation(GLuint program, const GLchar* name)
{
EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context)
+ if (!programObject)
{
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
+ if (context->getShader(program))
{
- if (context->getShader(program))
- {
- return gl::error(GL_INVALID_OPERATION, -1);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE, -1);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return -1;
}
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programObject->isLinked() || !programBinary)
+ else
{
- return gl::error(GL_INVALID_OPERATION, -1);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return -1;
}
+ }
- return programBinary->getAttributeLocation(name);
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+ if (!programObject->isLinked() || !programBinary)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return -1;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, -1);
+
+ return programBinary->getAttributeLocation(name);
}
return -1;
@@ -2990,62 +1982,24 @@ void __stdcall glGetBooleanv(GLenum pname, GLboolean* params)
{
EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
{
- if (!(context->getBooleanv(pname, params)))
- {
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!context->getQueryParameterInfo(pname, &nativeType, &numParams))
- return gl::error(GL_INVALID_ENUM);
-
- if (numParams == 0)
- return; // it is known that the pname is valid, but there are no parameters to return
-
- if (nativeType == GL_FLOAT)
- {
- GLfloat *floatParams = NULL;
- floatParams = new GLfloat[numParams];
-
- context->getFloatv(pname, floatParams);
-
- for (unsigned int i = 0; i < numParams; ++i)
- {
- if (floatParams[i] == 0.0f)
- params[i] = GL_FALSE;
- else
- params[i] = GL_TRUE;
- }
-
- delete [] floatParams;
- }
- else if (nativeType == GL_INT)
- {
- GLint *intParams = NULL;
- intParams = new GLint[numParams];
-
- context->getIntegerv(pname, intParams);
-
- for (unsigned int i = 0; i < numParams; ++i)
- {
- if (intParams[i] == 0)
- params[i] = GL_FALSE;
- else
- params[i] = GL_TRUE;
- }
+ return;
+ }
- delete [] intParams;
- }
- }
+ if (nativeType == GL_BOOL)
+ {
+ context->getBooleanv(pname, params);
+ }
+ else
+ {
+ CastStateValues(context, nativeType, pname, numParams, params);
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
}
}
@@ -3053,47 +2007,53 @@ void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params
{
EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ if (!gl::ValidBufferTarget(context, target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- if (context)
+ if (!gl::ValidBufferParameter(context, pname))
{
- gl::Buffer *buffer;
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- switch (target)
- {
- case GL_ARRAY_BUFFER:
- buffer = context->getArrayBuffer();
- break;
- case GL_ELEMENT_ARRAY_BUFFER:
- buffer = context->getElementArrayBuffer();
- break;
- default: return gl::error(GL_INVALID_ENUM);
- }
+ gl::Buffer *buffer = context->getState().getTargetBuffer(target);
- if (!buffer)
- {
- // A null buffer means that "0" is bound to the requested buffer target
- return gl::error(GL_INVALID_OPERATION);
- }
+ if (!buffer)
+ {
+ // A null buffer means that "0" is bound to the requested buffer target
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- switch (pname)
- {
- case GL_BUFFER_USAGE:
- *params = buffer->usage();
- break;
- case GL_BUFFER_SIZE:
- *params = buffer->size();
- break;
- default: return gl::error(GL_INVALID_ENUM);
- }
+ switch (pname)
+ {
+ case GL_BUFFER_USAGE:
+ *params = static_cast<GLint>(buffer->getUsage());
+ break;
+ case GL_BUFFER_SIZE:
+ *params = gl::clampCast<GLint>(buffer->getSize());
+ break;
+ case GL_BUFFER_ACCESS_FLAGS:
+ *params = buffer->getAccessFlags();
+ break;
+ case GL_BUFFER_MAPPED:
+ *params = static_cast<GLint>(buffer->isMapped());
+ break;
+ case GL_BUFFER_MAP_OFFSET:
+ *params = gl::clampCast<GLint>(buffer->getMapOffset());
+ break;
+ case GL_BUFFER_MAP_LENGTH:
+ *params = gl::clampCast<GLint>(buffer->getMapLength());
+ break;
+ default: UNREACHABLE(); break;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
GLenum __stdcall glGetError(void)
@@ -3114,26 +2074,35 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
{
EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
-
- gl::Context *context = gl::getNonLostContext();
+ gl::FenceNV *fenceObject = context->getFenceNV(fence);
- if (context)
+ if (fenceObject == NULL)
{
- gl::Fence *fenceObject = context->getFence(fence);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (fenceObject == NULL)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ if (fenceObject->isFence() != GL_TRUE)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_FENCE_STATUS_NV:
+ case GL_FENCE_CONDITION_NV:
+ break;
- fenceObject->getFenceiv(pname, params);
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ params[0] = fenceObject->getFencei(pname);
}
}
@@ -3141,59 +2110,24 @@ void __stdcall glGetFloatv(GLenum pname, GLfloat* params)
{
EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
{
- if (!(context->getFloatv(pname, params)))
- {
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!context->getQueryParameterInfo(pname, &nativeType, &numParams))
- return gl::error(GL_INVALID_ENUM);
-
- if (numParams == 0)
- return; // it is known that the pname is valid, but that there are no parameters to return.
-
- if (nativeType == GL_BOOL)
- {
- GLboolean *boolParams = NULL;
- boolParams = new GLboolean[numParams];
-
- context->getBooleanv(pname, boolParams);
-
- for (unsigned int i = 0; i < numParams; ++i)
- {
- if (boolParams[i] == GL_FALSE)
- params[i] = 0.0f;
- else
- params[i] = 1.0f;
- }
-
- delete [] boolParams;
- }
- else if (nativeType == GL_INT)
- {
- GLint *intParams = NULL;
- intParams = new GLint[numParams];
-
- context->getIntegerv(pname, intParams);
-
- for (unsigned int i = 0; i < numParams; ++i)
- {
- params[i] = (GLfloat)intParams[i];
- }
+ return;
+ }
- delete [] intParams;
- }
- }
+ if (nativeType == GL_FLOAT)
+ {
+ context->getFloatv(pname, params);
+ }
+ else
+ {
+ CastStateValues(context, nativeType, pname, numParams, params);
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
}
}
@@ -3202,219 +2136,335 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac
EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
target, attachment, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ if (!gl::ValidFramebufferTarget(target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- if (context)
+ int clientVersion = context->getClientVersion();
+
+ switch (pname)
{
- if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
- {
- return gl::error(GL_INVALID_ENUM);
- }
+ 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;
- gl::Framebuffer *framebuffer = NULL;
- if (target == GL_READ_FRAMEBUFFER_ANGLE)
+ case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+ if (clientVersion < 3 && !context->getExtensions().sRGB)
{
- if(context->getReadFramebufferHandle() == 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
- framebuffer = context->getReadFramebuffer();
+ 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->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- else
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ // 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)
{
- if (context->getDrawFramebufferHandle() == 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
- framebuffer = context->getDrawFramebuffer();
+ 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->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
+ break;
+ }
- GLenum attachmentType;
- GLuint attachmentHandle;
+ GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id();
+ gl::Framebuffer *framebuffer = context->getFramebuffer(framebufferHandle);
- if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+ if (framebufferHandle == 0)
+ {
+ if (clientVersion < 3)
{
- const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (colorAttachment >= context->getMaximumRenderTargets())
- {
- return gl::error(GL_INVALID_ENUM);
- }
+ switch (attachment)
+ {
+ case GL_BACK:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ break;
- attachmentType = framebuffer->getColorbufferType(colorAttachment);
- attachmentHandle = framebuffer->getColorbufferHandle(colorAttachment);
+ default:
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+ }
+ else
+ {
+ if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+ {
+ // Valid attachment query
}
else
{
switch (attachment)
{
case GL_DEPTH_ATTACHMENT:
- attachmentType = framebuffer->getDepthbufferType();
- attachmentHandle = framebuffer->getDepthbufferHandle();
- break;
case GL_STENCIL_ATTACHMENT:
- attachmentType = framebuffer->getStencilbufferType();
- attachmentHandle = framebuffer->getStencilbufferHandle();
break;
- default: return gl::error(GL_INVALID_ENUM);
+
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (framebuffer->hasValidDepthStencil())
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
}
+ }
- GLenum attachmentObjectType; // Type category
- if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER)
- {
- attachmentObjectType = attachmentType;
- }
- else if (gl::IsInternalTextureTarget(attachmentType))
- {
- attachmentObjectType = GL_TEXTURE;
- }
- else
- {
- UNREACHABLE();
- return;
- }
+ GLenum attachmentType = GL_NONE;
+ GLuint attachmentHandle = 0;
+ GLuint attachmentLevel = 0;
+ GLuint attachmentLayer = 0;
+
+ const gl::FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
+
+ if (attachmentObject)
+ {
+ attachmentType = attachmentObject->type();
+ attachmentHandle = attachmentObject->id();
+ attachmentLevel = attachmentObject->mipLevel();
+ attachmentLayer = attachmentObject->layer();
+ }
+
+ GLenum attachmentObjectType; // Type category
+ if (framebufferHandle == 0)
+ {
+ attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
+ }
+ else if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER)
+ {
+ attachmentObjectType = attachmentType;
+ }
+ else if (gl::ValidTexture2DDestinationTarget(context, attachmentType))
+ {
+ attachmentObjectType = GL_TEXTURE;
+ }
+ else
+ {
+ UNREACHABLE();
+ return;
+ }
+
+ if (attachmentObjectType == GL_NONE)
+ {
+ // 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 = attachmentObjectType;
break;
+
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
- if (attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
+ if (clientVersion < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = 0;
+ break;
+
+ default:
+ if (clientVersion < 3)
{
- *params = attachmentHandle;
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
else
{
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
+ }
+ }
+ else
+ {
+ ASSERT(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE ||
+ attachmentObjectType == GL_FRAMEBUFFER_DEFAULT);
+ ASSERT(attachmentObject != NULL);
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ *params = attachmentObjectType;
break;
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
- if (attachmentObjectType == GL_TEXTURE)
+
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ if (attachmentObjectType != GL_RENDERBUFFER && attachmentObjectType != GL_TEXTURE)
{
- *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- else
+ *params = attachmentHandle;
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ if (attachmentObjectType != GL_TEXTURE)
{
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
+ *params = attachmentLevel;
break;
+
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
- if (attachmentObjectType == GL_TEXTURE)
+ if (attachmentObjectType != GL_TEXTURE)
{
- if (gl::IsCubemapTextureTarget(attachmentType))
- {
- *params = attachmentType;
- }
- else
- {
- *params = 0;
- }
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- else
+ *params = gl::IsCubemapTextureTarget(attachmentType) ? attachmentType : 0;
+ 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:
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
{
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
+ *params = attachmentObject->getComponentType();
break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+ *params = attachmentObject->getColorEncoding();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+ if (attachmentObjectType != GL_TEXTURE)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = attachmentLayer;
+ break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ UNREACHABLE();
+ break;
}
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
GLenum __stdcall glGetGraphicsResetStatusEXT(void)
{
EVENT("()");
- try
- {
- gl::Context *context = gl::getContext();
-
- if (context)
- {
- return context->getResetStatus();
- }
+ gl::Context *context = gl::getContext();
- return GL_NO_ERROR;
- }
- catch(std::bad_alloc&)
+ if (context)
{
- return GL_OUT_OF_MEMORY;
+ return context->getResetStatus();
}
+
+ return GL_NO_ERROR;
}
void __stdcall glGetIntegerv(GLenum pname, GLint* params)
{
EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ GLenum nativeType;
+ unsigned int numParams = 0;
- if (context)
+ if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
{
- if (!(context->getIntegerv(pname, params)))
- {
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!context->getQueryParameterInfo(pname, &nativeType, &numParams))
- return gl::error(GL_INVALID_ENUM);
-
- if (numParams == 0)
- return; // it is known that pname is valid, but there are no parameters to return
-
- if (nativeType == GL_BOOL)
- {
- GLboolean *boolParams = NULL;
- boolParams = new GLboolean[numParams];
-
- context->getBooleanv(pname, boolParams);
-
- for (unsigned int i = 0; i < numParams; ++i)
- {
- if (boolParams[i] == GL_FALSE)
- params[i] = 0;
- else
- params[i] = 1;
- }
-
- delete [] boolParams;
- }
- else if (nativeType == GL_FLOAT)
- {
- GLfloat *floatParams = NULL;
- floatParams = new GLfloat[numParams];
-
- context->getFloatv(pname, floatParams);
-
- for (unsigned int i = 0; i < numParams; ++i)
- {
- if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
- {
- params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) / 2.0f);
- }
- else
- params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
- }
+ return;
+ }
- delete [] floatParams;
- }
- }
+ if (nativeType == GL_INT)
+ {
+ context->getIntegerv(pname, params);
+ }
+ else
+ {
+ CastStateValues(context, nativeType, pname, numParams, params);
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
}
}
@@ -3422,59 +2472,83 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params)
{
EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context)
+ if (!programObject)
{
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ if (context->getClientVersion() < 3)
+ {
switch (pname)
{
- case GL_DELETE_STATUS:
- *params = programObject->isFlaggedForDeletion();
- return;
- case GL_LINK_STATUS:
- *params = programObject->isLinked();
- return;
- case GL_VALIDATE_STATUS:
- *params = programObject->isValidated();
- return;
- case GL_INFO_LOG_LENGTH:
- *params = programObject->getInfoLogLength();
- return;
- case GL_ATTACHED_SHADERS:
- *params = programObject->getAttachedShadersCount();
- return;
- case GL_ACTIVE_ATTRIBUTES:
- *params = programObject->getActiveAttributeCount();
- return;
- case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
- *params = programObject->getActiveAttributeMaxLength();
- return;
- case GL_ACTIVE_UNIFORMS:
- *params = programObject->getActiveUniformCount();
- return;
- case GL_ACTIVE_UNIFORM_MAX_LENGTH:
- *params = programObject->getActiveUniformMaxLength();
+ 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:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
return;
- case GL_PROGRAM_BINARY_LENGTH_OES:
- *params = programObject->getProgramBinaryLength();
- return;
- default:
- return gl::error(GL_INVALID_ENUM);
}
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ switch (pname)
+ {
+ case GL_DELETE_STATUS:
+ *params = programObject->isFlaggedForDeletion();
+ return;
+ case GL_LINK_STATUS:
+ *params = programObject->isLinked();
+ return;
+ case GL_VALIDATE_STATUS:
+ *params = programObject->isValidated();
+ return;
+ case GL_INFO_LOG_LENGTH:
+ *params = programObject->getInfoLogLength();
+ return;
+ case GL_ATTACHED_SHADERS:
+ *params = programObject->getAttachedShadersCount();
+ return;
+ case GL_ACTIVE_ATTRIBUTES:
+ *params = programObject->getActiveAttributeCount();
+ return;
+ case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+ *params = programObject->getActiveAttributeMaxLength();
+ return;
+ case GL_ACTIVE_UNIFORMS:
+ *params = programObject->getActiveUniformCount();
+ return;
+ case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+ *params = programObject->getActiveUniformMaxLength();
+ return;
+ case GL_PROGRAM_BINARY_LENGTH_OES:
+ *params = programObject->getProgramBinaryLength();
+ return;
+ case GL_ACTIVE_UNIFORM_BLOCKS:
+ *params = programObject->getActiveUniformBlockCount();
+ return;
+ case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+ *params = programObject->getActiveUniformBlockMaxLength();
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
+ *params = programObject->getTransformFeedbackBufferMode();
+ break;
+ case GL_TRANSFORM_FEEDBACK_VARYINGS:
+ *params = programObject->getTransformFeedbackVaryingCount();
+ break;
+ case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+ *params = programObject->getTransformFeedbackVaryingMaxLength();
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
}
}
@@ -3483,30 +2557,24 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len
EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
program, bufsize, length, infolog);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (bufsize < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context)
+ if (!programObject)
{
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- programObject->getInfoLog(bufsize, length, infolog);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ programObject->getInfoLog(bufsize, length, infolog);
}
}
@@ -3514,178 +2582,170 @@ void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
{
EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
+ if (!ValidQueryType(context, target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
switch (pname)
{
case GL_CURRENT_QUERY_EXT:
+ params[0] = context->getState().getActiveQueryId(target);
break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- params[0] = context->getActiveQuery(target);
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
{
EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- switch (pname)
+ gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
+
+ if (!queryObject)
{
- case GL_QUERY_RESULT_EXT:
- case GL_QUERY_RESULT_AVAILABLE_EXT:
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
- if (context)
+ if (context->getState().getActiveQueryId(queryObject->getType()) == id)
{
- gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (!queryObject)
+ switch(pname)
+ {
+ case GL_QUERY_RESULT_EXT:
{
- return gl::error(GL_INVALID_OPERATION);
+ gl::Error error = queryObject->getResult(params);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
}
+ break;
- if (context->getActiveQuery(queryObject->getType()) == id)
+ case GL_QUERY_RESULT_AVAILABLE_EXT:
{
- return gl::error(GL_INVALID_OPERATION);
+ gl::Error error = queryObject->isResultAvailable(params);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
}
+ break;
- switch(pname)
- {
- case GL_QUERY_RESULT_EXT:
- params[0] = queryObject->getResult();
- break;
- case GL_QUERY_RESULT_AVAILABLE_EXT:
- params[0] = queryObject->isResultAvailable();
- break;
- default:
- ASSERT(false);
- }
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
{
EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ if (target != GL_RENDERBUFFER)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- if (context)
+ if (context->getState().getRenderbufferId() == 0)
{
- if (target != GL_RENDERBUFFER)
- {
- return gl::error(GL_INVALID_ENUM);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (context->getRenderbufferHandle() == 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getState().getRenderbufferId());
- gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle());
+ 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->getInternalFormat(); 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;
- switch (pname)
+ case GL_RENDERBUFFER_SAMPLES_ANGLE:
+ if (!context->getExtensions().framebufferMultisample)
{
- case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
- case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
- case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); 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:
- if (context->getMaxSupportedSamples() != 0)
- {
- *params = renderbuffer->getSamples();
- }
- else
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
+ *params = renderbuffer->getSamples();
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
{
EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Shader *shaderObject = context->getShader(shader);
- if (context)
+ if (!shaderObject)
{
- gl::Shader *shaderObject = context->getShader(shader);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- if (!shaderObject)
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ switch (pname)
+ {
+ case GL_SHADER_TYPE:
+ *params = shaderObject->getType();
+ return;
+ case GL_DELETE_STATUS:
+ *params = shaderObject->isFlaggedForDeletion();
+ return;
+ case GL_COMPILE_STATUS:
+ *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
+ return;
+ case GL_INFO_LOG_LENGTH:
+ *params = shaderObject->getInfoLogLength();
+ return;
+ case GL_SHADER_SOURCE_LENGTH:
+ *params = shaderObject->getSourceLength();
+ return;
+ case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+ *params = shaderObject->getTranslatedSourceLength();
+ return;
- switch (pname)
- {
- case GL_SHADER_TYPE:
- *params = shaderObject->getType();
- return;
- case GL_DELETE_STATUS:
- *params = shaderObject->isFlaggedForDeletion();
- return;
- case GL_COMPILE_STATUS:
- *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
- return;
- case GL_INFO_LOG_LENGTH:
- *params = shaderObject->getInfoLogLength();
- return;
- case GL_SHADER_SOURCE_LENGTH:
- *params = shaderObject->getSourceLength();
- return;
- case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
- *params = shaderObject->getTranslatedSourceLength();
- return;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
@@ -3693,30 +2753,24 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt
EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
shader, bufsize, length, infolog);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (bufsize < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Shader *shaderObject = context->getShader(shader);
- if (context)
+ if (!shaderObject)
{
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!shaderObject)
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- shaderObject->getInfoLog(bufsize, length, infolog);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ shaderObject->getInfoLog(bufsize, length, infolog);
}
}
@@ -3725,15 +2779,18 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp
EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
shadertype, precisiontype, range, precision);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
switch (shadertype)
{
case GL_VERTEX_SHADER:
case GL_FRAGMENT_SHADER:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
switch (precisiontype)
@@ -3746,6 +2803,7 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp
range[1] = 127;
*precision = 23;
break;
+
case GL_LOW_INT:
case GL_MEDIUM_INT:
case GL_HIGH_INT:
@@ -3755,14 +2813,12 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp
range[1] = 24;
*precision = 0;
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
@@ -3770,30 +2826,24 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length
EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
shader, bufsize, length, source);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (bufsize < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Shader *shaderObject = context->getShader(shader);
- if (context)
+ if (!shaderObject)
{
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!shaderObject)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- shaderObject->getSource(bufsize, length, source);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ shaderObject->getSource(bufsize, length, source);
}
}
@@ -3802,30 +2852,24 @@ void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize,
EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
shader, bufsize, length, source);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (bufsize < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Shader *shaderObject = context->getShader(shader);
- if (context)
+ if (!shaderObject)
{
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!shaderObject)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- shaderObject->getTranslatedSource(bufsize, length, source);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ shaderObject->getTranslatedSource(bufsize, length, source);
}
}
@@ -3833,29 +2877,45 @@ const GLubyte* __stdcall glGetString(GLenum name)
{
EVENT("(GLenum name = 0x%X)", name);
- try
+ gl::Context *context = gl::getNonLostContext();
+
+ switch (name)
{
- gl::Context *context = gl::getNonLostContext();
+ case GL_VENDOR:
+ return (GLubyte*)"Google Inc.";
- switch (name)
+ case GL_RENDERER:
+ return (GLubyte*)((context != NULL) ? context->getRendererString().c_str() : "ANGLE");
+
+ case GL_VERSION:
+ if (context->getClientVersion() == 2)
{
- case GL_VENDOR:
- return (GLubyte*)"Google Inc.";
- case GL_RENDERER:
- return (GLubyte*)((context != NULL) ? context->getRendererString() : "ANGLE");
- case GL_VERSION:
return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")";
- case GL_SHADING_LANGUAGE_VERSION:
+ }
+ else
+ {
+ return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")";
+ }
+
+ case GL_SHADING_LANGUAGE_VERSION:
+ if (context->getClientVersion() == 2)
+ {
return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")";
- case GL_EXTENSIONS:
- return (GLubyte*)((context != NULL) ? context->getExtensionString() : "");
- default:
- return gl::error(GL_INVALID_ENUM, (GLubyte*)NULL);
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, (GLubyte*)NULL);
+ else
+ {
+ return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")";
+ }
+
+ case GL_EXTENSIONS:
+ return (GLubyte*)((context != NULL) ? context->getExtensionString().c_str() : "");
+
+ default:
+ if (context)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ }
+ return NULL;
}
}
@@ -3863,124 +2923,264 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
{
EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Texture *texture = context->getTargetTexture(target);
- if (context)
+ if (!texture)
{
- gl::Texture *texture;
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- switch (target)
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = (GLfloat)texture->getSamplerState().magFilter;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = (GLfloat)texture->getSamplerState().minFilter;
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = (GLfloat)texture->getSamplerState().wrapS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = (GLfloat)texture->getSamplerState().wrapT;
+ break;
+ case GL_TEXTURE_WRAP_R:
+ if (context->getClientVersion() < 3)
{
- case GL_TEXTURE_2D:
- texture = context->getTexture2D();
- break;
- case GL_TEXTURE_CUBE_MAP:
- texture = context->getTextureCubeMap();
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
-
- switch (pname)
+ *params = (GLfloat)texture->getSamplerState().wrapR;
+ break;
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ // Exposed to ES2.0 through EXT_texture_storage, no client version validation.
+ *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE);
+ break;
+ case GL_TEXTURE_IMMUTABLE_LEVELS:
+ if (context->getClientVersion() < 3)
{
- case GL_TEXTURE_MAG_FILTER:
- *params = (GLfloat)texture->getMagFilter();
- break;
- case GL_TEXTURE_MIN_FILTER:
- *params = (GLfloat)texture->getMinFilter();
- break;
- case GL_TEXTURE_WRAP_S:
- *params = (GLfloat)texture->getWrapS();
- break;
- case GL_TEXTURE_WRAP_T:
- *params = (GLfloat)texture->getWrapT();
- break;
- case GL_TEXTURE_IMMUTABLE_FORMAT_EXT:
- *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE);
- break;
- case GL_TEXTURE_USAGE_ANGLE:
- *params = (GLfloat)texture->getUsage();
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- if (!context->supportsTextureFilterAnisotropy())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- *params = (GLfloat)texture->getMaxAnisotropy();
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->immutableLevelCount();
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ *params = (GLfloat)texture->getUsage();
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->getExtensions().textureFilterAnisotropic)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().maxAnisotropy;
+ break;
+ case GL_TEXTURE_SWIZZLE_R:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().swizzleRed;
+ break;
+ case GL_TEXTURE_SWIZZLE_G:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().swizzleGreen;
+ break;
+ case GL_TEXTURE_SWIZZLE_B:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
+ *params = (GLfloat)texture->getSamplerState().swizzleBlue;
+ break;
+ case GL_TEXTURE_SWIZZLE_A:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().swizzleAlpha;
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().baseLevel;
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().maxLevel;
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().minLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().maxLod;
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
{
EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Texture *texture = context->getTargetTexture(target);
- if (context)
+ if (!texture)
{
- gl::Texture *texture;
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- switch (target)
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = texture->getSamplerState().magFilter;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = texture->getSamplerState().minFilter;
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = texture->getSamplerState().wrapS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = texture->getSamplerState().wrapT;
+ break;
+ case GL_TEXTURE_WRAP_R:
+ if (context->getClientVersion() < 3)
{
- case GL_TEXTURE_2D:
- texture = context->getTexture2D();
- break;
- case GL_TEXTURE_CUBE_MAP:
- texture = context->getTextureCubeMap();
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
-
- switch (pname)
+ *params = texture->getSamplerState().wrapR;
+ break;
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ // Exposed to ES2.0 through EXT_texture_storage, no client version validation.
+ *params = texture->isImmutable() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_TEXTURE_IMMUTABLE_LEVELS:
+ if (context->getClientVersion() < 3)
{
- case GL_TEXTURE_MAG_FILTER:
- *params = texture->getMagFilter();
- break;
- case GL_TEXTURE_MIN_FILTER:
- *params = texture->getMinFilter();
- break;
- case GL_TEXTURE_WRAP_S:
- *params = texture->getWrapS();
- break;
- case GL_TEXTURE_WRAP_T:
- *params = texture->getWrapT();
- break;
- case GL_TEXTURE_IMMUTABLE_FORMAT_EXT:
- *params = texture->isImmutable() ? GL_TRUE : GL_FALSE;
- break;
- case GL_TEXTURE_USAGE_ANGLE:
- *params = texture->getUsage();
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- if (!context->supportsTextureFilterAnisotropy())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- *params = (GLint)texture->getMaxAnisotropy();
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->immutableLevelCount();
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ *params = texture->getUsage();
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->getExtensions().textureFilterAnisotropic)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLint)texture->getSamplerState().maxAnisotropy;
+ break;
+ case GL_TEXTURE_SWIZZLE_R:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().swizzleRed;
+ break;
+ case GL_TEXTURE_SWIZZLE_G:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
+ *params = texture->getSamplerState().swizzleGreen;
+ break;
+ case GL_TEXTURE_SWIZZLE_B:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().swizzleBlue;
+ break;
+ case GL_TEXTURE_SWIZZLE_A:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().swizzleAlpha;
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().baseLevel;
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().maxLevel;
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLint)texture->getSamplerState().minLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLint)texture->getSamplerState().maxLod;
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
@@ -3988,44 +3188,20 @@ void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSiz
EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",
program, location, bufSize, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (bufSize < 0)
+ if (!ValidateGetnUniformfvEXT(context, program, location, bufSize, params))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- if (program == 0)
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ gl::Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+ ASSERT(programBinary);
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject || !programObject->isLinked())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programBinary)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- if (!programBinary->getUniformfv(location, &bufSize, params))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ programBinary->getUniformfv(location, params);
}
}
@@ -4033,85 +3209,42 @@ void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params)
{
EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (!ValidateGetUniformfv(context, program, location, params))
{
- if (program == 0)
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject || !programObject->isLinked())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ return;
+ }
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programBinary)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ gl::Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+ ASSERT(programBinary);
- if (!programBinary->getUniformfv(location, NULL, params))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ programBinary->getUniformfv(location, params);
}
}
void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
{
- EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
+ EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
program, location, bufSize, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (bufSize < 0)
+ if (!ValidateGetnUniformivEXT(context, program, location, bufSize, params))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- if (program == 0)
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- gl::Program *programObject = context->getProgram(program);
+ gl::Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+ ASSERT(programBinary);
- if (!programObject || !programObject->isLinked())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programBinary)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- if (!programBinary->getUniformiv(location, &bufSize, params))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ programBinary->getUniformiv(location, params);
}
}
@@ -4119,83 +3252,59 @@ void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params)
{
EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (!ValidateGetUniformiv(context, program, location, params))
{
- if (program == 0)
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject || !programObject->isLinked())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ return;
+ }
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programBinary)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ gl::Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+ ASSERT(programBinary);
- if (!programBinary->getUniformiv(location, NULL, params))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ programBinary->getUniformiv(location, params);
}
}
-int __stdcall glGetUniformLocation(GLuint program, const GLchar* name)
+GLint __stdcall glGetUniformLocation(GLuint program, const GLchar* name)
{
EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
if (strstr(name, "gl_") == name)
{
return -1;
}
- if (context)
- {
- gl::Program *programObject = context->getProgram(program);
+ gl::Program *programObject = context->getProgram(program);
- if (!programObject)
+ if (!programObject)
+ {
+ if (context->getShader(program))
{
- if (context->getShader(program))
- {
- return gl::error(GL_INVALID_OPERATION, -1);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE, -1);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return -1;
}
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programObject->isLinked() || !programBinary)
+ else
{
- return gl::error(GL_INVALID_OPERATION, -1);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return -1;
}
+ }
- return programBinary->getUniformLocation(name);
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+ if (!programObject->isLinked() || !programBinary)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return -1;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, -1);
+
+ return programBinary->getUniformLocation(name);
}
return -1;
@@ -4205,55 +3314,33 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
{
EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
{
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- const gl::VertexAttribute &attribState = context->getVertexAttribState(index);
+ const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index);
+ if (!gl::ValidateGetVertexAttribParameters(context, pname))
+ {
+ return;
+ }
- switch (pname)
+ if (pname == GL_CURRENT_VERTEX_ATTRIB)
+ {
+ const gl::VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
+ for (int i = 0; i < 4; ++i)
{
- case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
- *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
- break;
- case GL_VERTEX_ATTRIB_ARRAY_SIZE:
- *params = (GLfloat)attribState.mSize;
- break;
- case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
- *params = (GLfloat)attribState.mStride;
- break;
- case GL_VERTEX_ATTRIB_ARRAY_TYPE:
- *params = (GLfloat)attribState.mType;
- break;
- case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
- *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
- break;
- case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
- *params = (GLfloat)attribState.mBoundBuffer.id();
- break;
- case GL_CURRENT_VERTEX_ATTRIB:
- for (int i = 0; i < 4; ++i)
- {
- params[i] = attribState.mCurrentValue[i];
- }
- break;
- case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
- *params = (GLfloat)attribState.mDivisor;
- break;
- default: return gl::error(GL_INVALID_ENUM);
+ params[i] = currentValueData.FloatValues[i];
}
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ else
+ {
+ *params = gl::QuerySingleVertexAttributeParameter<GLfloat>(attribState, pname);
+ }
}
}
@@ -4261,56 +3348,35 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
{
EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
{
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- const gl::VertexAttribute &attribState = context->getVertexAttribState(index);
+ const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index);
- switch (pname)
+ if (!gl::ValidateGetVertexAttribParameters(context, pname))
+ {
+ return;
+ }
+
+ if (pname == GL_CURRENT_VERTEX_ATTRIB)
+ {
+ const gl::VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
+ for (int i = 0; i < 4; ++i)
{
- case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
- *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
- break;
- case GL_VERTEX_ATTRIB_ARRAY_SIZE:
- *params = attribState.mSize;
- break;
- case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
- *params = attribState.mStride;
- break;
- case GL_VERTEX_ATTRIB_ARRAY_TYPE:
- *params = attribState.mType;
- break;
- case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
- *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
- break;
- case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
- *params = attribState.mBoundBuffer.id();
- break;
- case GL_CURRENT_VERTEX_ATTRIB:
- for (int i = 0; i < 4; ++i)
- {
- float currentValue = attribState.mCurrentValue[i];
- params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
- }
- break;
- case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
- *params = (GLint)attribState.mDivisor;
- break;
- default: return gl::error(GL_INVALID_ENUM);
+ float currentValue = currentValueData.FloatValues[i];
+ params[i] = gl::iround<GLint>(currentValue);
}
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ else
+ {
+ *params = gl::QuerySingleVertexAttributeParameter<GLint>(attribState, pname);
+ }
}
}
@@ -4318,28 +3384,22 @@ void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** po
{
EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
{
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
- {
- return gl::error(GL_INVALID_ENUM);
- }
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
+ if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ *pointer = const_cast<GLvoid*>(context->getState().getVertexAttribPointer(index));
}
}
@@ -4347,7 +3407,8 @@ void __stdcall glHint(GLenum target, GLenum mode)
{
EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
switch (mode)
{
@@ -4355,51 +3416,43 @@ void __stdcall glHint(GLenum target, GLenum mode)
case GL_NICEST:
case GL_DONT_CARE:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
switch (target)
{
case GL_GENERATE_MIPMAP_HINT:
- if (context) context->setGenerateMipmapHint(mode);
+ context->getState().setGenerateMipmapHint(mode);
break;
+
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
- if (context) context->setFragmentShaderDerivativeHint(mode);
+ context->getState().setFragmentShaderDerivativeHint(mode);
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
GLboolean __stdcall glIsBuffer(GLuint buffer)
{
EVENT("(GLuint buffer = %d)", buffer);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context && buffer)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Buffer *bufferObject = context->getBuffer(buffer);
- if (context && buffer)
+ if (bufferObject)
{
- gl::Buffer *bufferObject = context->getBuffer(buffer);
-
- if (bufferObject)
- {
- return GL_TRUE;
- }
+ return GL_TRUE;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
- }
return GL_FALSE;
}
@@ -4408,31 +3461,16 @@ GLboolean __stdcall glIsEnabled(GLenum cap)
{
EVENT("(GLenum cap = 0x%X)", cap);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (!ValidCap(context, cap))
{
- switch (cap)
- {
- case GL_CULL_FACE: return context->isCullFaceEnabled();
- case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
- case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
- case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
- case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
- case GL_STENCIL_TEST: return context->isStencilTestEnabled();
- case GL_DEPTH_TEST: return context->isDepthTestEnabled();
- case GL_BLEND: return context->isBlendEnabled();
- case GL_DITHER: return context->isDitherEnabled();
- default:
- return gl::error(GL_INVALID_ENUM, false);
- }
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return GL_FALSE;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, false);
+
+ return context->getState().getEnableFeature(cap);
}
return false;
@@ -4442,25 +3480,17 @@ GLboolean __stdcall glIsFenceNV(GLuint fence)
{
EVENT("(GLuint fence = %d)", fence);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::FenceNV *fenceObject = context->getFenceNV(fence);
- if (context)
+ if (fenceObject == NULL)
{
- gl::Fence *fenceObject = context->getFence(fence);
-
- if (fenceObject == NULL)
- {
- return GL_FALSE;
- }
-
- return fenceObject->isFence();
+ return GL_FALSE;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
+
+ return fenceObject->isFence();
}
return GL_FALSE;
@@ -4470,24 +3500,16 @@ GLboolean __stdcall glIsFramebuffer(GLuint framebuffer)
{
EVENT("(GLuint framebuffer = %d)", framebuffer);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context && framebuffer)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
- if (context && framebuffer)
+ if (framebufferObject)
{
- gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
-
- if (framebufferObject)
- {
- return GL_TRUE;
- }
+ return GL_TRUE;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
- }
return GL_FALSE;
}
@@ -4496,24 +3518,16 @@ GLboolean __stdcall glIsProgram(GLuint program)
{
EVENT("(GLuint program = %d)", program);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context && program)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context && program)
+ if (programObject)
{
- gl::Program *programObject = context->getProgram(program);
-
- if (programObject)
- {
- return GL_TRUE;
- }
+ return GL_TRUE;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
- }
return GL_FALSE;
}
@@ -4522,28 +3536,10 @@ GLboolean __stdcall glIsQueryEXT(GLuint id)
{
EVENT("(GLuint id = %d)", id);
- try
- {
- if (id == 0)
- {
- return GL_FALSE;
- }
-
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
-
- if (queryObject)
- {
- return GL_TRUE;
- }
- }
- }
- catch(std::bad_alloc&)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
+ return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
}
return GL_FALSE;
@@ -4553,24 +3549,16 @@ GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer)
{
EVENT("(GLuint renderbuffer = %d)", renderbuffer);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context && renderbuffer)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
- if (context && renderbuffer)
+ if (renderbufferObject)
{
- gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
-
- if (renderbufferObject)
- {
- return GL_TRUE;
- }
+ return GL_TRUE;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
- }
return GL_FALSE;
}
@@ -4579,24 +3567,16 @@ GLboolean __stdcall glIsShader(GLuint shader)
{
EVENT("(GLuint shader = %d)", shader);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context && shader)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Shader *shaderObject = context->getShader(shader);
- if (context && shader)
+ if (shaderObject)
{
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (shaderObject)
- {
- return GL_TRUE;
- }
+ return GL_TRUE;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
- }
return GL_FALSE;
}
@@ -4605,24 +3585,16 @@ GLboolean __stdcall glIsTexture(GLuint texture)
{
EVENT("(GLuint texture = %d)", texture);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context && texture)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Texture *textureObject = context->getTexture(texture);
- if (context && texture)
+ if (textureObject)
{
- gl::Texture *textureObject = context->getTexture(texture);
-
- if (textureObject)
- {
- return GL_TRUE;
- }
+ return GL_TRUE;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
- }
return GL_FALSE;
}
@@ -4631,23 +3603,16 @@ void __stdcall glLineWidth(GLfloat width)
{
EVENT("(GLfloat width = %f)", width);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (width <= 0.0f)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setLineWidth(width);
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setLineWidth(width);
}
}
@@ -4655,32 +3620,26 @@ void __stdcall glLinkProgram(GLuint program)
{
EVENT("(GLuint program = %d)", program);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context)
+ if (!programObject)
{
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
+ if (context->getShader(program))
{
- if (context->getShader(program))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
-
- context->linkProgram(program);
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ context->linkProgram(program);
}
}
@@ -4688,63 +3647,66 @@ void __stdcall glPixelStorei(GLenum pname, GLint param)
{
EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ switch (pname)
{
- switch (pname)
+ case GL_UNPACK_ALIGNMENT:
+ if (param != 1 && param != 2 && param != 4 && param != 8)
{
- case GL_UNPACK_ALIGNMENT:
- if (param != 1 && param != 2 && param != 4 && param != 8)
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- context->setUnpackAlignment(param);
- break;
+ context->getState().setUnpackAlignment(param);
+ break;
- case GL_PACK_ALIGNMENT:
- if (param != 1 && param != 2 && param != 4 && param != 8)
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ case GL_PACK_ALIGNMENT:
+ if (param != 1 && param != 2 && param != 4 && param != 8)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- context->setPackAlignment(param);
- break;
+ context->getState().setPackAlignment(param);
+ break;
- case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
- context->setPackReverseRowOrder(param != 0);
- break;
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ context->getState().setPackReverseRowOrder(param != 0);
+ break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ case GL_UNPACK_IMAGE_HEIGHT:
+ case GL_UNPACK_SKIP_IMAGES:
+ case GL_UNPACK_ROW_LENGTH:
+ case GL_UNPACK_SKIP_ROWS:
+ case GL_UNPACK_SKIP_PIXELS:
+ case GL_PACK_ROW_LENGTH:
+ case GL_PACK_SKIP_ROWS:
+ case GL_PACK_SKIP_PIXELS:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
+ UNIMPLEMENTED();
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glPolygonOffset(GLfloat factor, GLfloat units)
{
EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
- try
- {
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->setPolygonOffsetParams(factor, units);
- }
- }
- catch(std::bad_alloc&)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setPolygonOffsetParams(factor, units);
}
}
@@ -4756,37 +3718,28 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
"GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)",
x, y, width, height, format, type, bufSize, data);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (width < 0 || height < 0 || bufSize < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (!gl::ValidateReadPixelsParameters(context, x, y, width, height,
+ format, type, &bufSize, data))
{
- GLenum currentFormat, currentType;
-
- // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound,
- // and attempting to read back if that's the case is an error. The error will be registered
- // by getCurrentReadFormat.
- if (!context->getCurrentReadFormatType(&currentFormat, &currentType))
- return;
-
- if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ return;
+ }
- context->readPixels(x, y, width, height, format, type, &bufSize, data);
+ gl::Error error = context->readPixels(x, y, width, height, format, type, &bufSize, data);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
@@ -4796,50 +3749,39 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
"GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
x, y, width, height, format, type, pixels);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (width < 0 || height < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (!gl::ValidateReadPixelsParameters(context, x, y, width, height,
+ format, type, NULL, pixels))
{
- GLenum currentFormat, currentType;
-
- // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound,
- // and attempting to read back if that's the case is an error. The error will be registered
- // by getCurrentReadFormat.
- if (!context->getCurrentReadFormatType(&currentFormat, &currentType))
- return;
-
- if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ return;
+ }
- context->readPixels(x, y, width, height, format, type, NULL, pixels);
+ gl::Error error = context->readPixels(x, y, width, height, format, type, NULL, pixels);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glReleaseShaderCompiler(void)
{
EVENT("()");
- try
- {
- gl::Shader::releaseCompiler();
- }
- catch(std::bad_alloc&)
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ context->releaseShaderCompiler();
}
}
@@ -4848,64 +3790,16 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp
EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
target, samples, internalformat, width, height);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- switch (target)
- {
- case GL_RENDERBUFFER:
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- if (!gl::IsColorRenderable(internalformat) && !gl::IsDepthRenderable(internalformat) && !gl::IsStencilRenderable(internalformat))
- {
- return gl::error(GL_INVALID_ENUM);
- }
-
- if (width < 0 || height < 0 || samples < 0)
+ if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat,
+ width, height, true))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- if (width > context->getMaximumRenderbufferDimension() ||
- height > context->getMaximumRenderbufferDimension() ||
- samples > context->getMaxSupportedSamples())
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- GLuint handle = context->getRenderbufferHandle();
- if (handle == 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- switch (internalformat)
- {
- case GL_DEPTH_COMPONENT16:
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGB565:
- case GL_RGB8_OES:
- case GL_RGBA8_OES:
- case GL_STENCIL_INDEX8:
- case GL_DEPTH24_STENCIL8_OES:
- case GL_BGRA8_EXT:
- context->setRenderbufferStorage(width, height, internalformat, samples);
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ context->setRenderbufferStorage(width, height, internalformat, samples);
}
}
@@ -4916,20 +3810,13 @@ void __stdcall glRenderbufferStorage(GLenum target, GLenum internalformat, GLsiz
void __stdcall glSampleCoverage(GLclampf value, GLboolean invert)
{
- EVENT("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
+ EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert);
- try
- {
- gl::Context* context = gl::getNonLostContext();
+ gl::Context* context = gl::getNonLostContext();
- if (context)
- {
- context->setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE);
- }
- }
- catch(std::bad_alloc&)
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE);
}
}
@@ -4937,30 +3824,24 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition)
{
EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (condition != GL_ALL_COMPLETED_NV)
{
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::FenceNV *fenceObject = context->getFenceNV(fence);
- if (context)
+ if (fenceObject == NULL)
{
- gl::Fence *fenceObject = context->getFence(fence);
-
- if (fenceObject == NULL)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- fenceObject->setFence(condition);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ fenceObject->setFence(condition);
}
}
@@ -4968,23 +3849,16 @@ void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
{
EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
- try
+ gl::Context* context = gl::getNonLostContext();
+ if (context)
{
if (width < 0 || height < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context* context = gl::getNonLostContext();
-
- if (context)
- {
- context->setScissorParams(x, y, width, height);
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ context->getState().setScissorParams(x, y, width, height);
}
}
@@ -4994,53 +3868,52 @@ void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryfor
"const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
n, shaders, binaryformat, binary, length);
- try
+ gl::Context* context = gl::getNonLostContext();
+ if (context)
{
+ const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
+ if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) == shaderBinaryFormats.end())
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
// No binary shader formats are supported.
- return gl::error(GL_INVALID_ENUM);
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+ UNIMPLEMENTED();
}
}
-void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
+void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length)
{
EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
shader, count, string, length);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
if (count < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Shader *shaderObject = context->getShader(shader);
- if (context)
+ if (!shaderObject)
{
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!shaderObject)
+ if (context->getProgram(shader))
{
- if (context->getProgram(shader))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
-
- shaderObject->setSource(count, string, length);
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ shaderObject->setSource(count, string, length);
}
}
@@ -5053,7 +3926,8 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint
{
EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
switch (face)
{
@@ -5061,8 +3935,10 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint
case GL_BACK:
case GL_FRONT_AND_BACK:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
switch (func)
@@ -5076,29 +3952,22 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint
case GL_GREATER:
case GL_NOTEQUAL:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
{
- if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
- {
- context->setStencilParams(func, ref, mask);
- }
+ context->getState().setStencilParams(func, ref, mask);
+ }
- if (face == GL_BACK || face == GL_FRONT_AND_BACK)
- {
- context->setStencilBackParams(func, ref, mask);
- }
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ context->getState().setStencilBackParams(func, ref, mask);
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glStencilMask(GLuint mask)
@@ -5110,7 +3979,8 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask)
{
EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
switch (face)
{
@@ -5118,29 +3988,22 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask)
case GL_BACK:
case GL_FRONT_AND_BACK:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
{
- if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
- {
- context->setStencilWritemask(mask);
- }
+ context->getState().setStencilWritemask(mask);
+ }
- if (face == GL_BACK || face == GL_FRONT_AND_BACK)
- {
- context->setStencilBackWritemask(mask);
- }
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ context->getState().setStencilBackWritemask(mask);
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
@@ -5153,7 +4016,8 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu
EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
face, fail, zfail, zpass);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
switch (face)
{
@@ -5161,8 +4025,10 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu
case GL_BACK:
case GL_FRONT_AND_BACK:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
switch (fail)
@@ -5176,8 +4042,10 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu
case GL_INCR_WRAP:
case GL_DECR_WRAP:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
switch (zfail)
@@ -5191,8 +4059,10 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu
case GL_INCR_WRAP:
case GL_DECR_WRAP:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
switch (zpass)
@@ -5206,56 +4076,48 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu
case GL_INCR_WRAP:
case GL_DECR_WRAP:
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
{
- if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
- {
- context->setStencilOperations(fail, zfail, zpass);
- }
+ context->getState().setStencilOperations(fail, zfail, zpass);
+ }
- if (face == GL_BACK || face == GL_FRONT_AND_BACK)
- {
- context->setStencilBackOperations(fail, zfail, zpass);
- }
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ context->getState().setStencilBackOperations(fail, zfail, zpass);
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
GLboolean __stdcall glTestFenceNV(GLuint fence)
{
EVENT("(GLuint fence = %d)", fence);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::FenceNV *fenceObject = context->getFenceNV(fence);
- if (context)
+ if (fenceObject == NULL)
{
- gl::Fence *fenceObject = context->getFence(fence);
-
- if (fenceObject == NULL)
- {
- return gl::error(GL_INVALID_OPERATION, GL_TRUE);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return GL_TRUE;
+ }
- return fenceObject->testFence();
+ if (fenceObject->isFence() != GL_TRUE)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return GL_TRUE;
}
+
+ return fenceObject->testFence();
}
- catch(std::bad_alloc&)
- {
- gl::error(GL_OUT_OF_MEMORY);
- }
-
+
return GL_TRUE;
}
@@ -5263,712 +4125,1813 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
GLint border, GLenum format, GLenum type, const GLvoid* pixels)
{
EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
- "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
+ "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
target, level, internalformat, width, height, border, format, type, pixels);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (!validImageSize(level, width, height))
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
+ 0, 0, width, height, border, format, type, pixels))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- if (internalformat != GLint(format))
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3TexImageParameters(context, target, level, internalformat, false, false,
+ 0, 0, 0, width, height, 1, border, format, type, pixels))
{
- return gl::error(GL_INVALID_OPERATION);
+ return;
}
- // validate <type> by itself (used as secondary key below)
- switch (type)
+ switch (target)
{
- 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:
+ case GL_TEXTURE_2D:
+ {
+ gl::Texture2D *texture = context->getTexture2D();
+ texture->setImage(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
+ }
break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- // 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_TEXTURE_CUBE_MAP_POSITIVE_X:
{
- case GL_UNSIGNED_BYTE:
- case GL_FLOAT:
- case GL_HALF_FLOAT_OES:
- break;
- default:
- return gl::error(GL_INVALID_OPERATION);
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+ texture->setImagePosX(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
}
break;
- case GL_RGB:
- switch (type)
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
{
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_FLOAT:
- case GL_HALF_FLOAT_OES:
- break;
- default:
- return gl::error(GL_INVALID_OPERATION);
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+ texture->setImageNegX(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
}
break;
- case GL_RGBA:
- switch (type)
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
{
- 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:
- return gl::error(GL_INVALID_OPERATION);
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+ texture->setImagePosY(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
}
break;
- case GL_BGRA_EXT:
- switch (type)
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
{
- case GL_UNSIGNED_BYTE:
- break;
- default:
- return gl::error(GL_INVALID_OPERATION);
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+ texture->setImageNegY(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
}
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_TEXTURE_CUBE_MAP_POSITIVE_Z:
{
- case GL_UNSIGNED_SHORT:
- case GL_UNSIGNED_INT:
- break;
- default:
- return gl::error(GL_INVALID_OPERATION);
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+ texture->setImagePosZ(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
}
break;
- case GL_DEPTH_STENCIL_OES:
- switch (type)
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
{
- case GL_UNSIGNED_INT_24_8_OES:
- break;
- default:
- return gl::error(GL_INVALID_OPERATION);
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+ texture->setImageNegZ(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
}
break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ default: UNREACHABLE();
}
+ }
+}
- if (border != 0)
+void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateTexParamParameters(context, pname, static_cast<GLint>(param)))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Texture *texture = context->getTargetTexture(target);
- if (context)
+ if (!texture)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = gl::uiround<GLenum>(param); break;
+ case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = gl::uiround<GLenum>(param); break;
+ case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = gl::uiround<GLenum>(param); break;
+ case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = gl::uiround<GLenum>(param); break;
+ case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = gl::uiround<GLenum>(param); break;
+ case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(gl::uiround<GLenum>(param)); break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min(param, context->getExtensions().maxTextureAnisotropy); break;
+ case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = gl::uiround<GLenum>(param); break;
+ case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = gl::uiround<GLenum>(param); break;
+ case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = gl::uiround<GLenum>(param); break;
+ case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = gl::uiround<GLenum>(param); break;
+ case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = gl::uiround<GLenum>(param); break;
+ case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = gl::uiround<GLenum>(param); break;
+ case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = gl::iround<GLint>(param); break;
+ case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = gl::iround<GLint>(param); break;
+ case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = param; break;
+ case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = param; break;
+ default: UNREACHABLE(); break;
+ }
+ }
+}
+
+void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+{
+ glTexParameterf(target, pname, (GLfloat)*params);
+}
+
+void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateTexParamParameters(context, pname, param))
{
- if (level > context->getMaximumTextureLevel())
+ return;
+ }
+
+ gl::Texture *texture = context->getTargetTexture(target);
+
+ if (!texture)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = (GLenum)param; break;
+ case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = (GLenum)param; break;
+ case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = (GLenum)param; break;
+ case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = (GLenum)param; break;
+ case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = (GLenum)param; break;
+ case GL_TEXTURE_USAGE_ANGLE: texture->setUsage((GLenum)param); break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min((float)param, context->getExtensions().maxTextureAnisotropy); break;
+ case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = (GLenum)param; break;
+ case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = (GLenum)param; break;
+ case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = (GLenum)param; break;
+ case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = (GLenum)param; break;
+ case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = (GLenum)param; break;
+ case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = (GLenum)param; break;
+ case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = param; break;
+ case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = param; break;
+ case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = (GLfloat)param; break;
+ case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = (GLfloat)param; break;
+ default: UNREACHABLE(); break;
+ }
+ }
+}
+
+void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
+{
+ glTexParameteri(target, pname, *params);
+}
+
+void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+ target, levels, internalformat, width, height);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!context->getExtensions().textureStorage)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height))
+ {
+ return;
+ }
+
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1))
+ {
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
{
- return gl::error(GL_INVALID_VALUE);
+ gl::Texture2D *texture2d = context->getTexture2D();
+ texture2d->storage(levels, internalformat, width, height);
}
+ break;
- switch (target)
+ case GL_TEXTURE_CUBE_MAP:
{
- case GL_TEXTURE_2D:
- if (width > (context->getMaximumTextureDimension() >> level) ||
- height > (context->getMaximumTextureDimension() >> level))
- {
- return gl::error(GL_INVALID_VALUE);
- }
- 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 (width != height)
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
+ textureCube->storage(levels, internalformat, width);
+ }
+ break;
- if (width > (context->getMaximumCubeTextureDimension() >> level) ||
- height > (context->getMaximumCubeTextureDimension() >> level))
- {
- return gl::error(GL_INVALID_VALUE);
- }
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid* pixels)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
+ "const GLvoid* pixels = 0x%0.8p)",
+ target, level, xoffset, yoffset, width, height, format, type, pixels);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true,
+ xoffset, yoffset, width, height, 0, format, type, pixels))
+ {
+ return;
+ }
+
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true,
+ xoffset, yoffset, 0, width, height, 1, 0, format, type, pixels))
+ {
+ return;
+ }
+
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ {
+ gl::Texture2D *texture = context->getTexture2D();
+ texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels);
}
+ break;
- switch (format) {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (context->supportsDXT1Textures())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (context->supportsDXT3Textures())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (context->supportsDXT5Textures())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_STENCIL_OES:
- if (!context->supportsDepthTextures())
- {
- return gl::error(GL_INVALID_VALUE);
- }
- if (target != GL_TEXTURE_2D)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- // OES_depth_texture supports loading depth data and multiple levels,
- // but ANGLE_depth_texture does not
- if (pixels != NULL || level != 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- break;
- default:
- 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:
+ {
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+ texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels);
}
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ }
+}
+
+void __stdcall glUniform1f(GLint location, GLfloat x)
+{
+ glUniform1fv(location, 1, &x);
+}
+
+void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_FLOAT, location, count))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniform1fv(location, count, v);
+ }
+}
+
+void __stdcall glUniform1i(GLint location, GLint x)
+{
+ glUniform1iv(location, 1, &x);
+}
+
+void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_INT, location, count))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniform1iv(location, count, v);
+ }
+}
+
+void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y)
+{
+ GLfloat xy[2] = {x, y};
+
+ glUniform2fv(location, 1, xy);
+}
+
+void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniform2fv(location, count, v);
+ }
+}
+
+void __stdcall glUniform2i(GLint location, GLint x, GLint y)
+{
+ GLint xy[2] = {x, y};
+
+ glUniform2iv(location, 1, xy);
+}
+
+void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_INT_VEC2, location, count))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniform2iv(location, count, v);
+ }
+}
+
+void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat xyz[3] = {x, y, z};
+
+ glUniform3fv(location, 1, xyz);
+}
+
+void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniform3fv(location, count, v);
+ }
+}
+
+void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z)
+{
+ GLint xyz[3] = {x, y, z};
+
+ glUniform3iv(location, 1, xyz);
+}
+
+void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_INT_VEC3, location, count))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniform3iv(location, count, v);
+ }
+}
+
+void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GLfloat xyzw[4] = {x, y, z, w};
+
+ glUniform4fv(location, 1, xyzw);
+}
+
+void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniform4fv(location, count, v);
+ }
+}
+
+void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+ GLint xyzw[4] = {x, y, z, w};
- if (type == GL_FLOAT)
+ glUniform4iv(location, 1, xyzw);
+}
+
+void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_INT_VEC4, location, count))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniform4iv(location, count, v);
+ }
+}
+
+void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniformMatrix2fv(location, count, transpose, value);
+ }
+}
+
+void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniformMatrix3fv(location, count, transpose, value);
+ }
+}
+
+void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniformMatrix4fv(location, count, transpose, value);
+ }
+}
+
+void __stdcall glUseProgram(GLuint program)
+{
+ EVENT("(GLuint program = %d)", program);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject && program != 0)
+ {
+ if (context->getShader(program))
{
- if (!context->supportsFloat32Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- else if (type == GL_HALF_FLOAT_OES)
+ else
{
- if (!context->supportsFloat16Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+ }
- if (target == GL_TEXTURE_2D)
- {
- gl::Texture2D *texture = context->getTexture2D();
+ if (program != 0 && !programObject->isLinked())
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (!texture)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ context->useProgram(program);
+ }
+}
- if (texture->isImmutable())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+void __stdcall glValidateProgram(GLuint program)
+{
+ EVENT("(GLuint program = %d)", program);
- texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels);
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
else
{
- gl::TextureCubeMap *texture = context->getTextureCubeMap();
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
- if (!texture)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ programObject->validate(context->getCaps());
+ }
+}
- if (texture->isImmutable())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+void __stdcall glVertexAttrib1f(GLuint index, GLfloat x)
+{
+ EVENT("(GLuint index = %d, GLfloat x = %f)", index, x);
- switch (target)
- {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- texture->setImagePosX(level, width, height, format, type, context->getUnpackAlignment(), pixels);
- break;
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- texture->setImageNegX(level, width, height, format, type, context->getUnpackAlignment(), pixels);
- break;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- texture->setImagePosY(level, width, height, format, type, context->getUnpackAlignment(), pixels);
- break;
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- texture->setImageNegY(level, width, height, format, type, context->getUnpackAlignment(), pixels);
- break;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- texture->setImagePosZ(level, width, height, format, type, context->getUnpackAlignment(), pixels);
- break;
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- texture->setImageNegZ(level, width, height, format, type, context->getUnpackAlignment(), pixels);
- break;
- default: UNREACHABLE();
- }
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { x, 0, 0, 1 };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values)
+{
+ EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { values[0], 0, 0, 1 };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+{
+ EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { x, y, 0, 1 };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values)
+{
+ EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { values[0], values[1], 0, 1 };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { x, y, z, 1 };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values)
+{
+ EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { values[0], values[1], values[2], 1 };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { x, y, z, w };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values)
+{
+ EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->getState().setVertexAttribf(index, values);
+ }
+}
+
+void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
+{
+ EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->setVertexAttribDivisor(index, divisor);
+ }
+}
+
+void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+{
+ EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
+ "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
+ index, size, type, normalized, stride, ptr);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (size < 1 || size > 4)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ switch (type)
+ {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ case GL_FIXED:
+ case GL_FLOAT:
+ break;
+
+ case GL_HALF_FLOAT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (stride < 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+
+ if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // [OpenGL ES 3.0.2] Section 2.8 page 24:
+ // An INVALID_OPERATION error is generated when a non-zero vertex array object
+ // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
+ // and the pointer argument is not NULL.
+ if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && ptr != NULL)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type,
+ normalized == GL_TRUE, false, stride, ptr);
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (width < 0 || height < 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->getState().setViewportParams(x, y, width, height);
}
}
-void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param)
+// OpenGL ES 3.0 functions
+
+void __stdcall glReadBuffer(GLenum mode)
{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param);
+ EVENT("(GLenum mode = 0x%X)", mode);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (context)
+ // glReadBuffer
+ UNIMPLEMENTED();
+ }
+}
+
+void __stdcall glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices)
+{
+ EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, "
+ "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // glDrawRangeElements
+ UNIMPLEMENTED();
+ }
+}
+
+void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
+ "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, "
+ "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
+ target, level, internalformat, width, height, depth, border, format, type, pixels);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // validateES3TexImageFormat sets the error code if there is an error
+ if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false,
+ 0, 0, 0, width, height, depth, border, format, type, pixels))
{
- gl::Texture *texture;
+ return;
+ }
- switch (target)
+ switch(target)
+ {
+ case GL_TEXTURE_3D:
{
- case GL_TEXTURE_2D:
- texture = context->getTexture2D();
- break;
- case GL_TEXTURE_CUBE_MAP:
- texture = context->getTextureCubeMap();
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ gl::Texture3D *texture = context->getTexture3D();
+ texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels);
}
+ break;
- switch (pname)
+ case GL_TEXTURE_2D_ARRAY:
{
- case GL_TEXTURE_WRAP_S:
- if (!texture->setWrapS((GLenum)param))
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_TEXTURE_WRAP_T:
- if (!texture->setWrapT((GLenum)param))
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_TEXTURE_MIN_FILTER:
- if (!texture->setMinFilter((GLenum)param))
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_TEXTURE_MAG_FILTER:
- if (!texture->setMagFilter((GLenum)param))
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_TEXTURE_USAGE_ANGLE:
- if (!texture->setUsage((GLenum)param))
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- if (!context->supportsTextureFilterAnisotropy())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy()))
- {
- return gl::error(GL_INVALID_VALUE);
- }
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ gl::Texture2DArray *texture = context->getTexture2DArray();
+ texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels);
}
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
+ target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // validateES3TexImageFormat sets the error code if there is an error
+ if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true,
+ xoffset, yoffset, zoffset, width, height, depth, 0,
+ format, type, pixels))
+ {
+ return;
+ }
+
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0 || depth == 0)
+ {
+ return;
+ }
+
+ switch(target)
+ {
+ case GL_TEXTURE_3D:
+ {
+ gl::Texture3D *texture = context->getTexture3D();
+ texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels);
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ gl::Texture2DArray *texture = context->getTexture2DArray();
+ texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels);
+ }
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
}
}
-void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
{
- glTexParameterf(target, pname, (GLfloat)*params);
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+ target, level, xoffset, yoffset, zoffset, x, y, width, height);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset,
+ x, y, width, height, 0))
+ {
+ return;
+ }
+
+ gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
+ gl::Texture *texture = NULL;
+ switch (target)
+ {
+ case GL_TEXTURE_3D:
+ texture = context->getTexture3D();
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ texture = context->getTexture2DArray();
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
+ }
}
-void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param)
+void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
+ "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
+ "const GLvoid* data = 0x%0.8p)",
+ target, level, internalformat, width, height, depth, border, imageSize, data);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (context)
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
{
- gl::Texture *texture;
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- switch (target)
+ // validateES3TexImageFormat sets the error code if there is an error
+ if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false,
+ 0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data))
+ {
+ return;
+ }
+
+ switch(target)
+ {
+ case GL_TEXTURE_3D:
{
- case GL_TEXTURE_2D:
- texture = context->getTexture2D();
- break;
- case GL_TEXTURE_CUBE_MAP:
- texture = context->getTextureCubeMap();
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ gl::Texture3D *texture = context->getTexture3D();
+ texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
}
+ break;
- switch (pname)
+ case GL_TEXTURE_2D_ARRAY:
{
- case GL_TEXTURE_WRAP_S:
- if (!texture->setWrapS((GLenum)param))
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_TEXTURE_WRAP_T:
- if (!texture->setWrapT((GLenum)param))
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_TEXTURE_MIN_FILTER:
- if (!texture->setMinFilter((GLenum)param))
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_TEXTURE_MAG_FILTER:
- if (!texture->setMagFilter((GLenum)param))
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_TEXTURE_USAGE_ANGLE:
- if (!texture->setUsage((GLenum)param))
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- if (!context->supportsTextureFilterAnisotropy())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy()))
- {
- return gl::error(GL_INVALID_VALUE);
- }
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ gl::Texture2DArray *texture = context->getTexture2DArray();
+ texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
}
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
+ "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
+ target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (!data)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ // validateES3TexImageFormat sets the error code if there is an error
+ if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true,
+ 0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data))
+ {
+ return;
+ }
+
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ switch(target)
+ {
+ case GL_TEXTURE_3D:
+ {
+ gl::Texture3D *texture = context->getTexture3D();
+ texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth,
+ format, imageSize, data);
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ gl::Texture2DArray *texture = context->getTexture2DArray();
+ texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth,
+ format, imageSize, data);
+ }
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
}
}
-void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
+void __stdcall glGenQueries(GLsizei n, GLuint* ids)
{
- glTexParameteri(target, pname, *params);
+ EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (n < 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (GLsizei i = 0; i < n; i++)
+ {
+ ids[i] = context->createQuery();
+ }
+ }
}
-void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+void __stdcall glDeleteQueries(GLsizei n, const GLuint* ids)
{
- EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
- target, levels, internalformat, width, height);
+ EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- if (width < 1 || height < 1 || levels < 1)
+ if (n < 0)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- if (target == GL_TEXTURE_CUBE_MAP && width != height)
+ for (GLsizei i = 0; i < n; i++)
{
- return gl::error(GL_INVALID_VALUE);
+ context->deleteQuery(ids[i]);
}
+ }
+}
- if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
+GLboolean __stdcall glIsQuery(GLuint id)
+{
+ EVENT("(GLuint id = %u)", id);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
}
- GLenum format = gl::ExtractFormat(internalformat);
- GLenum type = gl::ExtractType(internalformat);
+ return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
+ }
- if (format == GL_NONE || type == GL_NONE)
+ return GL_FALSE;
+}
+
+void __stdcall glBeginQuery(GLenum target, GLuint id)
+{
+ EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ if (!ValidateBeginQuery(context, target, id))
+ {
+ return;
+ }
- if (context)
+ gl::Error error = context->beginQuery(target, id);
+ if (error.isError())
{
- switch (target)
- {
- case GL_TEXTURE_2D:
- if (width > context->getMaximumTextureDimension() ||
- height > context->getMaximumTextureDimension())
- {
- return gl::error(GL_INVALID_VALUE);
- }
- break;
- case GL_TEXTURE_CUBE_MAP:
- if (width > context->getMaximumCubeTextureDimension() ||
- height > context->getMaximumCubeTextureDimension())
- {
- return gl::error(GL_INVALID_VALUE);
- }
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void __stdcall glEndQuery(GLenum target)
+{
+ EVENT("(GLenum target = 0x%X)", target);
- if (levels != 1 && !context->supportsNonPower2Texture())
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateEndQuery(context, target))
+ {
+ return;
+ }
+
+ gl::Error error = context->endQuery(target);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void __stdcall glGetQueryiv(GLenum target, GLenum pname, GLint* params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidQueryType(context, target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_CURRENT_QUERY:
+ params[0] = static_cast<GLint>(context->getState().getActiveQueryId(target));
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void __stdcall glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
+{
+ EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
+
+ if (!queryObject)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (context->getState().getActiveQueryId(queryObject->getType()) == id)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch(pname)
+ {
+ case GL_QUERY_RESULT_EXT:
{
- if (!gl::isPow2(width) || !gl::isPow2(height))
+ gl::Error error = queryObject->getResult(params);
+ if (error.isError())
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(error);
+ return;
}
}
+ break;
- switch (internalformat)
+ case GL_QUERY_RESULT_AVAILABLE_EXT:
{
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (!context->supportsDXT1Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (!context->supportsDXT3Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (!context->supportsDXT5Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_RGBA32F_EXT:
- case GL_RGB32F_EXT:
- case GL_ALPHA32F_EXT:
- case GL_LUMINANCE32F_EXT:
- case GL_LUMINANCE_ALPHA32F_EXT:
- if (!context->supportsFloat32Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- break;
- case GL_RGBA16F_EXT:
- case GL_RGB16F_EXT:
- case GL_ALPHA16F_EXT:
- case GL_LUMINANCE16F_EXT:
- case GL_LUMINANCE_ALPHA16F_EXT:
- if (!context->supportsFloat16Textures())
+ gl::Error error = queryObject->isResultAvailable(params);
+ if (error.isError())
{
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(error);
+ return;
}
- break;
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT32_OES:
- case GL_DEPTH24_STENCIL8_OES:
- if (!context->supportsDepthTextures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- if (target != GL_TEXTURE_2D)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- // ANGLE_depth_texture only supports 1-level textures
- if (levels != 1)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- break;
- default:
- break;
}
+ break;
- if (target == GL_TEXTURE_2D)
- {
- gl::Texture2D *texture = context->getTexture2D();
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
- if (!texture || texture->id() == 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+GLboolean __stdcall glUnmapBuffer(GLenum target)
+{
+ EVENT("(GLenum target = 0x%X)", target);
- if (texture->isImmutable())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
+ }
- texture->storage(levels, internalformat, width, height);
- }
- else if (target == GL_TEXTURE_CUBE_MAP)
- {
- gl::TextureCubeMap *texture = context->getTextureCubeMap();
+ return glUnmapBufferOES(target);
+ }
- if (!texture || texture->id() == 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ return GL_FALSE;
+}
- if (texture->isImmutable())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+void __stdcall glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
- texture->storage(levels, internalformat, width);
- }
- else UNREACHABLE();
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
+
+ glGetBufferPointervOES(target, pname, params);
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glDrawBuffers(GLsizei n, const GLenum* bufs)
+{
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ glDrawBuffersEXT(n, bufs);
}
}
-void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLenum format, GLenum type, const GLvoid* pixels)
+void __stdcall glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
- "const GLvoid* pixels = 0x%0.8p)",
- target, level, xoffset, yoffset, width, height, format, type, pixels);
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (!gl::IsInternalTextureTarget(target))
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose))
{
- return gl::error(GL_INVALID_ENUM);
+ return;
}
- if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniformMatrix2x3fv(location, count, transpose, value);
+ }
+}
+
+void __stdcall glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniformMatrix3x2fv(location, count, transpose, value);
+ }
+}
+
+void __stdcall glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- if (!checkTextureFormatType(format, type))
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniformMatrix2x4fv(location, count, transpose, value);
+ }
+}
+
+void __stdcall glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose))
{
- return; // error is set by helper function
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniformMatrix4x2fv(location, count, transpose, value);
+ }
+}
- if (context)
+void __stdcall glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniformMatrix3x4fv(location, count, transpose, value);
+ }
+}
+
+void __stdcall glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniformMatrix4x3fv(location, count, transpose, value);
+ }
+}
+
+void __stdcall glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+{
+ EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, "
+ "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
+ srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter,
+ false))
+ {
+ return;
+ }
+
+ context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
+ }
+}
+
+void __stdcall glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+ target, samples, internalformat, width, height);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat,
+ width, height, false))
+ {
+ return;
+ }
+
+ context->setRenderbufferStorage(width, height, internalformat, samples);
+ }
+}
+
+void __stdcall glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+{
+ EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)",
+ target, attachment, texture, level, layer);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateFramebufferTextureLayer(context, target, attachment, texture,
+ level, layer))
+ {
+ return;
+ }
+
+ gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ gl::Texture *textureObject = context->getTexture(texture);
+ GLenum textarget = textureObject ? textureObject->getTarget() : GL_NONE;
+
+ if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+ {
+ const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
+ framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, layer);
+ }
+ else
{
- if (level > context->getMaximumTextureLevel())
+ switch (attachment)
{
- return gl::error(GL_INVALID_VALUE);
+ case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level, layer); break;
+ case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level, layer); break;
+ case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, layer); break;
}
+ }
+ }
+}
+
+GLvoid* __stdcall glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+{
+ EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
+ target, offset, length, access);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ return glMapBufferRangeEXT(target, offset, length, access);
+ }
+
+ return NULL;
+}
+
+void __stdcall glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
+{
+ EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ glFlushMappedBufferRangeEXT(target, offset, length);
+ }
+}
+
+void __stdcall glBindVertexArray(GLuint array)
+{
+ EVENT("(GLuint array = %u)", array);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ gl::VertexArray *vao = context->getVertexArray(array);
+
+ if (!vao)
+ {
+ // The default VAO should always exist
+ ASSERT(array != 0);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->bindVertexArray(array);
+ }
+}
+
+void __stdcall glDeleteVertexArrays(GLsizei n, const GLuint* arrays)
+{
+ EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays);
- if (format == GL_FLOAT)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (n < 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+ {
+ if (arrays[arrayIndex] != 0)
{
- if (!context->supportsFloat32Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
+ context->deleteVertexArray(arrays[arrayIndex]);
}
- else if (format == GL_HALF_FLOAT_OES)
+ }
+ }
+}
+
+void __stdcall glGenVertexArrays(GLsizei n, GLuint* arrays)
+{
+ EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (n < 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+ {
+ arrays[arrayIndex] = context->createVertexArray();
+ }
+ }
+}
+
+GLboolean __stdcall glIsVertexArray(GLuint array)
+{
+ EVENT("(GLuint array = %u)", array);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
+ }
+
+ if (array == 0)
+ {
+ return GL_FALSE;
+ }
+
+ gl::VertexArray *vao = context->getVertexArray(array);
+
+ return (vao != NULL ? GL_TRUE : GL_FALSE);
+ }
+
+ return GL_FALSE;
+}
+
+void __stdcall glGetIntegeri_v(GLenum target, GLuint index, GLint* data)
+{
+ EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)",
+ target, index, data);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ if (index >= caps.maxTransformFeedbackSeparateAttributes)
{
- if (!context->supportsFloat16Textures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- else if (gl::IsDepthTexture(format))
+ break;
+
+ case GL_UNIFORM_BUFFER_START:
+ case GL_UNIFORM_BUFFER_SIZE:
+ case GL_UNIFORM_BUFFER_BINDING:
+ if (index >= caps.maxCombinedUniformBlocks)
{
- if (!context->supportsDepthTextures())
- {
- return gl::error(GL_INVALID_ENUM);
- }
- if (target != GL_TEXTURE_2D)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- // OES_depth_texture supports loading depth data, but ANGLE_depth_texture does not
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- if (width == 0 || height == 0 || pixels == NULL)
+ if (!(context->getIndexedIntegerv(target, index, data)))
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
{
+ context->recordError(gl::Error(GL_INVALID_ENUM));
return;
}
- if (target == GL_TEXTURE_2D)
+ if (numParams == 0)
{
- gl::Texture2D *texture = context->getTexture2D();
- if (validateSubImageParams2D(false, width, height, xoffset, yoffset, level, format, type, texture))
- {
- texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
- }
+ return; // it is known that pname is valid, but there are no parameters to return
}
- else if (gl::IsCubemapTextureTarget(target))
+
+ if (nativeType == GL_INT_64_ANGLEX)
{
- gl::TextureCubeMap *texture = context->getTextureCubeMap();
- if (validateSubImageParamsCube(false, width, height, xoffset, yoffset, target, level, format, type, texture))
+ GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<int>::min());
+ GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<int>::max());
+ GLint64 *int64Params = new GLint64[numParams];
+
+ context->getIndexedInteger64v(target, index, int64Params);
+
+ for (unsigned int i = 0; i < numParams; ++i)
{
- texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
+ GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue);
+ data[i] = static_cast<GLint>(clampedValue);
}
+
+ delete [] int64Params;
}
else
{
@@ -5976,897 +5939,2368 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint
}
}
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glBeginTransformFeedback(GLenum primitiveMode)
+{
+ EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch (primitiveMode)
+ {
+ case GL_TRIANGLES:
+ case GL_LINES:
+ case GL_POINTS:
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != NULL);
+
+ if (transformFeedback->isStarted())
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (transformFeedback->isPaused())
+ {
+ transformFeedback->resume();
+ }
+ else
+ {
+ transformFeedback->start(primitiveMode);
+ }
}
}
-void __stdcall glUniform1f(GLint location, GLfloat x)
+void __stdcall glEndTransformFeedback(void)
{
- glUniform1fv(location, 1, &x);
+ EVENT("(void)");
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != NULL);
+
+ if (!transformFeedback->isStarted())
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ transformFeedback->stop();
+ }
}
-void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+void __stdcall glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)",
+ target, index, buffer, offset, size);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- if (location == -1)
+ const gl::Caps &caps = context->getCaps();
+ switch (target)
{
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ if (index >= caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ case GL_UNIFORM_BUFFER:
+ if (index >= caps.maxUniformBufferBindings)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
return;
}
- gl::Context *context = gl::getNonLostContext();
+ if (buffer != 0 && size <= 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- if (context)
+ switch (target)
{
- gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
- if (!programBinary)
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+
+ // size and offset must be a multiple of 4
+ if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- if (!programBinary->setUniform1fv(location, count, v))
+ context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size);
+ context->bindGenericTransformFeedbackBuffer(buffer);
+ break;
+
+ case GL_UNIFORM_BUFFER:
+
+ // it is an error to bind an offset not a multiple of the alignment
+ if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+
+ context->bindIndexedUniformBuffer(buffer, index, offset, size);
+ context->bindGenericUniformBuffer(buffer);
+ break;
+
+ default:
+ UNREACHABLE();
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
-void __stdcall glUniform1i(GLint location, GLint x)
+void __stdcall glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
{
- glUniform1iv(location, 1, &x);
+ EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)",
+ target, index, buffer);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ if (index >= caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ case GL_UNIFORM_BUFFER:
+ if (index >= caps.maxUniformBufferBindings)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0);
+ context->bindGenericTransformFeedbackBuffer(buffer);
+ break;
+
+ case GL_UNIFORM_BUFFER:
+ context->bindIndexedUniformBuffer(buffer, index, 0, 0);
+ context->bindGenericUniformBuffer(buffer);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ }
}
-void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v)
+void __stdcall glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)",
+ program, count, varyings, bufferMode);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- if (location == -1)
+ if (count < 0)
{
+ context->recordError(gl::Error(GL_INVALID_VALUE));
return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ const gl::Caps &caps = context->getCaps();
+ switch (bufferMode)
{
- gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
- if (!programBinary)
+ case GL_INTERLEAVED_ATTRIBS:
+ break;
+ case GL_SEPARATE_ATTRIBS:
+ if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+ break;
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- if (!programBinary->setUniform1iv(location, count, v))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ if (!gl::ValidProgram(context, program))
+ {
+ return;
}
+
+ gl::Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
+{
+ EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, "
+ "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
+ program, index, bufSize, length, size, type, name);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (bufSize < 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (!gl::ValidProgram(context, program))
+ {
+ return;
+ }
+
+ gl::Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
}
}
-void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y)
+void __stdcall glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer)
{
- GLfloat xy[2] = {x, y};
+ EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)",
+ index, size, type, stride, pointer);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (size < 1 || size > 4)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ switch (type)
+ {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ break;
- glUniform2fv(location, 1, (GLfloat*)&xy);
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (stride < 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // [OpenGL ES 3.0.2] Section 2.8 page 24:
+ // An INVALID_OPERATION error is generated when a non-zero vertex array object
+ // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
+ // and the pointer argument is not NULL.
+ if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && pointer != NULL)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true,
+ stride, pointer);
+ }
}
-void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
+void __stdcall glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
+ index, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
-
- if (location == -1)
+
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
{
+ context->recordError(gl::Error(GL_INVALID_VALUE));
return;
}
- gl::Context *context = gl::getNonLostContext();
+ const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index);
- if (context)
+ if (!gl::ValidateGetVertexAttribParameters(context, pname))
{
- gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
- if (!programBinary)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ return;
+ }
- if (!programBinary->setUniform2fv(location, count, v))
+ if (pname == GL_CURRENT_VERTEX_ATTRIB)
+ {
+ const gl::VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
+ for (int i = 0; i < 4; ++i)
{
- return gl::error(GL_INVALID_OPERATION);
+ params[i] = currentValueData.IntValues[i];
}
}
+ else
+ {
+ *params = gl::QuerySingleVertexAttributeParameter<GLint>(attribState, pname);
+ }
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
+{
+ EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)",
+ index, pname, params);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index);
+
+ if (!gl::ValidateGetVertexAttribParameters(context, pname))
+ {
+ return;
+ }
+
+ if (pname == GL_CURRENT_VERTEX_ATTRIB)
+ {
+ const gl::VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
+ for (int i = 0; i < 4; ++i)
+ {
+ params[i] = currentValueData.UnsignedIntValues[i];
+ }
+ }
+ else
+ {
+ *params = gl::QuerySingleVertexAttributeParameter<GLuint>(attribState, pname);
+ }
}
}
-void __stdcall glUniform2i(GLint location, GLint x, GLint y)
+void __stdcall glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
{
- GLint xy[4] = {x, y};
+ EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
+ index, x, y, z, w);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- glUniform2iv(location, 1, (GLint*)&xy);
+ GLint vals[4] = { x, y, z, w };
+ context->getState().setVertexAttribi(index, vals);
+ }
}
-void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v)
+void __stdcall glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)",
+ index, x, y, z, w);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- if (location == -1)
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
{
+ context->recordError(gl::Error(GL_INVALID_VALUE));
return;
}
- gl::Context *context = gl::getNonLostContext();
+ GLuint vals[4] = { x, y, z, w };
+ context->getState().setVertexAttribu(index, vals);
+ }
+}
+
+void __stdcall glVertexAttribI4iv(GLuint index, const GLint* v)
+{
+ EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v);
- if (context)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
{
- gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
- if (!programBinary)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (!programBinary->setUniform2iv(location, count, v))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+
+ context->getState().setVertexAttribi(index, v);
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glVertexAttribI4uiv(GLuint index, const GLuint* v)
+{
+ EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->getState().setVertexAttribu(index, v);
}
}
-void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+void __stdcall glGetUniformuiv(GLuint program, GLint location, GLuint* params)
{
- GLfloat xyz[3] = {x, y, z};
+ EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)",
+ program, location, params);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateGetUniformuiv(context, program, location, params))
+ {
+ return;
+ }
+
+ gl::Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+ ASSERT(programBinary);
- glUniform3fv(location, 1, (GLfloat*)&xyz);
+ programBinary->getUniformuiv(location, params);
+ }
}
-void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
+GLint __stdcall glGetFragDataLocation(GLuint program, const GLchar *name)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)",
+ program, name);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return -1;
}
- if (location == -1)
+ if (program == 0)
{
- return;
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return -1;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context)
+ if (!programObject || !programObject->isLinked())
{
- gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
- if (!programBinary)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return -1;
+ }
- if (!programBinary->setUniform3fv(location, count, v))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+ if (!programBinary)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return -1;
}
+
+ return programBinary->getFragDataLocation(name);
}
- catch(std::bad_alloc&)
+
+ return 0;
+}
+
+void __stdcall glUniform1ui(GLint location, GLuint v0)
+{
+ glUniform1uiv(location, 1, &v0);
+}
+
+void __stdcall glUniform2ui(GLint location, GLuint v0, GLuint v1)
+{
+ const GLuint xy[] = { v0, v1 };
+ glUniform2uiv(location, 1, xy);
+}
+
+void __stdcall glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
+{
+ const GLuint xyz[] = { v0, v1, v2 };
+ glUniform3uiv(location, 1, xyz);
+}
+
+void __stdcall glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ const GLuint xyzw[] = { v0, v1, v2, v3 };
+ glUniform4uiv(location, 1, xyzw);
+}
+
+void __stdcall glUniform1uiv(GLint location, GLsizei count, const GLuint* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
+ location, count, value);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniform1uiv(location, count, value);
}
}
-void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z)
+void __stdcall glUniform2uiv(GLint location, GLsizei count, const GLuint* value)
{
- GLint xyz[3] = {x, y, z};
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
+ location, count, value);
- glUniform3iv(location, 1, (GLint*)&xyz);
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count))
+ {
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniform2uiv(location, count, value);
+ }
}
-void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v)
+void __stdcall glUniform3uiv(GLint location, GLsizei count, const GLuint* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)",
+ location, count, value);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0)
+ if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- if (location == -1)
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniform3uiv(location, count, value);
+ }
+}
+
+void __stdcall glUniform4uiv(GLint location, GLsizei count, const GLuint* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
+ location, count, value);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count))
{
return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ programBinary->setUniform4uiv(location, count, value);
+ }
+}
- if (context)
+void __stdcall glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value)
+{
+ EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)",
+ buffer, drawbuffer, value);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateClearBuffer(context))
+ {
+ return;
+ }
+
+ switch (buffer)
{
- gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
- if (!programBinary)
+ case GL_COLOR:
+ if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+ break;
- if (!programBinary->setUniform3iv(location, count, v))
+ case GL_STENCIL:
+ if (drawbuffer != 0)
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- }
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
-}
+ break;
-void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- GLfloat xyzw[4] = {x, y, z, w};
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- glUniform4fv(location, 1, (GLfloat*)&xyzw);
+ gl::Error error = context->clearBufferiv(buffer, drawbuffer, value);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
}
-void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
+void __stdcall glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)",
+ buffer, drawbuffer, value);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0)
+ if (!ValidateClearBuffer(context))
{
- return gl::error(GL_INVALID_VALUE);
+ return;
}
- if (location == -1)
+ switch (buffer)
{
+ case GL_COLOR:
+ if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ gl::Error error = context->clearBufferuiv(buffer, drawbuffer, value);
+ if (error.isError())
+ {
+ context->recordError(error);
return;
}
+ }
+}
- gl::Context *context = gl::getNonLostContext();
+void __stdcall glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)
+{
+ EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)",
+ buffer, drawbuffer, value);
- if (context)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!ValidateClearBuffer(context))
+ {
+ return;
+ }
+
+ switch (buffer)
{
- gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
- if (!programBinary)
+ case GL_COLOR:
+ if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+ break;
- if (!programBinary->setUniform4fv(location, count, v))
+ case GL_DEPTH:
+ if (drawbuffer != 0)
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ gl::Error error = context->clearBufferfv(buffer, drawbuffer, value);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
}
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+{
+ EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)",
+ buffer, drawbuffer, depth, stencil);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (!ValidateClearBuffer(context))
+ {
+ return;
+ }
+
+ switch (buffer)
+ {
+ case GL_DEPTH_STENCIL:
+ if (drawbuffer != 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ gl::Error error = context->clearBufferfi(buffer, drawbuffer, depth, stencil);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
}
}
-void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+const GLubyte* __stdcall glGetStringi(GLenum name, GLuint index)
{
- GLint xyzw[4] = {x, y, z, w};
+ EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ if (name != GL_EXTENSIONS)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return NULL;
+ }
+
+ if (index >= context->getExtensionStringCount())
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return NULL;
+ }
+
+ return reinterpret_cast<const GLubyte*>(context->getExtensionString(index).c_str());
+ }
- glUniform4iv(location, 1, (GLint*)&xyzw);
+ return NULL;
}
-void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v)
+void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
+ readTarget, writeTarget, readOffset, writeOffset, size);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- if (location == -1)
+ if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, readTarget))
{
+ context->recordError(gl::Error(GL_INVALID_ENUM));
return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Buffer *readBuffer = context->getState().getTargetBuffer(readTarget);
+ gl::Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget);
- if (context)
+ if (!readBuffer || !writeBuffer)
{
- gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
- if (!programBinary)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (!programBinary->setUniform4iv(location, count, v))
+ // Verify that readBuffer and writeBuffer are not currently mapped
+ if (readBuffer->isMapped() || writeBuffer->isMapped())
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (readOffset < 0 || writeOffset < 0 || size < 0 ||
+ static_cast<unsigned int>(readOffset + size) > readBuffer->getSize() ||
+ static_cast<unsigned int>(writeOffset + size) > writeBuffer->getSize())
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (readBuffer == writeBuffer && abs(readOffset - writeOffset) < size)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ // if size is zero, the copy is a successful no-op
+ if (size > 0)
+ {
+ gl::Error error = writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size);
+ if (error.isError())
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(error);
+ return;
}
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
-void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void __stdcall glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices)
{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
+ EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)",
+ program, uniformCount, uniformNames, uniformIndices);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0 || transpose != GL_FALSE)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- if (location == -1)
+ if (uniformCount < 0)
{
+ context->recordError(gl::Error(GL_INVALID_VALUE));
return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context)
+ if (!programObject)
{
- gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
- if (!programBinary)
+ if (context->getShader(program))
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
+ else
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
- if (!programBinary->setUniformMatrix2fv(location, count, value))
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+ if (!programObject->isLinked() || !programBinary)
+ {
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
{
- return gl::error(GL_INVALID_OPERATION);
+ uniformIndices[uniformId] = GL_INVALID_INDEX;
+ }
+ }
+ else
+ {
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ uniformIndices[uniformId] = programBinary->getUniformIndex(uniformNames[uniformId]);
}
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
}
}
-void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
+ EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
+ program, uniformCount, uniformIndices, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0 || transpose != GL_FALSE)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- if (location == -1)
+ if (uniformCount < 0)
{
+ context->recordError(gl::Error(GL_INVALID_VALUE));
return;
}
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context)
+ if (!programObject)
{
- gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
- if (!programBinary)
+ if (context->getShader(program))
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+ }
+
+ switch (pname)
+ {
+ case GL_UNIFORM_TYPE:
+ case GL_UNIFORM_SIZE:
+ case GL_UNIFORM_NAME_LENGTH:
+ case GL_UNIFORM_BLOCK_INDEX:
+ case GL_UNIFORM_OFFSET:
+ case GL_UNIFORM_ARRAY_STRIDE:
+ case GL_UNIFORM_MATRIX_STRIDE:
+ case GL_UNIFORM_IS_ROW_MAJOR:
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+
+ if (!programBinary && uniformCount > 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- if (!programBinary->setUniformMatrix3fv(location, count, value))
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ const GLuint index = uniformIndices[uniformId];
+
+ if (index >= (GLuint)programBinary->getActiveUniformCount())
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
}
+
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ const GLuint index = uniformIndices[uniformId];
+ params[uniformId] = programBinary->getActiveUniformi(index, pname);
+ }
}
- catch(std::bad_alloc&)
+}
+
+GLuint __stdcall glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName)
+{
+ EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return GL_INVALID_INDEX;
+ }
+
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return GL_INVALID_INDEX;
+ }
+ else
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return GL_INVALID_INDEX;
+ }
+ }
+
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+ if (!programBinary)
+ {
+ return GL_INVALID_INDEX;
+ }
+
+ return programBinary->getUniformBlockIndex(uniformBlockName);
}
+
+ return 0;
}
-void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params)
{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
+ EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
+ program, uniformBlockIndex, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (count < 0 || transpose != GL_FALSE)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
+ gl::Program *programObject = context->getProgram(program);
- if (location == -1)
+ if (!programObject)
{
+ if (context->getShader(program))
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+
+ if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount())
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
return;
}
- gl::Context *context = gl::getNonLostContext();
+ switch (pname)
+ {
+ case GL_UNIFORM_BLOCK_BINDING:
+ *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex));
+ break;
- if (context)
+ 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:
+ programBinary->getActiveUniformBlockiv(uniformBlockIndex, pname, params);
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void __stdcall glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName)
+{
+ EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)",
+ program, uniformBlockIndex, bufSize, length, uniformBlockName);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
{
- gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
- if (!programBinary)
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
-
- if (!programBinary->setUniformMatrix4fv(location, count, value))
+ else
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+
+ if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount())
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ programBinary->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
}
}
-void __stdcall glUseProgram(GLuint program)
+void __stdcall glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
{
- EVENT("(GLuint program = %d)", program);
+ EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)",
+ program, uniformBlockIndex, uniformBlockBinding);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (context)
+ if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
{
- gl::Program *programObject = context->getProgram(program);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- if (!programObject && program != 0)
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
{
- if (context->getShader(program))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
-
- if (program != 0 && !programObject->isLinked())
+ else
{
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+ }
- context->useProgram(program);
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+
+ // if never linked, there won't be any uniform blocks
+ if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount())
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+
+ programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
+{
+ EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
+ mode, first, count, instanceCount);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // glDrawArraysInstanced
+ UNIMPLEMENTED();
}
}
-void __stdcall glValidateProgram(GLuint program)
+void __stdcall glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount)
{
- EVENT("(GLuint program = %d)", program);
+ EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)",
+ mode, count, type, indices, instanceCount);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (context)
+ // glDrawElementsInstanced
+ UNIMPLEMENTED();
+ }
+}
+
+GLsync __stdcall glFenceSync(GLenum condition, GLbitfield flags)
+{
+ EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
{
- gl::Program *programObject = context->getProgram(program);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return 0;
+ }
- if (!programObject)
- {
- if (context->getShader(program))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
- else
- {
- return gl::error(GL_INVALID_VALUE);
- }
- }
+ if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return 0;
+ }
- programObject->validate();
+ if (flags != 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return 0;
}
+
+ return context->createFenceSync(condition);
}
- catch(std::bad_alloc&)
+
+ return NULL;
+}
+
+GLboolean __stdcall glIsSync(GLsync sync)
+{
+ EVENT("(GLsync sync = 0x%0.8p)", sync);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
+ }
+
+ return (context->getFenceSync(sync) != NULL);
}
+
+ return GL_FALSE;
}
-void __stdcall glVertexAttrib1f(GLuint index, GLfloat x)
+void __stdcall glDeleteSync(GLsync sync)
{
- EVENT("(GLuint index = %d, GLfloat x = %f)", index, x);
+ EVENT("(GLsync sync = 0x%0.8p)", sync);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (index >= gl::MAX_VERTEX_ATTRIBS)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync))
{
- GLfloat vals[4] = { x, 0, 0, 1 };
- context->setVertexAttrib(index, vals);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+
+ context->deleteFenceSync(sync);
}
- catch(std::bad_alloc&)
+}
+
+GLenum __stdcall glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
+ sync, flags, timeout);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return GL_WAIT_FAILED;
+ }
+
+ if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return GL_WAIT_FAILED;
+ }
+
+ gl::FenceSync *fenceSync = context->getFenceSync(sync);
+
+ if (!fenceSync)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return GL_WAIT_FAILED;
+ }
+
+ return fenceSync->clientWait(flags, timeout);
}
+
+ return GL_FALSE;
}
-void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values)
+void __stdcall glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
{
- EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+ EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
+ sync, flags, timeout);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (index >= gl::MAX_VERTEX_ATTRIBS)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ if (flags != 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- if (context)
+ if (timeout != GL_TIMEOUT_IGNORED)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ gl::FenceSync *fenceSync = context->getFenceSync(sync);
+
+ if (!fenceSync)
{
- GLfloat vals[4] = { values[0], 0, 0, 1 };
- context->setVertexAttrib(index, vals);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+
+ fenceSync->serverWait();
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glGetInteger64v(GLenum pname, GLint64* params)
+{
+ EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
+ pname, params);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
+ {
+ return;
+ }
+
+ if (nativeType == GL_INT_64_ANGLEX)
+ {
+ context->getInteger64v(pname, params);
+ }
+ else
+ {
+ CastStateValues(context, nativeType, pname, numParams, params);
+ }
}
}
-void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values)
{
- EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
+ EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)",
+ sync, pname, bufSize, length, values);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (index >= gl::MAX_VERTEX_ATTRIBS)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ if (bufSize < 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- if (context)
+ gl::FenceSync *fenceSync = context->getFenceSync(sync);
+
+ if (!fenceSync)
{
- GLfloat vals[4] = { x, y, 0, 1 };
- context->setVertexAttrib(index, vals);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_OBJECT_TYPE: values[0] = static_cast<GLint>(GL_SYNC_FENCE); break;
+ case GL_SYNC_STATUS: values[0] = static_cast<GLint>(fenceSync->getStatus()); break;
+ case GL_SYNC_CONDITION: values[0] = static_cast<GLint>(fenceSync->getCondition()); break;
+ case GL_SYNC_FLAGS: values[0] = 0; break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glGetInteger64i_v(GLenum target, GLuint index, GLint64* data)
+{
+ EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)",
+ target, index, data);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ if (index >= caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ case GL_UNIFORM_BUFFER_START:
+ case GL_UNIFORM_BUFFER_SIZE:
+ case GL_UNIFORM_BUFFER_BINDING:
+ if (index >= caps.maxUniformBufferBindings)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (!(context->getIndexedInteger64v(target, index, data)))
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (numParams == 0)
+ return; // it is known that pname is valid, but there are no parameters to return
+
+ if (nativeType == GL_INT)
+ {
+ GLint *intParams = new GLint[numParams];
+
+ context->getIndexedIntegerv(target, index, intParams);
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ data[i] = static_cast<GLint64>(intParams[i]);
+ }
+
+ delete [] intParams;
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
}
}
-void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values)
+void __stdcall glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params)
{
- EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
+ target, pname, params);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (index >= gl::MAX_VERTEX_ATTRIBS)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ if (!gl::ValidBufferTarget(context, target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- if (context)
+ if (!gl::ValidBufferParameter(context, pname))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ gl::Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (!buffer)
{
- GLfloat vals[4] = { values[0], values[1], 0, 1 };
- context->setVertexAttrib(index, vals);
+ // A null buffer means that "0" is bound to the requested buffer target
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_BUFFER_USAGE:
+ *params = static_cast<GLint64>(buffer->getUsage());
+ break;
+ case GL_BUFFER_SIZE:
+ *params = buffer->getSize();
+ break;
+ case GL_BUFFER_ACCESS_FLAGS:
+ *params = static_cast<GLint64>(buffer->getAccessFlags());
+ break;
+ case GL_BUFFER_MAPPED:
+ *params = static_cast<GLint64>(buffer->isMapped());
+ break;
+ case GL_BUFFER_MAP_OFFSET:
+ *params = buffer->getMapOffset();
+ break;
+ case GL_BUFFER_MAP_LENGTH:
+ *params = buffer->getMapLength();
+ break;
+ default: UNREACHABLE(); break;
}
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glGenSamplers(GLsizei count, GLuint* samplers)
+{
+ EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (count < 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < count; i++)
+ {
+ samplers[i] = context->createSampler();
+ }
}
}
-void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+void __stdcall glDeleteSamplers(GLsizei count, const GLuint* samplers)
{
- EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
+ EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (index >= gl::MAX_VERTEX_ATTRIBS)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ if (count < 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- if (context)
+ for (int i = 0; i < count; i++)
{
- GLfloat vals[4] = { x, y, z, 1 };
- context->setVertexAttrib(index, vals);
+ context->deleteSampler(samplers[i]);
}
}
- catch(std::bad_alloc&)
+}
+
+GLboolean __stdcall glIsSampler(GLuint sampler)
+{
+ EVENT("(GLuint sampler = %u)", sampler);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
+ }
+
+ return context->isSampler(sampler);
}
+
+ return GL_FALSE;
}
-void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values)
+void __stdcall glBindSampler(GLuint unit, GLuint sampler)
{
- EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+ EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (index >= gl::MAX_VERTEX_ATTRIBS)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ if (sampler != 0 && !context->isSampler(sampler))
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (context)
+ if (unit >= context->getCaps().maxCombinedTextureImageUnits)
{
- GLfloat vals[4] = { values[0], values[1], values[2], 1 };
- context->setVertexAttrib(index, vals);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
+
+ context->bindSampler(unit, sampler);
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)
+{
+ EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!gl::ValidateSamplerObjectParameter(context, pname))
+ {
+ return;
+ }
+
+ if (!gl::ValidateTexParamParameters(context, pname, param))
+ {
+ return;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->samplerParameteri(sampler, pname, param);
}
}
-void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+void __stdcall glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param)
{
- EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
+ glSamplerParameteri(sampler, pname, *param);
+}
- try
+void __stdcall glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
+{
+ EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (index >= gl::MAX_VERTEX_ATTRIBS)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ if (!gl::ValidateSamplerObjectParameter(context, pname))
+ {
+ return;
+ }
- if (context)
+ if (!gl::ValidateTexParamParameters(context, pname, static_cast<GLint>(param)))
{
- GLfloat vals[4] = { x, y, z, w };
- context->setVertexAttrib(index, vals);
+ return;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
+
+ context->samplerParameterf(sampler, pname, param);
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param)
+{
+ glSamplerParameterf(sampler, pname, *param);
+}
+
+void __stdcall glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params)
+{
+ EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!gl::ValidateSamplerObjectParameter(context, pname))
+ {
+ return;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ *params = context->getSamplerParameteri(sampler, pname);
}
}
-void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values)
+void __stdcall glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params)
{
- EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+ EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!gl::ValidateSamplerObjectParameter(context, pname))
+ {
+ return;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ *params = context->getSamplerParameterf(sampler, pname);
+ }
+}
- try
+void __stdcall glVertexAttribDivisor(GLuint index, GLuint divisor)
+{
+ EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
if (index >= gl::MAX_VERTEX_ATTRIBS)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ context->setVertexAttribDivisor(index, divisor);
+ }
+}
- if (context)
+void __stdcall glBindTransformFeedback(GLenum target, GLuint id)
+{
+ EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
{
- context->setVertexAttrib(index, values);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK:
+ {
+ // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1)
+ gl::TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1)
+ if (context->getTransformFeedback(id) == NULL)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->bindTransformFeedback(id);
+ }
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
+{
+ EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ context->deleteTransformFeedback(ids[i]);
+ }
}
}
-void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
+void __stdcall glGenTransformFeedbacks(GLsizei n, GLuint* ids)
{
- EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
+ EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (index >= gl::MAX_VERTEX_ATTRIBS)
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
{
- return gl::error(GL_INVALID_VALUE);
+ ids[i] = context->createTransformFeedback();
}
+ }
+}
- gl::Context *context = gl::getNonLostContext();
+GLboolean __stdcall glIsTransformFeedback(GLuint id)
+{
+ EVENT("(GLuint id = %u)", id);
- if (context)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
{
- context->setVertexAttribDivisor(index, divisor);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
}
+
+ return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE);
}
- catch(std::bad_alloc&)
+
+ return GL_FALSE;
+}
+
+void __stdcall glPauseTransformFeedback(void)
+{
+ EVENT("(void)");
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != NULL);
+
+ // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86)
+ if (!transformFeedback->isStarted() || transformFeedback->isPaused())
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ transformFeedback->pause();
}
}
-void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+void __stdcall glResumeTransformFeedback(void)
{
- EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
- "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
- index, size, type, normalized, stride, ptr);
+ EVENT("(void)");
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (index >= gl::MAX_VERTEX_ATTRIBS)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- if (size < 1 || size > 4)
+ gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != NULL);
+
+ // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86)
+ if (!transformFeedback->isStarted() || !transformFeedback->isPaused())
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- switch (type)
+ transformFeedback->resume();
+ }
+}
+
+void __stdcall glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)
+{
+ EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)",
+ program, bufSize, length, binaryFormat, binary);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
{
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_FIXED:
- case GL_FLOAT:
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- if (stride < 0)
+ // glGetProgramBinary
+ UNIMPLEMENTED();
+ }
+}
+
+void __stdcall glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length)
+{
+ EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
+ program, binaryFormat, binary, length);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ // glProgramBinary
+ UNIMPLEMENTED();
+ }
+}
- if (context)
+void __stdcall glProgramParameteri(GLuint program, GLenum pname, GLint value)
+{
+ EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)",
+ program, pname, value);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
{
- context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
+
+ // glProgramParameteri
+ UNIMPLEMENTED();
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments)
+{
+ EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)",
+ target, numAttachments, attachments);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments))
+ {
+ return;
+ }
+
+ gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ if (framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
+ {
+ framebuffer->invalidate(context->getCaps(), numAttachments, attachments);
+ }
}
}
-void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
+void __stdcall glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height)
{
- EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
+ EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, "
+ "GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+ target, numAttachments, attachments, x, y, width, height);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- if (width < 0 || height < 0)
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments))
+ {
+ return;
+ }
- if (context)
+ gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ if (framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
{
- context->setViewportParams(x, y, width, height);
+ framebuffer->invalidateSub(context->getCaps(), numAttachments, attachments, x, y, width, height);
}
}
- catch(std::bad_alloc&)
+}
+
+void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+ target, levels, internalformat, width, height);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1))
+ {
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ {
+ gl::Texture2D *texture2d = context->getTexture2D();
+ texture2d->storage(levels, internalformat, width, height);
+ }
+ break;
+
+ case GL_TEXTURE_CUBE_MAP:
+ {
+ gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
+ textureCube->storage(levels, internalformat, width);
+ }
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
}
}
-void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
+void __stdcall glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
{
- EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
- "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
- "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
- srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
+ "GLsizei height = %d, GLsizei depth = %d)",
+ target, levels, internalformat, width, height, depth);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- switch (filter)
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth))
+ {
+ return;
+ }
+
+ switch (target)
{
- case GL_NEAREST:
+ case GL_TEXTURE_3D:
+ {
+ gl::Texture3D *texture3d = context->getTexture3D();
+ texture3d->storage(levels, internalformat, width, height, depth);
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ gl::Texture2DArray *texture2darray = context->getTexture2DArray();
+ texture2darray->storage(levels, internalformat, width, height, depth);
+ }
break;
+
default:
- return gl::error(GL_INVALID_ENUM);
+ UNREACHABLE();
}
+ }
+}
+
+void __stdcall glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, "
+ "GLint* params = 0x%0.8p)",
+ target, internalformat, pname, bufSize, params);
- if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
+ const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (!formatCaps.renderable)
{
- ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
- return gl::error(GL_INVALID_OPERATION);
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
- gl::Context *context = gl::getNonLostContext();
+ if (target != GL_RENDERBUFFER)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- if (context)
+ if (bufSize < 0)
{
- if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_NUM_SAMPLE_COUNTS:
+ if (bufSize != 0)
{
- ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
- return gl::error(GL_INVALID_OPERATION);
+ *params = formatCaps.sampleCounts.size();
}
+ break;
- context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask);
+ case GL_SAMPLES:
+ std::copy_n(formatCaps.sampleCounts.rbegin(), std::min<size_t>(bufSize, formatCaps.sampleCounts.size()), params);
+ break;
+
+ default:
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
}
}
- catch(std::bad_alloc&)
+}
+
+// Extension functions
+
+void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
+ "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
+ "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
+ srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter,
+ true))
+ {
+ return;
+ }
+
+ context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
}
}
@@ -6878,54 +8312,40 @@ void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat
"GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
target, level, internalformat, width, height, depth, border, format, type, pixels);
- try
- {
- UNIMPLEMENTED(); // FIXME
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
+ UNIMPLEMENTED(); // FIXME
}
-void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length,
+void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length,
GLenum *binaryFormat, void *binary)
{
EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)",
program, bufSize, length, binaryFormat, binary);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Program *programObject = context->getProgram(program);
- if (context)
+ if (!programObject || !programObject->isLinked())
{
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject || !programObject->isLinked())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- if (!programBinary)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programBinary->save(binary, bufSize, length))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ if (!programBinary)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
- *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
+ if (!programBinary->save(binaryFormat, binary, bufSize, length))
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
}
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
}
void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat,
@@ -6934,30 +8354,24 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat,
EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)",
program, binaryFormat, binary, length);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
+ const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
+ if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == programBinaryFormats.end())
{
- if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
- {
- return gl::error(GL_INVALID_ENUM);
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
- context->setProgramBinary(program, binary, length);
+ gl::Program *programObject = context->getProgram(program);
+ if (!programObject)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY);
+
+ context->setProgramBinary(program, binaryFormat, binary, length);
}
}
@@ -6965,57 +8379,310 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
{
EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
- if (context)
+ if (context->getState().getDrawFramebuffer()->id() == 0)
{
- if (n < 0 || (unsigned int)n > context->getMaximumRenderTargets())
+ if (n != 1)
{
- return gl::error(GL_INVALID_VALUE);
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- if (context->getDrawFramebufferHandle() == 0)
+ if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
{
- if (n != 1)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
- else
+ }
+ else
+ {
+ for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
{
- for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
+ const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
+ if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment)
{
- const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
- if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
}
}
+ }
- gl::Framebuffer *framebuffer = context->getDrawFramebuffer();
+ gl::Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
- for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
- {
- framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]);
- }
+ for (unsigned int colorAttachment = 0; colorAttachment < static_cast<unsigned int>(n); colorAttachment++)
+ {
+ framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]);
+ }
- for (int colorAttachment = n; colorAttachment < (int)context->getMaximumRenderTargets(); colorAttachment++)
- {
- framebuffer->setDrawBufferState(colorAttachment, GL_NONE);
- }
+ for (unsigned int colorAttachment = n; colorAttachment < context->getCaps().maxDrawBuffers; colorAttachment++)
+ {
+ framebuffer->setDrawBufferState(colorAttachment, GL_NONE);
+ }
+ }
+}
+
+void __stdcall glGetBufferPointervOES(GLenum target, GLenum pname, void** params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!gl::ValidBufferTarget(context, target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (pname != GL_BUFFER_MAP_POINTER)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ gl::Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (!buffer || !buffer->isMapped())
+ {
+ *params = NULL;
+ }
+ else
+ {
+ *params = buffer->getMapPointer();
+ }
+ }
+}
+
+void * __stdcall glMapBufferOES(GLenum target, GLenum access)
+{
+ EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!gl::ValidBufferTarget(context, target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return NULL;
+ }
+
+ gl::Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (buffer == NULL)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ if (access != GL_WRITE_ONLY_OES)
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return NULL;
+ }
+
+ if (buffer->isMapped())
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ gl::Error error = buffer->mapRange(0, buffer->getSize(), GL_MAP_WRITE_BIT);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return NULL;
}
+
+ return buffer->getMapPointer();
}
- catch (std::bad_alloc&)
+
+ return NULL;
+}
+
+GLboolean __stdcall glUnmapBufferOES(GLenum target)
+{
+ EVENT("(GLenum target = 0x%X)", target);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- return gl::error(GL_OUT_OF_MEMORY);
+ if (!gl::ValidBufferTarget(context, target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return GL_FALSE;
+ }
+
+ gl::Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (buffer == NULL || !buffer->isMapped())
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
+ }
+
+ // TODO: detect if we had corruption. if so, throw an error and return false.
+
+ gl::Error error = buffer->unmap();
+ if (error.isError())
+ {
+ context->recordError(error);
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+{
+ EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
+ target, offset, length, access);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (!gl::ValidBufferTarget(context, target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return NULL;
+ }
+
+ if (offset < 0 || length < 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return NULL;
+ }
+
+ gl::Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (buffer == NULL)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ // Check for buffer overflow
+ size_t offsetSize = static_cast<size_t>(offset);
+ size_t lengthSize = static_cast<size_t>(length);
+
+ if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
+ offsetSize + lengthSize > static_cast<size_t>(buffer->getSize()))
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return NULL;
+ }
+
+ // 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->recordError(gl::Error(GL_INVALID_VALUE));
+ return NULL;
+ }
+
+ if (length == 0 || buffer->isMapped())
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ // Check for invalid bit combinations
+ if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ 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->recordError(gl::Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ gl::Error error = buffer->mapRange(offset, length, access);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return NULL;
+ }
+
+ return buffer->getMapPointer();
+ }
+
+ return NULL;
+}
+
+void __stdcall glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length)
+{
+ EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
+
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
+ {
+ if (offset < 0 || length < 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (!gl::ValidBufferTarget(context, target))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ gl::Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (buffer == NULL)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // Check for buffer overflow
+ size_t offsetSize = static_cast<size_t>(offset);
+ size_t lengthSize = static_cast<size_t>(length);
+
+ if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
+ offsetSize + lengthSize > static_cast<size_t>(buffer->getMapLength()))
+ {
+ context->recordError(gl::Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ // We do not currently support a non-trivial implementation of FlushMappedBufferRange
}
}
@@ -7057,7 +8724,12 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *
{"glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawArraysInstancedANGLE},
{"glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawElementsInstancedANGLE},
{"glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glGetProgramBinaryOES},
- {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES}, };
+ {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES},
+ {"glGetBufferPointervOES", (__eglMustCastToProperFunctionPointerType)glGetBufferPointervOES},
+ {"glMapBufferOES", (__eglMustCastToProperFunctionPointerType)glMapBufferOES},
+ {"glUnmapBufferOES", (__eglMustCastToProperFunctionPointerType)glUnmapBufferOES},
+ {"glMapBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glMapBufferRangeEXT},
+ {"glFlushMappedBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glFlushMappedBufferRangeEXT}, };
for (unsigned int ext = 0; ext < ArraySize(glExtensions); ext++)
{
@@ -7077,28 +8749,18 @@ bool __stdcall glBindTexImage(egl::Surface *surface)
EVENT("(egl::Surface* surface = 0x%0.8p)",
surface);
- try
+ gl::Context *context = gl::getNonLostContext();
+ if (context)
{
- gl::Context *context = gl::getNonLostContext();
+ gl::Texture2D *textureObject = context->getTexture2D();
+ ASSERT(textureObject != NULL);
- if (context)
+ if (textureObject->isImmutable())
{
- gl::Texture2D *textureObject = context->getTexture2D();
-
- if (textureObject->isImmutable())
- {
- return false;
- }
-
- if (textureObject)
- {
- textureObject->bindTexImage(surface);
- }
+ return false;
}
- }
- catch(std::bad_alloc&)
- {
- return gl::error(GL_OUT_OF_MEMORY, false);
+
+ textureObject->bindTexImage(surface);
}
return true;
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
index b8320c8f25..33557eb1c9 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
@@ -173,6 +173,117 @@ EXPORTS
glProgramBinaryOES @175
glGetProgramBinaryOES @176
glDrawBuffersEXT @179
+ glMapBufferOES @285
+ glUnmapBufferOES @286
+ glGetBufferPointervOES @287
+ glMapBufferRangeEXT @288
+ glFlushMappedBufferRangeEXT @289
+
+ ; GLES 3.0 Functions
+ glReadBuffer @180
+ glDrawRangeElements @181
+ glTexImage3D @182
+ glTexSubImage3D @183
+ glCopyTexSubImage3D @184
+ glCompressedTexImage3D @185
+ glCompressedTexSubImage3D @186
+ glGenQueries @187
+ glDeleteQueries @188
+ glIsQuery @189
+ glBeginQuery @190
+ glEndQuery @191
+ glGetQueryiv @192
+ glGetQueryObjectuiv @193
+ glUnmapBuffer @194
+ glGetBufferPointerv @195
+ glDrawBuffers @196
+ glUniformMatrix2x3fv @197
+ glUniformMatrix3x2fv @198
+ glUniformMatrix2x4fv @199
+ glUniformMatrix4x2fv @200
+ glUniformMatrix3x4fv @201
+ glUniformMatrix4x3fv @202
+ glBlitFramebuffer @203
+ glRenderbufferStorageMultisample @204
+ glFramebufferTextureLayer @205
+ glMapBufferRange @206
+ glFlushMappedBufferRange @207
+ glBindVertexArray @208
+ glDeleteVertexArrays @209
+ glGenVertexArrays @210
+ glIsVertexArray @211
+ glGetIntegeri_v @212
+ glBeginTransformFeedback @213
+ glEndTransformFeedback @214
+ glBindBufferRange @215
+ glBindBufferBase @216
+ glTransformFeedbackVaryings @217
+ glGetTransformFeedbackVarying @218
+ glVertexAttribIPointer @219
+ glGetVertexAttribIiv @220
+ glGetVertexAttribIuiv @221
+ glVertexAttribI4i @222
+ glVertexAttribI4ui @223
+ glVertexAttribI4iv @224
+ glVertexAttribI4uiv @225
+ glGetUniformuiv @226
+ glGetFragDataLocation @227
+ glUniform1ui @228
+ glUniform2ui @229
+ glUniform3ui @230
+ glUniform4ui @231
+ glUniform1uiv @232
+ glUniform2uiv @233
+ glUniform3uiv @234
+ glUniform4uiv @235
+ glClearBufferiv @236
+ glClearBufferuiv @237
+ glClearBufferfv @238
+ glClearBufferfi @239
+ glGetStringi @240
+ glCopyBufferSubData @241
+ glGetUniformIndices @242
+ glGetActiveUniformsiv @243
+ glGetUniformBlockIndex @244
+ glGetActiveUniformBlockiv @245
+ glGetActiveUniformBlockName @246
+ glUniformBlockBinding @247
+ glDrawArraysInstanced @248
+ glDrawElementsInstanced @249
+ glFenceSync @250
+ glIsSync @251
+ glDeleteSync @252
+ glClientWaitSync @253
+ glWaitSync @254
+ glGetInteger64v @255
+ glGetSynciv @256
+ glGetInteger64i_v @257
+ glGetBufferParameteri64v @258
+ glGenSamplers @259
+ glDeleteSamplers @260
+ glIsSampler @261
+ glBindSampler @262
+ glSamplerParameteri @263
+ glSamplerParameteriv @264
+ glSamplerParameterf @265
+ glSamplerParameterfv @266
+ glGetSamplerParameteriv @267
+ glGetSamplerParameterfv @268
+ glVertexAttribDivisor @269
+ glBindTransformFeedback @270
+ glDeleteTransformFeedbacks @271
+ glGenTransformFeedbacks @272
+ glIsTransformFeedback @273
+ glPauseTransformFeedback @274
+ glResumeTransformFeedback @275
+ glGetProgramBinary @276
+ glProgramBinary @277
+ glProgramParameteri @278
+ glInvalidateFramebuffer @279
+ glInvalidateSubFramebuffer @280
+ glTexStorage2D @281
+ glTexStorage3D @282
+ glGetInternalformativ @283
; EGL dependencies
glCreateContext @144 NONAME
@@ -183,6 +294,3 @@ EXPORTS
glBindTexImage @158 NONAME
glCreateRenderer @177 NONAME
glDestroyRenderer @178 NONAME
-
- ; Setting up TRACE macro callbacks
- SetTraceFunctionPointers @180
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
index ef44917d71..18ffcf6a0d 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
@@ -1,188 +1,296 @@
LIBRARY libGLESv2
EXPORTS
- glActiveTexture@4 @1
- glAttachShader@8 @2
- glBindAttribLocation@12 @3
- glBindBuffer@8 @4
- glBindFramebuffer@8 @5
- glBindRenderbuffer@8 @6
- glBindTexture@8 @7
- glBlendColor@16 @8
- glBlendEquation@4 @9
- glBlendEquationSeparate@8 @10
- glBlendFunc@8 @11
- glBlendFuncSeparate@16 @12
- glBufferData@16 @13
- glBufferSubData@16 @14
- glCheckFramebufferStatus@4 @15
- glClear@4 @16
- glClearColor@16 @17
- glClearDepthf@4 @18
- glClearStencil@4 @19
- glColorMask@16 @20
- glCompileShader@4 @21
- glCompressedTexImage2D@32 @22
- glCompressedTexSubImage2D@36 @23
- glCopyTexImage2D@32 @24
- glCopyTexSubImage2D@32 @25
- glCreateProgram@0 @26
- glCreateShader@4 @27
- glCullFace@4 @28
- glDeleteBuffers@8 @29
- glDeleteFramebuffers@8 @30
- glDeleteProgram@4 @32
- glDeleteRenderbuffers@8 @33
- glDeleteShader@4 @34
- glDeleteTextures@8 @31
- glDepthFunc@4 @36
- glDepthMask@4 @37
- glDepthRangef@8 @38
- glDetachShader@8 @35
- glDisable@4 @39
- glDisableVertexAttribArray@4 @40
- glDrawArrays@12 @41
- glDrawElements@16 @42
- glEnable@4 @43
- glEnableVertexAttribArray@4 @44
- glFinish@0 @45
- glFlush@0 @46
- glFramebufferRenderbuffer@16 @47
- glFramebufferTexture2D@20 @48
- glFrontFace@4 @49
- glGenBuffers@8 @50
- glGenFramebuffers@8 @52
- glGenRenderbuffers@8 @53
- glGenTextures@8 @54
- glGenerateMipmap@4 @51
- glGetActiveAttrib@28 @55
- glGetActiveUniform@28 @56
- glGetAttachedShaders@16 @57
- glGetAttribLocation@8 @58
- glGetBooleanv@8 @59
- glGetBufferParameteriv@12 @60
- glGetError@0 @61
- glGetFloatv@8 @62
- glGetFramebufferAttachmentParameteriv@16 @63
- glGetIntegerv@8 @64
- glGetProgramInfoLog@16 @66
- glGetProgramiv@12 @65
- glGetRenderbufferParameteriv@12 @67
- glGetShaderInfoLog@16 @69
- glGetShaderPrecisionFormat@16 @70
- glGetShaderSource@16 @71
- glGetShaderiv@12 @68
- glGetString@4 @72
- glGetTexParameterfv@12 @73
- glGetTexParameteriv@12 @74
- glGetUniformLocation@8 @77
- glGetUniformfv@12 @75
- glGetUniformiv@12 @76
- glGetVertexAttribPointerv@12 @80
- glGetVertexAttribfv@12 @78
- glGetVertexAttribiv@12 @79
- glHint@8 @81
- glIsBuffer@4 @82
- glIsEnabled@4 @83
- glIsFramebuffer@4 @84
- glIsProgram@4 @85
- glIsRenderbuffer@4 @86
- glIsShader@4 @87
- glIsTexture@4 @88
- glLineWidth@4 @89
- glLinkProgram@4 @90
- glPixelStorei@8 @91
- glPolygonOffset@8 @92
- glReadPixels@28 @93
- glReleaseShaderCompiler@0 @94
- glRenderbufferStorage@16 @95
- glSampleCoverage@8 @96
- glScissor@16 @97
- glShaderBinary@20 @98
- glShaderSource@16 @99
- glStencilFunc@12 @100
- glStencilFuncSeparate@16 @101
- glStencilMask@4 @102
- glStencilMaskSeparate@8 @103
- glStencilOp@12 @104
- glStencilOpSeparate@16 @105
- glTexImage2D@36 @106
- glTexParameterf@12 @107
- glTexParameterfv@12 @108
- glTexParameteri@12 @109
- glTexParameteriv@12 @110
- glTexSubImage2D@36 @111
- glUniform1f@8 @112
- glUniform1fv@12 @113
- glUniform1i@8 @114
- glUniform1iv@12 @115
- glUniform2f@12 @116
- glUniform2fv@12 @117
- glUniform2i@12 @118
- glUniform2iv@12 @119
- glUniform3f@16 @120
- glUniform3fv@12 @121
- glUniform3i@16 @122
- glUniform3iv@12 @123
- glUniform4f@20 @124
- glUniform4fv@12 @125
- glUniform4i@20 @126
- glUniform4iv@12 @127
- glUniformMatrix2fv@16 @128
- glUniformMatrix3fv@16 @129
- glUniformMatrix4fv@16 @130
- glUseProgram@4 @131
- glValidateProgram@4 @132
- glVertexAttrib1f@8 @133
- glVertexAttrib1fv@8 @134
- glVertexAttrib2f@12 @135
- glVertexAttrib2fv@8 @136
- glVertexAttrib3f@16 @137
- glVertexAttrib3fv@8 @138
- glVertexAttrib4f@20 @139
- glVertexAttrib4fv@8 @140
- glVertexAttribPointer@24 @141
- glViewport@16 @142
+ glActiveTexture@4 @1
+ glAttachShader@8 @2
+ glBindAttribLocation@12 @3
+ glBindBuffer@8 @4
+ glBindFramebuffer@8 @5
+ glBindRenderbuffer@8 @6
+ glBindTexture@8 @7
+ glBlendColor@16 @8
+ glBlendEquation@4 @9
+ glBlendEquationSeparate@8 @10
+ glBlendFunc@8 @11
+ glBlendFuncSeparate@16 @12
+ glBufferData@16 @13
+ glBufferSubData@16 @14
+ glCheckFramebufferStatus@4 @15
+ glClear@4 @16
+ glClearColor@16 @17
+ glClearDepthf@4 @18
+ glClearStencil@4 @19
+ glColorMask@16 @20
+ glCompileShader@4 @21
+ glCompressedTexImage2D@32 @22
+ glCompressedTexSubImage2D@36 @23
+ glCopyTexImage2D@32 @24
+ glCopyTexSubImage2D@32 @25
+ glCreateProgram@0 @26
+ glCreateShader@4 @27
+ glCullFace@4 @28
+ glDeleteBuffers@8 @29
+ glDeleteFramebuffers@8 @30
+ glDeleteProgram@4 @32
+ glDeleteRenderbuffers@8 @33
+ glDeleteShader@4 @34
+ glDeleteTextures@8 @31
+ glDepthFunc@4 @36
+ glDepthMask@4 @37
+ glDepthRangef@8 @38
+ glDetachShader@8 @35
+ glDisable@4 @39
+ glDisableVertexAttribArray@4 @40
+ glDrawArrays@12 @41
+ glDrawElements@16 @42
+ glEnable@4 @43
+ glEnableVertexAttribArray@4 @44
+ glFinish@0 @45
+ glFlush@0 @46
+ glFramebufferRenderbuffer@16 @47
+ glFramebufferTexture2D@20 @48
+ glFrontFace@4 @49
+ glGenBuffers@8 @50
+ glGenFramebuffers@8 @52
+ glGenRenderbuffers@8 @53
+ glGenTextures@8 @54
+ glGenerateMipmap@4 @51
+ glGetActiveAttrib@28 @55
+ glGetActiveUniform@28 @56
+ glGetAttachedShaders@16 @57
+ glGetAttribLocation@8 @58
+ glGetBooleanv@8 @59
+ glGetBufferParameteriv@12 @60
+ glGetError@0 @61
+ glGetFloatv@8 @62
+ glGetFramebufferAttachmentParameteriv@16 @63
+ glGetIntegerv@8 @64
+ glGetProgramInfoLog@16 @66
+ glGetProgramiv@12 @65
+ glGetRenderbufferParameteriv@12 @67
+ glGetShaderInfoLog@16 @69
+ glGetShaderPrecisionFormat@16 @70
+ glGetShaderSource@16 @71
+ glGetShaderiv@12 @68
+ glGetString@4 @72
+ glGetTexParameterfv@12 @73
+ glGetTexParameteriv@12 @74
+ glGetUniformLocation@8 @77
+ glGetUniformfv@12 @75
+ glGetUniformiv@12 @76
+ glGetVertexAttribPointerv@12 @80
+ glGetVertexAttribfv@12 @78
+ glGetVertexAttribiv@12 @79
+ glHint@8 @81
+ glIsBuffer@4 @82
+ glIsEnabled@4 @83
+ glIsFramebuffer@4 @84
+ glIsProgram@4 @85
+ glIsRenderbuffer@4 @86
+ glIsShader@4 @87
+ glIsTexture@4 @88
+ glLineWidth@4 @89
+ glLinkProgram@4 @90
+ glPixelStorei@8 @91
+ glPolygonOffset@8 @92
+ glReadPixels@28 @93
+ glReleaseShaderCompiler@0 @94
+ glRenderbufferStorage@16 @95
+ glSampleCoverage@8 @96
+ glScissor@16 @97
+ glShaderBinary@20 @98
+ glShaderSource@16 @99
+ glStencilFunc@12 @100
+ glStencilFuncSeparate@16 @101
+ glStencilMask@4 @102
+ glStencilMaskSeparate@8 @103
+ glStencilOp@12 @104
+ glStencilOpSeparate@16 @105
+ glTexImage2D@36 @106
+ glTexParameterf@12 @107
+ glTexParameterfv@12 @108
+ glTexParameteri@12 @109
+ glTexParameteriv@12 @110
+ glTexSubImage2D@36 @111
+ glUniform1f@8 @112
+ glUniform1fv@12 @113
+ glUniform1i@8 @114
+ glUniform1iv@12 @115
+ glUniform2f@12 @116
+ glUniform2fv@12 @117
+ glUniform2i@12 @118
+ glUniform2iv@12 @119
+ glUniform3f@16 @120
+ glUniform3fv@12 @121
+ glUniform3i@16 @122
+ glUniform3iv@12 @123
+ glUniform4f@20 @124
+ glUniform4fv@12 @125
+ glUniform4i@20 @126
+ glUniform4iv@12 @127
+ glUniformMatrix2fv@16 @128
+ glUniformMatrix3fv@16 @129
+ glUniformMatrix4fv@16 @130
+ glUseProgram@4 @131
+ glValidateProgram@4 @132
+ glVertexAttrib1f@8 @133
+ glVertexAttrib1fv@8 @134
+ glVertexAttrib2f@12 @135
+ glVertexAttrib2fv@8 @136
+ glVertexAttrib3f@16 @137
+ glVertexAttrib3fv@8 @138
+ glVertexAttrib4f@20 @139
+ glVertexAttrib4fv@8 @140
+ glVertexAttribPointer@24 @141
+ glViewport@16 @142
- ; Extensions
- glTexImage3DOES@40 @143
- glBlitFramebufferANGLE@40 @149
- glRenderbufferStorageMultisampleANGLE@20 @150
- glDeleteFencesNV@8 @151
- glFinishFenceNV@4 @152
- glGenFencesNV@8 @153
- glGetFenceivNV@12 @154
- glIsFenceNV@4 @155
- glSetFenceNV@8 @156
- glTestFenceNV@4 @157
- glGetTranslatedShaderSourceANGLE@16 @159
- glTexStorage2DEXT@20 @160
- glGetGraphicsResetStatusEXT@0 @161
- glReadnPixelsEXT@32 @162
- glGetnUniformfvEXT@16 @163
- glGetnUniformivEXT@16 @164
- glGenQueriesEXT@8 @165
- glDeleteQueriesEXT@8 @166
- glIsQueryEXT@4 @167
- glBeginQueryEXT@8 @168
- glEndQueryEXT@4 @169
- glGetQueryivEXT@12 @170
- glGetQueryObjectuivEXT@12 @171
- glVertexAttribDivisorANGLE@8 @172
- glDrawArraysInstancedANGLE@16 @173
- glDrawElementsInstancedANGLE@20 @174
- glProgramBinaryOES@16 @175
- glGetProgramBinaryOES@20 @176
- glDrawBuffersEXT@8 @179
+ ; Extensions
+ glTexImage3DOES@40 @143
+ glBlitFramebufferANGLE@40 @149
+ glRenderbufferStorageMultisampleANGLE@20 @150
+ glDeleteFencesNV@8 @151
+ glFinishFenceNV@4 @152
+ glGenFencesNV@8 @153
+ glGetFenceivNV@12 @154
+ glIsFenceNV@4 @155
+ glSetFenceNV@8 @156
+ glTestFenceNV@4 @157
+ glGetTranslatedShaderSourceANGLE@16 @159
+ glTexStorage2DEXT@20 @160
+ glGetGraphicsResetStatusEXT@0 @161
+ glReadnPixelsEXT@32 @162
+ glGetnUniformfvEXT@16 @163
+ glGetnUniformivEXT@16 @164
+ glGenQueriesEXT@8 @165
+ glDeleteQueriesEXT@8 @166
+ glIsQueryEXT@4 @167
+ glBeginQueryEXT@8 @168
+ glEndQueryEXT@4 @169
+ glGetQueryivEXT@12 @170
+ glGetQueryObjectuivEXT@12 @171
+ glVertexAttribDivisorANGLE@8 @172
+ glDrawArraysInstancedANGLE@16 @173
+ glDrawElementsInstancedANGLE@20 @174
+ glProgramBinaryOES@16 @175
+ glGetProgramBinaryOES@20 @176
+ glDrawBuffersEXT@8 @179
+ glMapBufferOES@8 @285
+ glUnmapBufferOES@4 @286
+ glGetBufferPointervOES@12 @287
+ glMapBufferRangeEXT@16 @288
+ glFlushMappedBufferRangeEXT@12 @289
- ; EGL dependencies
- glCreateContext @144 NONAME
- glDestroyContext @145 NONAME
- glMakeCurrent @146 NONAME
- glGetCurrentContext @147 NONAME
- glGetProcAddress@4 @148 NONAME
- glBindTexImage@4 @158 NONAME
- glCreateRenderer @177 NONAME
- glDestroyRenderer @178 NONAME
+ ; GLES 3.0 Functions
+ glReadBuffer@4 @180
+ glDrawRangeElements@24 @181
+ glTexImage3D@40 @182
+ glTexSubImage3D@44 @183
+ glCopyTexSubImage3D@36 @184
+ glCompressedTexImage3D@36 @185
+ glCompressedTexSubImage3D@44 @186
+ glGenQueries@8 @187
+ glDeleteQueries@8 @188
+ glIsQuery@4 @189
+ glBeginQuery@8 @190
+ glEndQuery@4 @191
+ glGetQueryiv@12 @192
+ glGetQueryObjectuiv@12 @193
+ glUnmapBuffer@4 @194
+ glGetBufferPointerv@12 @195
+ glDrawBuffers@8 @196
+ glUniformMatrix2x3fv@16 @197
+ glUniformMatrix3x2fv@16 @198
+ glUniformMatrix2x4fv@16 @199
+ glUniformMatrix4x2fv@16 @200
+ glUniformMatrix3x4fv@16 @201
+ glUniformMatrix4x3fv@16 @202
+ glBlitFramebuffer@40 @203
+ glRenderbufferStorageMultisample@20 @204
+ glFramebufferTextureLayer@20 @205
+ glMapBufferRange@16 @206
+ glFlushMappedBufferRange@12 @207
+ glBindVertexArray@4 @208
+ glDeleteVertexArrays@8 @209
+ glGenVertexArrays@8 @210
+ glIsVertexArray@4 @211
+ glGetIntegeri_v@12 @212
+ glBeginTransformFeedback@4 @213
+ glEndTransformFeedback@0 @214
+ glBindBufferRange@20 @215
+ glBindBufferBase@12 @216
+ glTransformFeedbackVaryings@16 @217
+ glGetTransformFeedbackVarying@28 @218
+ glVertexAttribIPointer@20 @219
+ glGetVertexAttribIiv@12 @220
+ glGetVertexAttribIuiv@12 @221
+ glVertexAttribI4i@20 @222
+ glVertexAttribI4ui@20 @223
+ glVertexAttribI4iv@8 @224
+ glVertexAttribI4uiv@8 @225
+ glGetUniformuiv@12 @226
+ glGetFragDataLocation@8 @227
+ glUniform1ui@8 @228
+ glUniform2ui@12 @229
+ glUniform3ui@16 @230
+ glUniform4ui@20 @231
+ glUniform1uiv@12 @232
+ glUniform2uiv@12 @233
+ glUniform3uiv@12 @234
+ glUniform4uiv@12 @235
+ glClearBufferiv@12 @236
+ glClearBufferuiv@12 @237
+ glClearBufferfv@12 @238
+ glClearBufferfi@16 @239
+ glGetStringi@8 @240
+ glCopyBufferSubData@20 @241
+ glGetUniformIndices@16 @242
+ glGetActiveUniformsiv@20 @243
+ glGetUniformBlockIndex@8 @244
+ glGetActiveUniformBlockiv@16 @245
+ glGetActiveUniformBlockName@20 @246
+ glUniformBlockBinding@12 @247
+ glDrawArraysInstanced@16 @248
+ glDrawElementsInstanced@20 @249
+ glFenceSync@8 @250
+ glIsSync@4 @251
+ glDeleteSync@4 @252
+ glClientWaitSync@16 @253
+ glWaitSync@16 @254
+ glGetInteger64v@8 @255
+ glGetSynciv@20 @256
+ glGetInteger64i_v@12 @257
+ glGetBufferParameteri64v@12 @258
+ glGenSamplers@8 @259
+ glDeleteSamplers@8 @260
+ glIsSampler@4 @261
+ glBindSampler@8 @262
+ glSamplerParameteri@12 @263
+ glSamplerParameteriv@12 @264
+ glSamplerParameterf@12 @265
+ glSamplerParameterfv@12 @266
+ glGetSamplerParameteriv@12 @267
+ glGetSamplerParameterfv@12 @268
+ glVertexAttribDivisor@8 @269
+ glBindTransformFeedback@8 @270
+ glDeleteTransformFeedbacks@8 @271
+ glGenTransformFeedbacks@8 @272
+ glIsTransformFeedback@4 @273
+ glPauseTransformFeedback@0 @274
+ glResumeTransformFeedback@0 @275
+ glGetProgramBinary@20 @276
+ glProgramBinary@16 @277
+ glProgramParameteri@12 @278
+ glInvalidateFramebuffer@12 @279
+ glInvalidateSubFramebuffer@28 @280
+ glTexStorage2D@20 @281
+ glTexStorage3D@24 @282
+ glGetInternalformativ@20 @283
- ; Setting up TRACE macro callbacks
- SetTraceFunctionPointers@8 @180
+ ; EGL dependencies
+ glCreateContext @144 NONAME
+ glDestroyContext @145 NONAME
+ glMakeCurrent @146 NONAME
+ glGetCurrentContext @147 NONAME
+ glGetProcAddress@4 @148 NONAME
+ glBindTexImage@4 @158 NONAME
+ glCreateRenderer @177 NONAME
+ glDestroyRenderer @178 NONAME
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
index 3dd5683b5f..120371e013 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
@@ -173,6 +173,117 @@ EXPORTS
glProgramBinaryOES @175
glGetProgramBinaryOES @176
glDrawBuffersEXT @179
+ glMapBufferOES @285
+ glUnmapBufferOES @286
+ glGetBufferPointervOES @287
+ glMapBufferRangeEXT @288
+ glFlushMappedBufferRangeEXT @289
+
+ ; GLES 3.0 Functions
+ glReadBuffer @180
+ glDrawRangeElements @181
+ glTexImage3D @182
+ glTexSubImage3D @183
+ glCopyTexSubImage3D @184
+ glCompressedTexImage3D @185
+ glCompressedTexSubImage3D @186
+ glGenQueries @187
+ glDeleteQueries @188
+ glIsQuery @189
+ glBeginQuery @190
+ glEndQuery @191
+ glGetQueryiv @192
+ glGetQueryObjectuiv @193
+ glUnmapBuffer @194
+ glGetBufferPointerv @195
+ glDrawBuffers @196
+ glUniformMatrix2x3fv @197
+ glUniformMatrix3x2fv @198
+ glUniformMatrix2x4fv @199
+ glUniformMatrix4x2fv @200
+ glUniformMatrix3x4fv @201
+ glUniformMatrix4x3fv @202
+ glBlitFramebuffer @203
+ glRenderbufferStorageMultisample @204
+ glFramebufferTextureLayer @205
+ glMapBufferRange @206
+ glFlushMappedBufferRange @207
+ glBindVertexArray @208
+ glDeleteVertexArrays @209
+ glGenVertexArrays @210
+ glIsVertexArray @211
+ glGetIntegeri_v @212
+ glBeginTransformFeedback @213
+ glEndTransformFeedback @214
+ glBindBufferRange @215
+ glBindBufferBase @216
+ glTransformFeedbackVaryings @217
+ glGetTransformFeedbackVarying @218
+ glVertexAttribIPointer @219
+ glGetVertexAttribIiv @220
+ glGetVertexAttribIuiv @221
+ glVertexAttribI4i @222
+ glVertexAttribI4ui @223
+ glVertexAttribI4iv @224
+ glVertexAttribI4uiv @225
+ glGetUniformuiv @226
+ glGetFragDataLocation @227
+ glUniform1ui @228
+ glUniform2ui @229
+ glUniform3ui @230
+ glUniform4ui @231
+ glUniform1uiv @232
+ glUniform2uiv @233
+ glUniform3uiv @234
+ glUniform4uiv @235
+ glClearBufferiv @236
+ glClearBufferuiv @237
+ glClearBufferfv @238
+ glClearBufferfi @239
+ glGetStringi @240
+ glCopyBufferSubData @241
+ glGetUniformIndices @242
+ glGetActiveUniformsiv @243
+ glGetUniformBlockIndex @244
+ glGetActiveUniformBlockiv @245
+ glGetActiveUniformBlockName @246
+ glUniformBlockBinding @247
+ glDrawArraysInstanced @248
+ glDrawElementsInstanced @249
+ glFenceSync @250
+ glIsSync @251
+ glDeleteSync @252
+ glClientWaitSync @253
+ glWaitSync @254
+ glGetInteger64v @255
+ glGetSynciv @256
+ glGetInteger64i_v @257
+ glGetBufferParameteri64v @258
+ glGenSamplers @259
+ glDeleteSamplers @260
+ glIsSampler @261
+ glBindSampler @262
+ glSamplerParameteri @263
+ glSamplerParameteriv @264
+ glSamplerParameterf @265
+ glSamplerParameterfv @266
+ glGetSamplerParameteriv @267
+ glGetSamplerParameterfv @268
+ glVertexAttribDivisor @269
+ glBindTransformFeedback @270
+ glDeleteTransformFeedbacks @271
+ glGenTransformFeedbacks @272
+ glIsTransformFeedback @273
+ glPauseTransformFeedback @274
+ glResumeTransformFeedback @275
+ glGetProgramBinary @276
+ glProgramBinary @277
+ glProgramParameteri @278
+ glInvalidateFramebuffer @279
+ glInvalidateSubFramebuffer @280
+ glTexStorage2D @281
+ glTexStorage3D @282
+ glGetInternalformativ @283
; EGL dependencies
glCreateContext @144 NONAME
@@ -183,6 +294,3 @@ EXPORTS
glBindTexImage @158 NONAME
glCreateRenderer @177 NONAME
glDestroyRenderer @178 NONAME
-
- ; Setting up TRACE macro callbacks
- SetTraceFunctionPointers @180
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
index 6c8d3ed630..8c1306a703 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
@@ -1,188 +1,296 @@
LIBRARY libGLESv2d
EXPORTS
- glActiveTexture@4 @1
- glAttachShader@8 @2
- glBindAttribLocation@12 @3
- glBindBuffer@8 @4
- glBindFramebuffer@8 @5
- glBindRenderbuffer@8 @6
- glBindTexture@8 @7
- glBlendColor@16 @8
- glBlendEquation@4 @9
- glBlendEquationSeparate@8 @10
- glBlendFunc@8 @11
- glBlendFuncSeparate@16 @12
- glBufferData@16 @13
- glBufferSubData@16 @14
- glCheckFramebufferStatus@4 @15
- glClear@4 @16
- glClearColor@16 @17
- glClearDepthf@4 @18
- glClearStencil@4 @19
- glColorMask@16 @20
- glCompileShader@4 @21
- glCompressedTexImage2D@32 @22
- glCompressedTexSubImage2D@36 @23
- glCopyTexImage2D@32 @24
- glCopyTexSubImage2D@32 @25
- glCreateProgram@0 @26
- glCreateShader@4 @27
- glCullFace@4 @28
- glDeleteBuffers@8 @29
- glDeleteFramebuffers@8 @30
- glDeleteProgram@4 @32
- glDeleteRenderbuffers@8 @33
- glDeleteShader@4 @34
- glDeleteTextures@8 @31
- glDepthFunc@4 @36
- glDepthMask@4 @37
- glDepthRangef@8 @38
- glDetachShader@8 @35
- glDisable@4 @39
- glDisableVertexAttribArray@4 @40
- glDrawArrays@12 @41
- glDrawElements@16 @42
- glEnable@4 @43
- glEnableVertexAttribArray@4 @44
- glFinish@0 @45
- glFlush@0 @46
- glFramebufferRenderbuffer@16 @47
- glFramebufferTexture2D@20 @48
- glFrontFace@4 @49
- glGenBuffers@8 @50
- glGenFramebuffers@8 @52
- glGenRenderbuffers@8 @53
- glGenTextures@8 @54
- glGenerateMipmap@4 @51
- glGetActiveAttrib@28 @55
- glGetActiveUniform@28 @56
- glGetAttachedShaders@16 @57
- glGetAttribLocation@8 @58
- glGetBooleanv@8 @59
- glGetBufferParameteriv@12 @60
- glGetError@0 @61
- glGetFloatv@8 @62
- glGetFramebufferAttachmentParameteriv@16 @63
- glGetIntegerv@8 @64
- glGetProgramInfoLog@16 @66
- glGetProgramiv@12 @65
- glGetRenderbufferParameteriv@12 @67
- glGetShaderInfoLog@16 @69
- glGetShaderPrecisionFormat@16 @70
- glGetShaderSource@16 @71
- glGetShaderiv@12 @68
- glGetString@4 @72
- glGetTexParameterfv@12 @73
- glGetTexParameteriv@12 @74
- glGetUniformLocation@8 @77
- glGetUniformfv@12 @75
- glGetUniformiv@12 @76
- glGetVertexAttribPointerv@12 @80
- glGetVertexAttribfv@12 @78
- glGetVertexAttribiv@12 @79
- glHint@8 @81
- glIsBuffer@4 @82
- glIsEnabled@4 @83
- glIsFramebuffer@4 @84
- glIsProgram@4 @85
- glIsRenderbuffer@4 @86
- glIsShader@4 @87
- glIsTexture@4 @88
- glLineWidth@4 @89
- glLinkProgram@4 @90
- glPixelStorei@8 @91
- glPolygonOffset@8 @92
- glReadPixels@28 @93
- glReleaseShaderCompiler@0 @94
- glRenderbufferStorage@16 @95
- glSampleCoverage@8 @96
- glScissor@16 @97
- glShaderBinary@20 @98
- glShaderSource@16 @99
- glStencilFunc@12 @100
- glStencilFuncSeparate@16 @101
- glStencilMask@4 @102
- glStencilMaskSeparate@8 @103
- glStencilOp@12 @104
- glStencilOpSeparate@16 @105
- glTexImage2D@36 @106
- glTexParameterf@12 @107
- glTexParameterfv@12 @108
- glTexParameteri@12 @109
- glTexParameteriv@12 @110
- glTexSubImage2D@36 @111
- glUniform1f@8 @112
- glUniform1fv@12 @113
- glUniform1i@8 @114
- glUniform1iv@12 @115
- glUniform2f@12 @116
- glUniform2fv@12 @117
- glUniform2i@12 @118
- glUniform2iv@12 @119
- glUniform3f@16 @120
- glUniform3fv@12 @121
- glUniform3i@16 @122
- glUniform3iv@12 @123
- glUniform4f@20 @124
- glUniform4fv@12 @125
- glUniform4i@20 @126
- glUniform4iv@12 @127
- glUniformMatrix2fv@16 @128
- glUniformMatrix3fv@16 @129
- glUniformMatrix4fv@16 @130
- glUseProgram@4 @131
- glValidateProgram@4 @132
- glVertexAttrib1f@8 @133
- glVertexAttrib1fv@8 @134
- glVertexAttrib2f@12 @135
- glVertexAttrib2fv@8 @136
- glVertexAttrib3f@16 @137
- glVertexAttrib3fv@8 @138
- glVertexAttrib4f@20 @139
- glVertexAttrib4fv@8 @140
- glVertexAttribPointer@24 @141
- glViewport@16 @142
+ glActiveTexture@4 @1
+ glAttachShader@8 @2
+ glBindAttribLocation@12 @3
+ glBindBuffer@8 @4
+ glBindFramebuffer@8 @5
+ glBindRenderbuffer@8 @6
+ glBindTexture@8 @7
+ glBlendColor@16 @8
+ glBlendEquation@4 @9
+ glBlendEquationSeparate@8 @10
+ glBlendFunc@8 @11
+ glBlendFuncSeparate@16 @12
+ glBufferData@16 @13
+ glBufferSubData@16 @14
+ glCheckFramebufferStatus@4 @15
+ glClear@4 @16
+ glClearColor@16 @17
+ glClearDepthf@4 @18
+ glClearStencil@4 @19
+ glColorMask@16 @20
+ glCompileShader@4 @21
+ glCompressedTexImage2D@32 @22
+ glCompressedTexSubImage2D@36 @23
+ glCopyTexImage2D@32 @24
+ glCopyTexSubImage2D@32 @25
+ glCreateProgram@0 @26
+ glCreateShader@4 @27
+ glCullFace@4 @28
+ glDeleteBuffers@8 @29
+ glDeleteFramebuffers@8 @30
+ glDeleteProgram@4 @32
+ glDeleteRenderbuffers@8 @33
+ glDeleteShader@4 @34
+ glDeleteTextures@8 @31
+ glDepthFunc@4 @36
+ glDepthMask@4 @37
+ glDepthRangef@8 @38
+ glDetachShader@8 @35
+ glDisable@4 @39
+ glDisableVertexAttribArray@4 @40
+ glDrawArrays@12 @41
+ glDrawElements@16 @42
+ glEnable@4 @43
+ glEnableVertexAttribArray@4 @44
+ glFinish@0 @45
+ glFlush@0 @46
+ glFramebufferRenderbuffer@16 @47
+ glFramebufferTexture2D@20 @48
+ glFrontFace@4 @49
+ glGenBuffers@8 @50
+ glGenFramebuffers@8 @52
+ glGenRenderbuffers@8 @53
+ glGenTextures@8 @54
+ glGenerateMipmap@4 @51
+ glGetActiveAttrib@28 @55
+ glGetActiveUniform@28 @56
+ glGetAttachedShaders@16 @57
+ glGetAttribLocation@8 @58
+ glGetBooleanv@8 @59
+ glGetBufferParameteriv@12 @60
+ glGetError@0 @61
+ glGetFloatv@8 @62
+ glGetFramebufferAttachmentParameteriv@16 @63
+ glGetIntegerv@8 @64
+ glGetProgramInfoLog@16 @66
+ glGetProgramiv@12 @65
+ glGetRenderbufferParameteriv@12 @67
+ glGetShaderInfoLog@16 @69
+ glGetShaderPrecisionFormat@16 @70
+ glGetShaderSource@16 @71
+ glGetShaderiv@12 @68
+ glGetString@4 @72
+ glGetTexParameterfv@12 @73
+ glGetTexParameteriv@12 @74
+ glGetUniformLocation@8 @77
+ glGetUniformfv@12 @75
+ glGetUniformiv@12 @76
+ glGetVertexAttribPointerv@12 @80
+ glGetVertexAttribfv@12 @78
+ glGetVertexAttribiv@12 @79
+ glHint@8 @81
+ glIsBuffer@4 @82
+ glIsEnabled@4 @83
+ glIsFramebuffer@4 @84
+ glIsProgram@4 @85
+ glIsRenderbuffer@4 @86
+ glIsShader@4 @87
+ glIsTexture@4 @88
+ glLineWidth@4 @89
+ glLinkProgram@4 @90
+ glPixelStorei@8 @91
+ glPolygonOffset@8 @92
+ glReadPixels@28 @93
+ glReleaseShaderCompiler@0 @94
+ glRenderbufferStorage@16 @95
+ glSampleCoverage@8 @96
+ glScissor@16 @97
+ glShaderBinary@20 @98
+ glShaderSource@16 @99
+ glStencilFunc@12 @100
+ glStencilFuncSeparate@16 @101
+ glStencilMask@4 @102
+ glStencilMaskSeparate@8 @103
+ glStencilOp@12 @104
+ glStencilOpSeparate@16 @105
+ glTexImage2D@36 @106
+ glTexParameterf@12 @107
+ glTexParameterfv@12 @108
+ glTexParameteri@12 @109
+ glTexParameteriv@12 @110
+ glTexSubImage2D@36 @111
+ glUniform1f@8 @112
+ glUniform1fv@12 @113
+ glUniform1i@8 @114
+ glUniform1iv@12 @115
+ glUniform2f@12 @116
+ glUniform2fv@12 @117
+ glUniform2i@12 @118
+ glUniform2iv@12 @119
+ glUniform3f@16 @120
+ glUniform3fv@12 @121
+ glUniform3i@16 @122
+ glUniform3iv@12 @123
+ glUniform4f@20 @124
+ glUniform4fv@12 @125
+ glUniform4i@20 @126
+ glUniform4iv@12 @127
+ glUniformMatrix2fv@16 @128
+ glUniformMatrix3fv@16 @129
+ glUniformMatrix4fv@16 @130
+ glUseProgram@4 @131
+ glValidateProgram@4 @132
+ glVertexAttrib1f@8 @133
+ glVertexAttrib1fv@8 @134
+ glVertexAttrib2f@12 @135
+ glVertexAttrib2fv@8 @136
+ glVertexAttrib3f@16 @137
+ glVertexAttrib3fv@8 @138
+ glVertexAttrib4f@20 @139
+ glVertexAttrib4fv@8 @140
+ glVertexAttribPointer@24 @141
+ glViewport@16 @142
- ; Extensions
- glTexImage3DOES@40 @143
- glBlitFramebufferANGLE@40 @149
- glRenderbufferStorageMultisampleANGLE@20 @150
- glDeleteFencesNV@8 @151
- glFinishFenceNV@4 @152
- glGenFencesNV@8 @153
- glGetFenceivNV@12 @154
- glIsFenceNV@4 @155
- glSetFenceNV@8 @156
- glTestFenceNV@4 @157
- glGetTranslatedShaderSourceANGLE@16 @159
- glTexStorage2DEXT@20 @160
- glGetGraphicsResetStatusEXT@0 @161
- glReadnPixelsEXT@32 @162
- glGetnUniformfvEXT@16 @163
- glGetnUniformivEXT@16 @164
- glGenQueriesEXT@8 @165
- glDeleteQueriesEXT@8 @166
- glIsQueryEXT@4 @167
- glBeginQueryEXT@8 @168
- glEndQueryEXT@4 @169
- glGetQueryivEXT@12 @170
- glGetQueryObjectuivEXT@12 @171
- glVertexAttribDivisorANGLE@8 @172
- glDrawArraysInstancedANGLE@16 @173
- glDrawElementsInstancedANGLE@20 @174
- glProgramBinaryOES@16 @175
- glGetProgramBinaryOES@20 @176
- glDrawBuffersEXT@8 @179
+ ; Extensions
+ glTexImage3DOES@40 @143
+ glBlitFramebufferANGLE@40 @149
+ glRenderbufferStorageMultisampleANGLE@20 @150
+ glDeleteFencesNV@8 @151
+ glFinishFenceNV@4 @152
+ glGenFencesNV@8 @153
+ glGetFenceivNV@12 @154
+ glIsFenceNV@4 @155
+ glSetFenceNV@8 @156
+ glTestFenceNV@4 @157
+ glGetTranslatedShaderSourceANGLE@16 @159
+ glTexStorage2DEXT@20 @160
+ glGetGraphicsResetStatusEXT@0 @161
+ glReadnPixelsEXT@32 @162
+ glGetnUniformfvEXT@16 @163
+ glGetnUniformivEXT@16 @164
+ glGenQueriesEXT@8 @165
+ glDeleteQueriesEXT@8 @166
+ glIsQueryEXT@4 @167
+ glBeginQueryEXT@8 @168
+ glEndQueryEXT@4 @169
+ glGetQueryivEXT@12 @170
+ glGetQueryObjectuivEXT@12 @171
+ glVertexAttribDivisorANGLE@8 @172
+ glDrawArraysInstancedANGLE@16 @173
+ glDrawElementsInstancedANGLE@20 @174
+ glProgramBinaryOES@16 @175
+ glGetProgramBinaryOES@20 @176
+ glDrawBuffersEXT@8 @179
+ glMapBufferOES@8 @285
+ glUnmapBufferOES@4 @286
+ glGetBufferPointervOES@12 @287
+ glMapBufferRangeEXT@16 @288
+ glFlushMappedBufferRangeEXT@12 @289
- ; EGL dependencies
- glCreateContext @144 NONAME
- glDestroyContext @145 NONAME
- glMakeCurrent @146 NONAME
- glGetCurrentContext @147 NONAME
- glGetProcAddress@4 @148 NONAME
- glBindTexImage@4 @158 NONAME
- glCreateRenderer @177 NONAME
- glDestroyRenderer @178 NONAME
+ ; GLES 3.0 Functions
+ glReadBuffer@4 @180
+ glDrawRangeElements@24 @181
+ glTexImage3D@40 @182
+ glTexSubImage3D@44 @183
+ glCopyTexSubImage3D@36 @184
+ glCompressedTexImage3D@36 @185
+ glCompressedTexSubImage3D@44 @186
+ glGenQueries@8 @187
+ glDeleteQueries@8 @188
+ glIsQuery@4 @189
+ glBeginQuery@8 @190
+ glEndQuery@4 @191
+ glGetQueryiv@12 @192
+ glGetQueryObjectuiv@12 @193
+ glUnmapBuffer@4 @194
+ glGetBufferPointerv@12 @195
+ glDrawBuffers@8 @196
+ glUniformMatrix2x3fv@16 @197
+ glUniformMatrix3x2fv@16 @198
+ glUniformMatrix2x4fv@16 @199
+ glUniformMatrix4x2fv@16 @200
+ glUniformMatrix3x4fv@16 @201
+ glUniformMatrix4x3fv@16 @202
+ glBlitFramebuffer@40 @203
+ glRenderbufferStorageMultisample@20 @204
+ glFramebufferTextureLayer@20 @205
+ glMapBufferRange@16 @206
+ glFlushMappedBufferRange@12 @207
+ glBindVertexArray@4 @208
+ glDeleteVertexArrays@8 @209
+ glGenVertexArrays@8 @210
+ glIsVertexArray@4 @211
+ glGetIntegeri_v@12 @212
+ glBeginTransformFeedback@4 @213
+ glEndTransformFeedback@0 @214
+ glBindBufferRange@20 @215
+ glBindBufferBase@12 @216
+ glTransformFeedbackVaryings@16 @217
+ glGetTransformFeedbackVarying@28 @218
+ glVertexAttribIPointer@20 @219
+ glGetVertexAttribIiv@12 @220
+ glGetVertexAttribIuiv@12 @221
+ glVertexAttribI4i@20 @222
+ glVertexAttribI4ui@20 @223
+ glVertexAttribI4iv@8 @224
+ glVertexAttribI4uiv@8 @225
+ glGetUniformuiv@12 @226
+ glGetFragDataLocation@8 @227
+ glUniform1ui@8 @228
+ glUniform2ui@12 @229
+ glUniform3ui@16 @230
+ glUniform4ui@20 @231
+ glUniform1uiv@12 @232
+ glUniform2uiv@12 @233
+ glUniform3uiv@12 @234
+ glUniform4uiv@12 @235
+ glClearBufferiv@12 @236
+ glClearBufferuiv@12 @237
+ glClearBufferfv@12 @238
+ glClearBufferfi@16 @239
+ glGetStringi@8 @240
+ glCopyBufferSubData@20 @241
+ glGetUniformIndices@16 @242
+ glGetActiveUniformsiv@20 @243
+ glGetUniformBlockIndex@8 @244
+ glGetActiveUniformBlockiv@16 @245
+ glGetActiveUniformBlockName@20 @246
+ glUniformBlockBinding@12 @247
+ glDrawArraysInstanced@16 @248
+ glDrawElementsInstanced@20 @249
+ glFenceSync@8 @250
+ glIsSync@4 @251
+ glDeleteSync@4 @252
+ glClientWaitSync@16 @253
+ glWaitSync@16 @254
+ glGetInteger64v@8 @255
+ glGetSynciv@20 @256
+ glGetInteger64i_v@12 @257
+ glGetBufferParameteri64v@12 @258
+ glGenSamplers@8 @259
+ glDeleteSamplers@8 @260
+ glIsSampler@4 @261
+ glBindSampler@8 @262
+ glSamplerParameteri@12 @263
+ glSamplerParameteriv@12 @264
+ glSamplerParameterf@12 @265
+ glSamplerParameterfv@12 @266
+ glGetSamplerParameteriv@12 @267
+ glGetSamplerParameterfv@12 @268
+ glVertexAttribDivisor@8 @269
+ glBindTransformFeedback@8 @270
+ glDeleteTransformFeedbacks@8 @271
+ glGenTransformFeedbacks@8 @272
+ glIsTransformFeedback@4 @273
+ glPauseTransformFeedback@0 @274
+ glResumeTransformFeedback@0 @275
+ glGetProgramBinary@20 @276
+ glProgramBinary@16 @277
+ glProgramParameteri@12 @278
+ glInvalidateFramebuffer@12 @279
+ glInvalidateSubFramebuffer@28 @280
+ glTexStorage2D@20 @281
+ glTexStorage3D@24 @282
+ glGetInternalformativ@20 @283
- ; Setting up TRACE macro callbacks
- SetTraceFunctionPointers@8 @180
+ ; EGL dependencies
+ glCreateContext @144 NONAME
+ glDestroyContext @145 NONAME
+ glMakeCurrent @146 NONAME
+ glGetCurrentContext @147 NONAME
+ glGetProcAddress@4 @148 NONAME
+ glBindTexImage@4 @158 NONAME
+ glCreateRenderer @177 NONAME
+ glDestroyRenderer @178 NONAME
diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp
index e52799438d..51447e273a 100644
--- a/src/3rdparty/angle/src/libGLESv2/main.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/main.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -8,60 +7,56 @@
// main.cpp: DLL entry point and management of thread-local data.
#include "libGLESv2/main.h"
-
#include "libGLESv2/Context.h"
-#if !defined(ANGLE_OS_WINRT)
-static DWORD currentTLS = TLS_OUT_OF_INDEXES;
-#else
-static __declspec(thread) void *currentTLS = 0;
+#include "common/tls.h"
+
+#if defined(ANGLE_PLATFORM_WINRT)
+__declspec(thread)
#endif
+static TLSIndex currentTLS = TLS_OUT_OF_INDEXES;
namespace gl
{
Current *AllocateCurrent()
{
-#if !defined(ANGLE_OS_WINRT)
- Current *current = (Current*)LocalAlloc(LPTR, sizeof(Current));
-#else
- currentTLS = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Current));
- Current *current = (Current*)currentTLS;
+#if defined(ANGLE_PLATFORM_WINRT)
+ if (currentTLS == TLS_OUT_OF_INDEXES)
+ {
+ currentTLS = CreateTLSIndex();
+ }
#endif
-
- if (!current)
+ ASSERT(currentTLS != TLS_OUT_OF_INDEXES);
+ if (currentTLS == TLS_OUT_OF_INDEXES)
{
- ERR("Could not allocate thread local storage.");
return NULL;
}
-#if !defined(ANGLE_OS_WINRT)
- ASSERT(currentTLS != TLS_OUT_OF_INDEXES);
- TlsSetValue(currentTLS, current);
-#endif
-
+ Current *current = new Current();
current->context = NULL;
current->display = NULL;
+ if (!SetTLSValue(currentTLS, current))
+ {
+ ERR("Could not set thread local storage.");
+ return NULL;
+ }
+
return current;
}
void DeallocateCurrent()
{
-#if !defined(ANGLE_OS_WINRT)
- void *current = TlsGetValue(currentTLS);
-
- if (current)
+#if defined(ANGLE_PLATFORM_WINRT)
+ if (currentTLS == TLS_OUT_OF_INDEXES)
{
- LocalFree((HLOCAL)current);
- }
-#else
- if (currentTLS)
- {
- HeapFree(GetProcessHeap(), 0, currentTLS);
- currentTLS = 0;
+ return;
}
#endif
+ Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
+ SafeDelete(current);
+ SetTLSValue(currentTLS, NULL);
}
}
@@ -74,16 +69,16 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
{
case DLL_PROCESS_ATTACH:
{
-#if !defined(ANGLE_OS_WINRT)
- currentTLS = TlsAlloc();
-
+#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain
+ return DisableThreadLibraryCalls(instance);
+#endif
+ currentTLS = CreateTLSIndex();
if (currentTLS == TLS_OUT_OF_INDEXES)
{
return FALSE;
}
-#endif
}
- // Fall throught to initialize index
+ // Fall through to initialize index
case DLL_THREAD_ATTACH:
{
gl::AllocateCurrent();
@@ -96,9 +91,9 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
break;
case DLL_PROCESS_DETACH:
{
+#if !defined(ANGLE_PLATFORM_WINRT)
gl::DeallocateCurrent();
-#if !defined(ANGLE_OS_WINRT)
- TlsFree(currentTLS);
+ DestroyTLSIndex(currentTLS);
#endif
}
break;
@@ -117,20 +112,16 @@ namespace gl
Current *GetCurrentData()
{
#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
-#if !defined(ANGLE_OS_WINRT)
- Current *current = (Current*)TlsGetValue(currentTLS);
-#else
- Current *current = (Current*)currentTLS;
-#endif
-#else
- // No precautions for thread safety taken as ANGLE is used single-threaded in Qt.
- static Current s_current = { 0, 0 };
- Current *current = &s_current;
-#endif
+ Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
// ANGLE issue 488: when the dll is loaded after thread initialization,
// thread local storage (current) might not exist yet.
return (current ? current : AllocateCurrent());
+#else
+ // No precautions for thread safety taken as ANGLE is used single-threaded in Qt.
+ static Current current = { 0, 0 };
+ return &current;
+#endif
}
void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
@@ -156,7 +147,7 @@ Context *getContext()
Context *getNonLostContext()
{
Context *context = getContext();
-
+
if (context)
{
if (context->isContextLost())
@@ -183,33 +174,26 @@ egl::Display *getDisplay()
void error(GLenum errorCode)
{
gl::Context *context = glGetCurrentContext();
+ context->recordError(Error(errorCode));
- if (context)
+ switch (errorCode)
{
- switch (errorCode)
- {
- case GL_INVALID_ENUM:
- context->recordInvalidEnum();
- TRACE("\t! Error generated: invalid enum\n");
- break;
- case GL_INVALID_VALUE:
- context->recordInvalidValue();
- TRACE("\t! Error generated: invalid value\n");
- break;
- case GL_INVALID_OPERATION:
- context->recordInvalidOperation();
- TRACE("\t! Error generated: invalid operation\n");
- break;
- case GL_OUT_OF_MEMORY:
- context->recordOutOfMemory();
- TRACE("\t! Error generated: out of memory\n");
- break;
- case GL_INVALID_FRAMEBUFFER_OPERATION:
- context->recordInvalidFramebufferOperation();
- TRACE("\t! Error generated: invalid framebuffer operation\n");
- break;
- default: UNREACHABLE();
- }
+ case GL_INVALID_ENUM:
+ TRACE("\t! Error generated: invalid enum\n");
+ break;
+ case GL_INVALID_VALUE:
+ TRACE("\t! Error generated: invalid value\n");
+ break;
+ case GL_INVALID_OPERATION:
+ TRACE("\t! Error generated: invalid operation\n");
+ break;
+ case GL_OUT_OF_MEMORY:
+ TRACE("\t! Error generated: out of memory\n");
+ break;
+ case GL_INVALID_FRAMEBUFFER_OPERATION:
+ TRACE("\t! Error generated: invalid framebuffer operation\n");
+ break;
+ default: UNREACHABLE();
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h
index 69465c9bbf..c30ad3375c 100644
--- a/src/3rdparty/angle/src/libGLESv2/main.h
+++ b/src/3rdparty/angle/src/libGLESv2/main.h
@@ -11,6 +11,13 @@
#include "common/debug.h"
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+
+#ifndef Sleep
+#define Sleep(ms) WaitForSingleObjectEx(GetCurrentThread(), ms, FALSE)
+#endif
+
namespace egl
{
class Display;
@@ -53,11 +60,11 @@ class Renderer;
extern "C"
{
// Exported functions for use by EGL
-gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
+gl::Context *glCreateContext(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
void glDestroyContext(gl::Context *context);
void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
gl::Context *glGetCurrentContext();
-rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType displayId);
+rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType);
void glDestroyRenderer(rx::Renderer *renderer);
__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
diff --git a/src/3rdparty/angle/src/libGLESv2/mathutil.h b/src/3rdparty/angle/src/libGLESv2/mathutil.h
deleted file mode 100644
index 6474b66745..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/mathutil.h
+++ /dev/null
@@ -1,162 +0,0 @@
-//
-// 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.
-//
-
-// mathutil.h: Math and bit manipulation functions.
-
-#ifndef LIBGLESV2_MATHUTIL_H_
-#define LIBGLESV2_MATHUTIL_H_
-
-#include <intrin.h>
-
-#include "common/debug.h"
-
-namespace gl
-{
-struct Vector4
-{
- Vector4() {}
- Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
-
- float x;
- float y;
- float z;
- float w;
-};
-
-inline bool isPow2(int x)
-{
- return (x & (x - 1)) == 0 && (x != 0);
-}
-
-inline int log2(int x)
-{
- int r = 0;
- while ((x >> r) > 1) r++;
- return r;
-}
-
-inline unsigned int ceilPow2(unsigned int x)
-{
- if (x != 0) x--;
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
- x++;
-
- return x;
-}
-
-template<typename T, typename MIN, typename MAX>
-inline T clamp(T x, MIN min, MAX max)
-{
- // Since NaNs fail all comparison tests, a NaN value will default to min
- return x > min ? (x > max ? max : x) : min;
-}
-
-inline float clamp01(float x)
-{
- return clamp(x, 0.0f, 1.0f);
-}
-
-template<const int n>
-inline unsigned int unorm(float x)
-{
- const unsigned int max = 0xFFFFFFFF >> (32 - n);
-
- if (x > 1)
- {
- return max;
- }
- else if (x < 0)
- {
- return 0;
- }
- else
- {
- return (unsigned int)(max * x + 0.5f);
- }
-}
-
-inline bool supportsSSE2()
-{
- static bool checked = false;
- static bool supports = false;
-
- if (checked)
- {
- return supports;
- }
-
-#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid()
- int info[4];
- __cpuid(info, 0);
-
- if (info[0] >= 1)
- {
- __cpuid(info, 1);
-
- supports = (info[3] >> 26) & 1;
- }
-#endif
-
- checked = true;
-
- return supports;
-}
-
-inline unsigned short float32ToFloat16(float fp32)
-{
- unsigned int fp32i = (unsigned int&)fp32;
- unsigned int sign = (fp32i & 0x80000000) >> 16;
- unsigned int abs = fp32i & 0x7FFFFFFF;
-
- if(abs > 0x47FFEFFF) // Infinity
- {
- return sign | 0x7FFF;
- }
- else if(abs < 0x38800000) // Denormal
- {
- unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;
- int e = 113 - (abs >> 23);
-
- if(e < 24)
- {
- abs = mantissa >> e;
- }
- else
- {
- abs = 0;
- }
-
- return sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13;
- }
- else
- {
- return sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13;
- }
-}
-
-float float16ToFloat32(unsigned short h);
-
-}
-
-namespace rx
-{
-
-struct Range
-{
- Range() {}
- Range(int lo, int hi) : start(lo), end(hi) { ASSERT(lo <= hi); }
-
- int start;
- int end;
-};
-
-}
-
-#endif // LIBGLESV2_MATHUTIL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.cpp b/src/3rdparty/angle/src/libGLESv2/precompiled.cpp
deleted file mode 100644
index 2621cd6ce3..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/precompiled.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-//
-// 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.
-//
-
-// precompiled.cpp: Precompiled header source file for libGLESv2.
-
-#include "precompiled.h"
diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h
deleted file mode 100644
index 2ff09f531e..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/precompiled.h
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// 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.
-//
-
-// precompiled.h: Precompiled header file for libGLESv2.
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#define EGLAPI
-#include <EGL/egl.h>
-
-#include <assert.h>
-#include <cstddef>
-#include <float.h>
-#include <intrin.h>
-#include <math.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <algorithm> // for std::min and std::max
-#include <limits>
-#include <map>
-#include <set>
-#include <sstream>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
-# define ANGLE_OS_WINRT
-# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-# define ANGLE_OS_WINPHONE
-# endif
-#endif
-
-#if defined(ANGLE_ENABLE_D3D9)
-# include <d3d9.h>
-#endif
-#if defined(ANGLE_ENABLE_D3D11)
-# if !defined(ANGLE_OS_WINRT)
-# include <d3d11.h>
-# else
-# include <d3d11_1.h>
-# define Sleep(x) WaitForSingleObjectEx(GetCurrentThread(), x, FALSE)
-# define GetVersion() WINVER
-# define LoadLibrary(x) LoadPackagedLibrary(x, NULL)
-# endif
-# include <dxgi.h>
-#endif
-#if !defined(ANGLE_OS_WINPHONE)
-# include <d3dcompiler.h>
-#endif
-
-#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL0
-#define D3DCOMPILE_OPTIMIZATION_LEVEL0 (1 << 14)
-#endif
-#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL1
-#define D3DCOMPILE_OPTIMIZATION_LEVEL1 0
-#endif
-#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL2
-#define D3DCOMPILE_OPTIMIZATION_LEVEL2 ((1 << 14) | (1 << 15))
-#endif
-#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3
-#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15)
-#endif
-#ifndef D3DCOMPILE_DEBUG
-#define D3DCOMPILE_DEBUG (1 << 0)
-#endif
-#ifndef D3DCOMPILE_SKIP_OPTIMIZATION
-#define D3DCOMPILE_SKIP_OPTIMIZATION (1 << 2)
-#endif
-#ifndef D3DCOMPILE_AVOID_FLOW_CONTROL
-#define D3DCOMPILE_AVOID_FLOW_CONTROL (1 << 9)
-#endif
-#ifndef D3DCOMPILE_PREFER_FLOW_CONTROL
-#define D3DCOMPILE_PREFER_FLOW_CONTROL (1 << 10)
-#endif
-
-#ifdef _MSC_VER
-#include <hash_map>
-#endif
diff --git a/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp b/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp
new file mode 100644
index 0000000000..7245902c51
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp
@@ -0,0 +1,147 @@
+//
+// 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 "libGLESv2/Context.h"
+#include "common/utilities.h"
+
+namespace gl
+{
+
+// 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 CastStateValueEnum { static GLenum mEnumForType; };
+
+template <> GLenum CastStateValueEnum<GLint>::mEnumForType = GL_INT;
+template <> GLenum CastStateValueEnum<GLuint>::mEnumForType = GL_UNSIGNED_INT;
+template <> GLenum CastStateValueEnum<GLboolean>::mEnumForType = GL_BOOL;
+template <> GLenum CastStateValueEnum<GLint64>::mEnumForType = GL_INT_64_ANGLEX;
+template <> GLenum CastStateValueEnum<GLfloat>::mEnumForType = GL_FLOAT;
+
+template <typename QueryT, typename NativeT>
+QueryT CastStateValueToInt(GLenum pname, NativeT value)
+{
+ GLenum queryType = CastStateValueEnum<QueryT>::mEnumForType;
+ GLenum nativeType = CastStateValueEnum<NativeT>::mEnumForType;
+
+ 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 static_cast<QueryT>((static_cast<GLfloat>(0xFFFFFFFF) * value - 1.0f) / 2.0f);
+ }
+ else
+ {
+ return gl::iround<QueryT>(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 = CastStateValueEnum<QueryT>::mEnumForType;
+
+ 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 (value == static_cast<NativeT>(0) ? GL_FALSE : GL_TRUE);
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+template <typename QueryT>
+void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
+ unsigned int numParams, QueryT *outParams)
+{
+ if (nativeType == GL_INT)
+ {
+ GLint *intParams = NULL;
+ intParams = new GLint[numParams];
+
+ context->getIntegerv(pname, intParams);
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastStateValue<QueryT>(pname, intParams[i]);
+ }
+
+ delete [] intParams;
+ }
+ else if (nativeType == GL_BOOL)
+ {
+ GLboolean *boolParams = NULL;
+ boolParams = new GLboolean[numParams];
+
+ context->getBooleanv(pname, boolParams);
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = (boolParams[i] == GL_FALSE ? static_cast<QueryT>(0) : static_cast<QueryT>(1));
+ }
+
+ delete [] boolParams;
+ }
+ else if (nativeType == GL_FLOAT)
+ {
+ GLfloat *floatParams = NULL;
+ floatParams = new GLfloat[numParams];
+
+ context->getFloatv(pname, floatParams);
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastStateValue<QueryT>(pname, floatParams[i]);
+ }
+
+ delete [] floatParams;
+ }
+ else if (nativeType == GL_INT_64_ANGLEX)
+ {
+ GLint64 *int64Params = NULL;
+ int64Params = new GLint64[numParams];
+
+ context->getInteger64v(pname, int64Params);
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastStateValue<QueryT>(pname, int64Params[i]);
+ }
+
+ delete [] int64Params;
+ }
+ 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 *);
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/queryconversions.h b/src/3rdparty/angle/src/libGLESv2/queryconversions.h
new file mode 100644
index 0000000000..da7047f730
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/queryconversions.h
@@ -0,0 +1,17 @@
+//
+// 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
+
+namespace gl
+{
+
+// 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);
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h
new file mode 100644
index 0000000000..f0b5f02227
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h
@@ -0,0 +1,34 @@
+//
+// 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 LIBGLESV2_RENDERER_BUFFERIMPL_H_
+#define LIBGLESV2_RENDERER_BUFFERIMPL_H_
+
+#include "common/angleutils.h"
+#include "libGLESv2/Buffer.h"
+
+namespace rx
+{
+
+class BufferImpl
+{
+ public:
+ virtual ~BufferImpl() { }
+
+ virtual gl::Error setData(const void* data, size_t size, GLenum usage) = 0;
+ virtual void *getData() = 0;
+ virtual gl::Error setSubData(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(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0;
+ virtual gl::Error unmap() = 0;
+ virtual void markTransformFeedbackUsage() = 0;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_BUFFERIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp
deleted file mode 100644
index a49b7bab84..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "precompiled.h"
-//
-// 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.
-//
-
-// BufferStorage.cpp Defines the abstract BufferStorage class.
-
-#include "libGLESv2/renderer/BufferStorage.h"
-
-namespace rx
-{
-
-unsigned int BufferStorage::mNextSerial = 1;
-
-BufferStorage::BufferStorage()
-{
- updateSerial();
-}
-
-BufferStorage::~BufferStorage()
-{
-}
-
-unsigned int BufferStorage::getSerial() const
-{
- return mSerial;
-}
-
-void BufferStorage::updateSerial()
-{
- mSerial = mNextSerial++;
-}
-
-void BufferStorage::markBufferUsage()
-{
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h
deleted file mode 100644
index ace1a11bae..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// 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.
-//
-
-// BufferStorage.h Defines the abstract BufferStorage class.
-
-#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE_H_
-#define LIBGLESV2_RENDERER_BUFFERSTORAGE_H_
-
-#include "common/angleutils.h"
-
-namespace rx
-{
-
-class BufferStorage
-{
- public:
- BufferStorage();
- virtual ~BufferStorage();
-
- // The data returned is only guaranteed valid until next non-const method.
- virtual void *getData() = 0;
- virtual void setData(const void* data, unsigned int size, unsigned int offset) = 0;
- virtual void clear() = 0;
- virtual unsigned int getSize() const = 0;
- virtual bool supportsDirectBinding() const = 0;
- virtual void markBufferUsage();
- unsigned int getSerial() const;
-
- protected:
- void updateSerial();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BufferStorage);
-
- unsigned int mSerial;
- static unsigned int mNextSerial;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h
index d7f2102a2e..d54e6becd3 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h
@@ -17,27 +17,16 @@ namespace rx
class FenceImpl
{
public:
- FenceImpl() : mStatus(GL_FALSE), mCondition(GL_NONE) { };
+ FenceImpl() { };
virtual ~FenceImpl() { };
- virtual GLboolean isFence() = 0;
- virtual void setFence(GLenum condition) = 0;
- virtual GLboolean testFence() = 0;
- virtual void finishFence() = 0;
- virtual void getFenceiv(GLenum pname, GLint *params) = 0;
-
- protected:
- void setStatus(GLboolean status) { mStatus = status; }
- GLboolean getStatus() const { return mStatus; }
-
- void setCondition(GLuint condition) { mCondition = condition; }
- GLuint getCondition() const { return mCondition; }
+ virtual bool isSet() const = 0;
+ virtual void set() = 0;
+ virtual bool test(bool flushCommandBuffer) = 0;
+ virtual bool hasError() const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(FenceImpl);
-
- GLboolean mStatus;
- GLenum mCondition;
};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp
index 57239ef74f..370b086233 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -18,531 +17,12 @@ Image::Image()
{
mWidth = 0;
mHeight = 0;
+ mDepth = 0;
mInternalFormat = GL_NONE;
mActualFormat = GL_NONE;
-}
-
-void Image::loadAlphaDataToBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned char *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = static_cast<const unsigned char*>(input) + y * inputPitch;
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = 0;
- dest[4 * x + 1] = 0;
- dest[4 * x + 2] = 0;
- dest[4 * x + 3] = source[x];
- }
- }
-}
-
-void Image::loadAlphaDataToNative(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned char *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = static_cast<const unsigned char*>(input) + y * inputPitch;
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
- memcpy(dest, source, width);
- }
-}
-
-void Image::loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const float *source = NULL;
- float *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = 0;
- dest[4 * x + 1] = 0;
- dest[4 * x + 2] = 0;
- dest[4 * x + 3] = source[x];
- }
- }
-}
-
-void Image::loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned short *source = NULL;
- unsigned short *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = 0;
- dest[4 * x + 1] = 0;
- dest[4 * x + 2] = 0;
- dest[4 * x + 3] = source[x];
- }
- }
-}
-
-void Image::loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output, bool native)
-{
- const unsigned char *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = static_cast<const unsigned char*>(input) + y * inputPitch;
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
-
- if (!native) // BGRA8 destination format
- {
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[x];
- dest[4 * x + 1] = source[x];
- dest[4 * x + 2] = source[x];
- dest[4 * x + 3] = 0xFF;
- }
- }
- else // L8 destination format
- {
- memcpy(dest, source, width);
- }
- }
-}
-
-void Image::loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const float *source = NULL;
- float *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[x];
- dest[4 * x + 1] = source[x];
- dest[4 * x + 2] = source[x];
- dest[4 * x + 3] = 1.0f;
- }
- }
-}
-
-void Image::loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const float *source = NULL;
- float *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
- for (int x = 0; x < width; x++)
- {
- dest[3 * x + 0] = source[x];
- dest[3 * x + 1] = source[x];
- dest[3 * x + 2] = source[x];
- }
- }
-}
-
-void Image::loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned short *source = NULL;
- unsigned short *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[x];
- dest[4 * x + 1] = source[x];
- dest[4 * x + 2] = source[x];
- dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
- }
- }
-}
-
-void Image::loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output, bool native)
-{
- const unsigned char *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = static_cast<const unsigned char*>(input) + y * inputPitch;
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
-
- if (!native) // BGRA8 destination format
- {
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[2*x+0];
- dest[4 * x + 1] = source[2*x+0];
- dest[4 * x + 2] = source[2*x+0];
- dest[4 * x + 3] = source[2*x+1];
- }
- }
- else
- {
- memcpy(dest, source, width * 2);
- }
- }
-}
-
-void Image::loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const float *source = NULL;
- float *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[2*x+0];
- dest[4 * x + 1] = source[2*x+0];
- dest[4 * x + 2] = source[2*x+0];
- dest[4 * x + 3] = source[2*x+1];
- }
- }
-}
-
-void Image::loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned short *source = NULL;
- unsigned short *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[2*x+0];
- dest[4 * x + 1] = source[2*x+0];
- dest[4 * x + 2] = source[2*x+0];
- dest[4 * x + 3] = source[2*x+1];
- }
- }
-}
-
-void Image::loadRGBUByteDataToBGRX(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned char *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = static_cast<const unsigned char*>(input) + y * inputPitch;
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[x * 3 + 2];
- dest[4 * x + 1] = source[x * 3 + 1];
- dest[4 * x + 2] = source[x * 3 + 0];
- dest[4 * x + 3] = 0xFF;
- }
- }
-}
-
-void Image::loadRGBUByteDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned char *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = static_cast<const unsigned char*>(input) + y * inputPitch;
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[x * 3 + 0];
- dest[4 * x + 1] = source[x * 3 + 1];
- dest[4 * x + 2] = source[x * 3 + 2];
- dest[4 * x + 3] = 0xFF;
- }
- }
-}
-
-void Image::loadRGB565DataToBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned short *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
- for (int x = 0; x < width; x++)
- {
- unsigned short rgba = source[x];
- dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
- dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
- dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
- dest[4 * x + 3] = 0xFF;
- }
- }
-}
-
-void Image::loadRGB565DataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned short *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
- for (int x = 0; x < width; x++)
- {
- unsigned short rgba = source[x];
- dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
- dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
- dest[4 * x + 2] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
- dest[4 * x + 3] = 0xFF;
- }
- }
-}
-
-void Image::loadRGBFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const float *source = NULL;
- float *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[x * 3 + 0];
- dest[4 * x + 1] = source[x * 3 + 1];
- dest[4 * x + 2] = source[x * 3 + 2];
- dest[4 * x + 3] = 1.0f;
- }
- }
-}
-
-void Image::loadRGBFloatDataToNative(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const float *source = NULL;
- float *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
- memcpy(dest, source, width * 12);
- }
-}
-
-void Image::loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned short *source = NULL;
- unsigned short *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
- for (int x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[x * 3 + 0];
- dest[4 * x + 1] = source[x * 3 + 1];
- dest[4 * x + 2] = source[x * 3 + 2];
- dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
- }
- }
-}
-
-void Image::loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned int *source = NULL;
- unsigned int *dest = NULL;
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
-
- for (int x = 0; x < width; x++)
- {
- unsigned int rgba = source[x];
- dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
- }
- }
-}
-
-void Image::loadRGBAUByteDataToNative(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned int *source = NULL;
- unsigned int *dest = NULL;
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
-
- memcpy(dest, source, width * 4);
- }
-}
-
-void Image::loadRGBA4444DataToBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned short *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
- for (int x = 0; x < width; x++)
- {
- unsigned short rgba = source[x];
- dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
- dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
- dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
- dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
- }
- }
-}
-
-void Image::loadRGBA4444DataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned short *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
- for (int x = 0; x < width; x++)
- {
- unsigned short rgba = source[x];
- dest[4 * x + 0] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
- dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
- dest[4 * x + 2] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
- dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
- }
- }
-}
-
-void Image::loadRGBA5551DataToBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned short *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
- for (int x = 0; x < width; x++)
- {
- unsigned short rgba = source[x];
- dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
- dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
- dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
- dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
- }
- }
-}
-
-void Image::loadRGBA5551DataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned short *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
- for (int x = 0; x < width; x++)
- {
- unsigned short rgba = source[x];
- dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
- dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
- dest[4 * x + 2] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
- dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
- }
- }
-}
-
-void Image::loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const float *source = NULL;
- float *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
- memcpy(dest, source, width * 16);
- }
-}
-
-void Image::loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned char *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = static_cast<const unsigned char*>(input) + y * inputPitch;
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
- memcpy(dest, source, width * 8);
- }
-}
-
-void Image::loadBGRADataToBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned char *source = NULL;
- unsigned char *dest = NULL;
-
- for (int y = 0; y < height; y++)
- {
- source = static_cast<const unsigned char*>(input) + y * inputPitch;
- dest = static_cast<unsigned char*>(output) + y * outputPitch;
- memcpy(dest, source, width*4);
- }
+ mTarget = GL_NONE;
+ mRenderable = false;
+ mDirty = false;
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h
index 454e83e21e..3bfc663762 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h
@@ -13,6 +13,8 @@
#include "common/debug.h"
+#include <GLES2/gl2.h>
+
namespace gl
{
class Framebuffer;
@@ -20,9 +22,8 @@ class Framebuffer;
namespace rx
{
+
class Renderer;
-class TextureStorageInterface2D;
-class TextureStorageInterfaceCube;
class Image
{
@@ -32,93 +33,33 @@ class Image
GLsizei getWidth() const { return mWidth; }
GLsizei getHeight() const { return mHeight; }
+ GLsizei getDepth() const { return mDepth; }
GLenum getInternalFormat() const { return mInternalFormat; }
GLenum getActualFormat() const { return mActualFormat; }
+ GLenum getTarget() const { return mTarget; }
+ bool isRenderableFormat() const { return mRenderable; }
void markDirty() {mDirty = true;}
void markClean() {mDirty = false;}
virtual bool isDirty() const = 0;
- virtual void setManagedSurface(TextureStorageInterface2D *storage, int level) {};
- virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) {};
- virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
- virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
-
- virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) = 0;
+ virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) = 0;
- virtual bool isRenderableFormat() const = 0;
-
- virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLint unpackAlignment, const void *input) = 0;
- virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+ GLint unpackAlignment, GLenum type, const void *input) = 0;
+ virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
const void *input) = 0;
- virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
-
- static void loadAlphaDataToBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadAlphaDataToNative(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output, bool native);
- static void loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output, bool native);
- static void loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBUByteDataToBGRX(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBUByteDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGB565DataToBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGB565DataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBFloatDataToNative(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBAUByteDataToNative(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBA4444DataToBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBA4444DataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBA5551DataToBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBA5551DataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
- static void loadBGRADataToBGRA(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output);
+ virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
protected:
GLsizei mWidth;
GLsizei mHeight;
- GLint mInternalFormat;
+ GLsizei mDepth;
+ GLenum mInternalFormat;
GLenum mActualFormat;
+ bool mRenderable;
+ GLenum mTarget;
bool mDirty;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp
deleted file mode 100644
index b2a90ca961..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "precompiled.h"
-//
-// 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.
-//
-
-// ImageSSE2.cpp: Implements SSE2-based functions of rx::Image class. It's
-// in a separated file for GCC, which can enable SSE usage only per-file,
-// not for code blocks that use SSE2 explicitly.
-
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/renderer/Image.h"
-
-namespace rx
-{
-
-void Image::loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned int *source = NULL;
- unsigned int *dest = NULL;
- __m128i brMask = _mm_set1_epi32(0x00ff00ff);
-
- for (int y = 0; y < height; y++)
- {
- source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
- dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
- int x = 0;
-
- // Make output writes aligned
- for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
- {
- unsigned int rgba = source[x];
- dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
- }
-
- for (; x + 3 < width; x += 4)
- {
- __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
- // Mask out g and a, which don't change
- __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
- // Mask out b and r
- __m128i brComponents = _mm_and_si128(sourceData, brMask);
- // Swap b and r
- __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
- __m128i result = _mm_or_si128(gaComponents, brSwapped);
- _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
- }
-
- // Perform leftover writes
- for (; x < width; x++)
- {
- unsigned int rgba = source[x];
- dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
- }
- }
-}
-
-void Image::loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height,
- int inputPitch, const void *input, size_t outputPitch, void *output)
-{
- const unsigned char *source = NULL;
- unsigned int *dest = NULL;
- __m128i zeroWide = _mm_setzero_si128();
-
- for (int y = 0; y < height; y++)
- {
- source = static_cast<const unsigned char*>(input) + y * inputPitch;
- dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
-
- int x;
- // Make output writes aligned
- for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++)
- {
- dest[x] = static_cast<unsigned int>(source[x]) << 24;
- }
-
- for (; x + 7 < width; x += 8)
- {
- __m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x]));
- // Interleave each byte to 16bit, make the lower byte to zero
- sourceData = _mm_unpacklo_epi8(zeroWide, sourceData);
- // Interleave each 16bit to 32bit, make the lower 16bit to zero
- __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData);
- __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData);
-
- _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo);
- _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi);
- }
-
- // Handle the remainder
- for (; x < width; x++)
- {
- dest[x] = static_cast<unsigned int>(source[x]) << 24;
- }
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp
deleted file mode 100644
index 49bace8193..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp
+++ /dev/null
@@ -1,339 +0,0 @@
-#include "precompiled.h"
-//
-// 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.
-//
-
-// IndexDataManager.cpp: Defines the IndexDataManager, a class that
-// runs the Buffer translation process for index buffers.
-
-#include "libGLESv2/renderer/IndexDataManager.h"
-#include "libGLESv2/renderer/BufferStorage.h"
-
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/renderer/IndexBuffer.h"
-
-namespace rx
-{
-
-IndexDataManager::IndexDataManager(Renderer *renderer) : mRenderer(renderer)
-{
- mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer);
- if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
- {
- delete mStreamingBufferShort;
- mStreamingBufferShort = NULL;
- }
-
- mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer);
- if (!mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
- {
- delete mStreamingBufferInt;
- mStreamingBufferInt = NULL;
- }
-
- if (!mStreamingBufferShort)
- {
- // Make sure both buffers are deleted.
- delete mStreamingBufferInt;
- mStreamingBufferInt = NULL;
-
- ERR("Failed to allocate the streaming index buffer(s).");
- }
-
- mCountingBuffer = NULL;
-}
-
-IndexDataManager::~IndexDataManager()
-{
- delete mStreamingBufferShort;
- delete mStreamingBufferInt;
- delete mCountingBuffer;
-}
-
-static void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
-{
- if (type == GL_UNSIGNED_BYTE)
- {
- const GLubyte *in = static_cast<const GLubyte*>(input);
- GLushort *out = static_cast<GLushort*>(output);
-
- for (GLsizei i = 0; i < count; i++)
- {
- out[i] = in[i];
- }
- }
- else if (type == GL_UNSIGNED_INT)
- {
- memcpy(output, input, count * sizeof(GLuint));
- }
- else if (type == GL_UNSIGNED_SHORT)
- {
- memcpy(output, input, count * sizeof(GLushort));
- }
- else UNREACHABLE();
-}
-
-template <class IndexType>
-static void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
-{
- *minIndex = indices[0];
- *maxIndex = indices[0];
-
- for (GLsizei i = 0; i < count; i++)
- {
- if (*minIndex > indices[i]) *minIndex = indices[i];
- if (*maxIndex < indices[i]) *maxIndex = indices[i];
- }
-}
-
-static void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
-{
- if (type == GL_UNSIGNED_BYTE)
- {
- computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex);
- }
- else if (type == GL_UNSIGNED_INT)
- {
- computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex);
- }
- else if (type == GL_UNSIGNED_SHORT)
- {
- computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex);
- }
- else UNREACHABLE();
-}
-
-GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated)
-{
- if (!mStreamingBufferShort)
- {
- return GL_OUT_OF_MEMORY;
- }
-
- GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
- unsigned int offset = 0;
- bool alignedOffset = false;
-
- BufferStorage *storage = NULL;
-
- if (buffer != NULL)
- {
- if (reinterpret_cast<uintptr_t>(indices) > std::numeric_limits<unsigned int>::max())
- {
- return GL_OUT_OF_MEMORY;
- }
- offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
-
- storage = buffer->getStorage();
-
- switch (type)
- {
- case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break;
- case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;
- case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break;
- default: UNREACHABLE(); alignedOffset = false;
- }
-
- unsigned int typeSize = gl::ComputeTypeSize(type);
-
- // check for integer overflows
- if (static_cast<unsigned int>(count) > (std::numeric_limits<unsigned int>::max() / typeSize) ||
- typeSize * static_cast<unsigned int>(count) + offset < offset)
- {
- return GL_OUT_OF_MEMORY;
- }
-
- if (typeSize * static_cast<unsigned int>(count) + offset > storage->getSize())
- {
- return GL_INVALID_OPERATION;
- }
-
- indices = static_cast<const GLubyte*>(storage->getData()) + offset;
- }
-
- StreamingIndexBufferInterface *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
-
- StaticIndexBufferInterface *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL;
- IndexBufferInterface *indexBuffer = streamingBuffer;
- bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() &&
- destinationIndexType == type;
- unsigned int streamOffset = 0;
-
- if (directStorage)
- {
- indexBuffer = streamingBuffer;
- streamOffset = offset;
- storage->markBufferUsage();
-
- if (!buffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex,
- &translated->maxIndex, NULL))
- {
- computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
- buffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
- translated->maxIndex, offset);
- }
- }
- else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset)
- {
- indexBuffer = staticBuffer;
- if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex,
- &translated->maxIndex, &streamOffset))
- {
- streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType);
- computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
- staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
- translated->maxIndex, streamOffset);
- }
- }
- else
- {
- unsigned int convertCount = count;
-
- if (staticBuffer)
- {
- if (staticBuffer->getBufferSize() == 0 && alignedOffset)
- {
- indexBuffer = staticBuffer;
- convertCount = storage->getSize() / gl::ComputeTypeSize(type);
- }
- else
- {
- buffer->invalidateStaticData();
- staticBuffer = NULL;
- }
- }
-
- if (!indexBuffer)
- {
- ERR("No valid index buffer.");
- return GL_INVALID_OPERATION;
- }
-
- unsigned int indexTypeSize = gl::ComputeTypeSize(destinationIndexType);
- if (convertCount > std::numeric_limits<unsigned int>::max() / indexTypeSize)
- {
- ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize);
- return GL_OUT_OF_MEMORY;
- }
-
- unsigned int bufferSizeRequired = convertCount * indexTypeSize;
- if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type))
- {
- ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired);
- return GL_OUT_OF_MEMORY;
- }
-
- void* output = NULL;
- if (!indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset))
- {
- ERR("Failed to map index buffer.");
- return GL_OUT_OF_MEMORY;
- }
-
- convertIndices(type, staticBuffer ? storage->getData() : indices, convertCount, output);
-
- if (!indexBuffer->unmapBuffer())
- {
- ERR("Failed to unmap index buffer.");
- return GL_OUT_OF_MEMORY;
- }
-
- computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
-
- if (staticBuffer)
- {
- streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType);
- staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
- translated->maxIndex, streamOffset);
- }
- }
-
- translated->storage = directStorage ? storage : NULL;
- translated->indexBuffer = indexBuffer->getIndexBuffer();
- translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial();
- translated->startIndex = streamOffset / gl::ComputeTypeSize(destinationIndexType);
- translated->startOffset = streamOffset;
-
- if (buffer)
- {
- buffer->promoteStaticUsage(count * gl::ComputeTypeSize(type));
- }
-
- return GL_NO_ERROR;
-}
-
-StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count)
-{
- if (count <= 65536) // 16-bit indices
- {
- const unsigned int spaceNeeded = count * sizeof(unsigned short);
-
- if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded)
- {
- delete mCountingBuffer;
- mCountingBuffer = new StaticIndexBufferInterface(mRenderer);
- mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
-
- void* mappedMemory = NULL;
- if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL))
- {
- ERR("Failed to map counting buffer.");
- return NULL;
- }
-
- unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
- for(int i = 0; i < count; i++)
- {
- data[i] = i;
- }
-
- if (!mCountingBuffer->unmapBuffer())
- {
- ERR("Failed to unmap counting buffer.");
- return NULL;
- }
- }
- }
- else if (mStreamingBufferInt) // 32-bit indices supported
- {
- const unsigned int spaceNeeded = count * sizeof(unsigned int);
-
- if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded)
- {
- delete mCountingBuffer;
- mCountingBuffer = new StaticIndexBufferInterface(mRenderer);
- mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
-
- void* mappedMemory = NULL;
- if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL))
- {
- ERR("Failed to map counting buffer.");
- return NULL;
- }
-
- unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
- for(int i = 0; i < count; i++)
- {
- data[i] = i;
- }
-
- if (!mCountingBuffer->unmapBuffer())
- {
- ERR("Failed to unmap counting buffer.");
- return NULL;
- }
- }
- }
- else
- {
- return NULL;
- }
-
- return mCountingBuffer;
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp
index 51d7f0b653..f68ac383de 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -9,17 +8,50 @@
// ranges of indices.
#include "libGLESv2/renderer/IndexRangeCache.h"
+#include "libGLESv2/formatutils.h"
+
#include "common/debug.h"
-#include "libGLESv2/utilities.h"
+
#include <tuple>
namespace rx
{
-void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx,
+template <class IndexType>
+static RangeUI ComputeTypedRange(const IndexType *indices, GLsizei count)
+{
+ unsigned int minIndex = indices[0];
+ unsigned int maxIndex = indices[0];
+
+ for (GLsizei i = 1; i < count; i++)
+ {
+ if (minIndex > indices[i]) minIndex = indices[i];
+ if (maxIndex < indices[i]) maxIndex = indices[i];
+ }
+
+ return RangeUI(minIndex, maxIndex);
+}
+
+RangeUI IndexRangeCache::ComputeRange(GLenum type, const GLvoid *indices, GLsizei count)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return ComputeTypedRange(static_cast<const GLubyte*>(indices), count);
+ case GL_UNSIGNED_INT:
+ return ComputeTypedRange(static_cast<const GLuint*>(indices), count);
+ case GL_UNSIGNED_SHORT:
+ return ComputeTypedRange(static_cast<const GLushort*>(indices), count);
+ default:
+ UNREACHABLE();
+ return RangeUI();
+ }
+}
+
+void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range,
unsigned int streamOffset)
{
- mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(minIdx, maxIdx, streamOffset);
+ mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(range, streamOffset);
}
void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size)
@@ -31,7 +63,7 @@ void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size)
while (i != mIndexRangeCache.end())
{
unsigned int rangeStart = i->second.streamOffset;
- unsigned int rangeEnd = i->second.streamOffset + (gl::ComputeTypeSize(i->first.type) * i->first.count);
+ unsigned int rangeEnd = i->second.streamOffset + (gl::GetTypeInfo(i->first.type).bytes * i->first.count);
if (invalidateEnd < rangeStart || invalidateStart > rangeEnd)
{
@@ -44,21 +76,19 @@ void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size)
}
}
-bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex,
- unsigned int *outMaxIndex, unsigned int *outStreamOffset) const
+bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count,
+ RangeUI *outRange, unsigned int *outStreamOffset) const
{
IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count));
if (i != mIndexRangeCache.end())
{
- if (outMinIndex) *outMinIndex = i->second.minIndex;
- if (outMaxIndex) *outMaxIndex = i->second.maxIndex;
+ if (outRange) *outRange = i->second.range;
if (outStreamOffset) *outStreamOffset = i->second.streamOffset;
return true;
}
else
{
- if (outMinIndex) *outMinIndex = 0;
- if (outMaxIndex) *outMaxIndex = 0;
+ if (outRange) *outRange = RangeUI(0, 0);
if (outStreamOffset) *outStreamOffset = 0;
return false;
}
@@ -89,12 +119,13 @@ bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const
}
IndexRangeCache::IndexBounds::IndexBounds()
- : minIndex(0), maxIndex(0), streamOffset(0)
+ : range(0, 0),
+ streamOffset(0)
{
}
-IndexRangeCache::IndexBounds::IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset)
- : minIndex(minIdx), maxIndex(maxIdx), streamOffset(offset)
+IndexRangeCache::IndexBounds::IndexBounds(const RangeUI &rangeIn, unsigned int offset)
+ : range(rangeIn), streamOffset(offset)
{
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h
index 56834306f2..a7d91e035b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h
@@ -11,6 +11,11 @@
#define LIBGLESV2_RENDERER_INDEXRANGECACHE_H_
#include "common/angleutils.h"
+#include "common/mathutil.h"
+
+#include "angle_gl.h"
+
+#include <map>
namespace rx
{
@@ -18,14 +23,16 @@ namespace rx
class IndexRangeCache
{
public:
- void addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx,
+ void addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range,
unsigned int streamOffset);
- bool findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex,
- unsigned int *outMaxIndex, unsigned int *outStreamOffset) const;
+ bool findRange(GLenum type, unsigned int offset, GLsizei count, RangeUI *rangeOut,
+ unsigned int *outStreamOffset) const;
void invalidateRange(unsigned int offset, unsigned int size);
void clear();
+ static RangeUI ComputeRange(GLenum type, const GLvoid *indices, GLsizei count);
+
private:
struct IndexRange
{
@@ -41,12 +48,11 @@ class IndexRangeCache
struct IndexBounds
{
- unsigned int minIndex;
- unsigned int maxIndex;
+ RangeUI range;
unsigned int streamOffset;
IndexBounds();
- IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset);
+ IndexBounds(const RangeUI &range, unsigned int offset);
};
typedef std::map<IndexRange, IndexBounds> IndexRangeMap;
@@ -55,4 +61,4 @@ class IndexRangeCache
}
-#endif LIBGLESV2_RENDERER_INDEXRANGECACHE_H
+#endif // LIBGLESV2_RENDERER_INDEXRANGECACHE_H
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h
new file mode 100644
index 0000000000..ba0955fdf8
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h
@@ -0,0 +1,58 @@
+//
+// 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 LIBGLESV2_RENDERER_PROGRAMIMPL_H_
+#define LIBGLESV2_RENDERER_PROGRAMIMPL_H_
+
+#include "common/angleutils.h"
+#include "libGLESv2/BinaryStream.h"
+#include "libGLESv2/Constants.h"
+#include "libGLESv2/ProgramBinary.h"
+
+namespace rx
+{
+
+class DynamicHLSL;
+class Renderer;
+
+class ProgramImpl
+{
+public:
+ virtual ~ProgramImpl() { }
+
+ // TODO: Temporary interfaces to ease migration. Remove soon!
+ virtual Renderer *getRenderer() = 0;
+ virtual DynamicHLSL *getDynamicHLSL() = 0;
+ virtual const std::vector<rx::PixelShaderOutputVariable> &getPixelShaderKey() = 0;
+
+ virtual GLenum getBinaryFormat() = 0;
+ virtual bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
+ virtual bool save(gl::BinaryOutputStream *stream) = 0;
+
+ virtual rx::ShaderExecutable *getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector<GLenum> &outputSignature,
+ const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
+ bool separatedOutputBuffers) = 0;
+ virtual rx::ShaderExecutable *getVertexExecutableForInputLayout(gl::InfoLog &infoLog,
+ const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
+ const sh::Attribute shaderAttributes[],
+ const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
+ bool separatedOutputBuffers) = 0;
+
+ virtual bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
+ const std::vector<std::string> &transformFeedbackVaryings, int *registers,
+ std::vector<gl::LinkedVarying> *linkedVaryings, std::map<int,
+ gl::VariableLocation> *outputVariables) = 0;
+
+ virtual void initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms) = 0;
+
+ virtual void reset() = 0;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_PROGRAMIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h
index a874047b0c..6b45810a3b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h
@@ -9,27 +9,27 @@
#ifndef LIBGLESV2_RENDERER_QUERYIMPL_H_
#define LIBGLESV2_RENDERER_QUERYIMPL_H_
+#include "libGLESv2/Error.h"
+
#include "common/angleutils.h"
+#include <GLES2/gl2.h>
+
namespace rx
{
class QueryImpl
{
public:
- explicit QueryImpl(GLenum type) : mType(type), mStatus(GL_FALSE), mResult(0) { }
+ explicit QueryImpl(GLenum type) { mType = type; }
virtual ~QueryImpl() { }
- virtual void begin() = 0;
- virtual void end() = 0;
- virtual GLuint getResult() = 0;
- virtual GLboolean isResultAvailable() = 0;
-
- GLenum getType() const { return mType; }
+ virtual gl::Error begin() = 0;
+ virtual gl::Error end() = 0;
+ virtual gl::Error getResult(GLuint *params) = 0;
+ virtual gl::Error isResultAvailable(GLuint *available) = 0;
- protected:
- GLuint mResult;
- GLboolean mStatus;
+ GLenum getType() const { return mType; }
private:
DISALLOW_COPY_AND_ASSIGN(QueryImpl);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h
index 80de39f4f7..44637ec7de 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h
@@ -11,6 +11,7 @@
#define LIBGLESV2_RENDERER_RENDERTARGET_H_
#include "common/angleutils.h"
+#include "libGLESv2/angletypes.h"
namespace rx
{
@@ -21,6 +22,7 @@ class RenderTarget
{
mWidth = 0;
mHeight = 0;
+ mDepth = 0;
mInternalFormat = GL_NONE;
mActualFormat = GL_NONE;
mSamples = 0;
@@ -28,21 +30,27 @@ class RenderTarget
virtual ~RenderTarget() {};
- GLsizei getWidth() { return mWidth; }
- GLsizei getHeight() { return mHeight; }
- GLenum getInternalFormat() { return mInternalFormat; }
- GLenum getActualFormat() { return mActualFormat; }
- GLsizei getSamples() { return mSamples; }
-
+ GLsizei getWidth() const { return mWidth; }
+ GLsizei getHeight() const { return mHeight; }
+ GLsizei getDepth() const { return mDepth; }
+ GLenum getInternalFormat() const { return mInternalFormat; }
+ GLenum getActualFormat() const { return mActualFormat; }
+ GLsizei getSamples() const { return mSamples; }
+ gl::Extents getExtents() const { return gl::Extents(mWidth, mHeight, mDepth); }
+
+ virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) = 0;
+
struct Desc {
GLsizei width;
GLsizei height;
+ GLsizei depth;
GLenum format;
};
protected:
GLsizei mWidth;
GLsizei mHeight;
+ GLsizei mDepth;
GLenum mInternalFormat;
GLenum mActualFormat;
GLsizei mSamples;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
index 5278113811..910d0285f1 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
@@ -1,222 +1,89 @@
-#include "precompiled.h"
//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
// Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances.
-#include <EGL/eglext.h>
#include "libGLESv2/main.h"
#include "libGLESv2/Program.h"
#include "libGLESv2/renderer/Renderer.h"
-#if defined(ANGLE_ENABLE_D3D9)
-# include "libGLESv2/renderer/d3d9/Renderer9.h"
-#endif
-#if defined(ANGLE_ENABLE_D3D11)
-# include "libGLESv2/renderer/d3d11/Renderer11.h"
-#endif
-#include "libGLESv2/utilities.h"
-#include "third_party/trace_event/trace_event.h"
-
-#ifndef D3DERR_OUTOFVIDEOMEMORY
-#define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380)
-#endif
-
-#if defined(__MINGW32__) || defined(ANGLE_OS_WINPHONE)
-
-#ifndef D3DCOMPILER_DLL
-
-// Add define + typedefs for older MinGW-w64 headers (pre 5783)
-
-#define D3DCOMPILER_DLL L"d3dcompiler_43.dll"
+#include "common/utilities.h"
+#include "libGLESv2/Shader.h"
-HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename,
- const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
- const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages);
-typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const char *filename,
- const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
- const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages);
+#if defined (ANGLE_ENABLE_D3D9)
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+#endif // ANGLE_ENABLE_D3D9
-#endif // D3DCOMPILER_DLL
+#if defined (ANGLE_ENABLE_D3D11)
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#endif // ANGLE_ENABLE_D3D11
-#endif // __MINGW32__ || ANGLE_OS_WINPHONE
+#if defined (ANGLE_TEST_CONFIG)
+#define ANGLE_DEFAULT_D3D11 1
+#endif
-#ifndef QT_D3DCOMPILER_DLL
-#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL
+#if !defined(ANGLE_DEFAULT_D3D11)
+// Enables use of the Direct3D 11 API for a default display, when available
+#define ANGLE_DEFAULT_D3D11 0
#endif
+#include <EGL/eglext.h>
+
namespace rx
{
-Renderer::Renderer(egl::Display *display) : mDisplay(display)
+Renderer::Renderer(egl::Display *display)
+ : mDisplay(display),
+ mCapsInitialized(false),
+ mCurrentClientVersion(2)
{
- mD3dCompilerModule = NULL;
- mD3DCompileFunc = NULL;
}
Renderer::~Renderer()
{
- if (mD3dCompilerModule)
- {
- FreeLibrary(mD3dCompilerModule);
- mD3dCompilerModule = NULL;
- }
}
-bool Renderer::initializeCompiler()
+const gl::Caps &Renderer::getRendererCaps() const
{
- TRACE_EVENT0("gpu", "initializeCompiler");
-#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
- // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
- static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
-
- for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i)
- {
- if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3dCompilerModule))
- {
- break;
- }
- }
-#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
-
- // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL
-#if !defined(ANGLE_OS_WINRT)
- const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL");
- if (!defaultCompiler)
- defaultCompiler = QT_D3DCOMPILER_DLL;
-#else // !ANGLE_OS_WINRT
-# ifdef _DEBUG
- const wchar_t *defaultCompiler = L"d3dcompiler_qtd.dll";
-# else
- const wchar_t *defaultCompiler = L"d3dcompiler_qt.dll";
-# endif
-#endif // ANGLE_OS_WINRT
-
- const wchar_t *compilerDlls[] = {
- defaultCompiler,
- L"d3dcompiler_47.dll",
- L"d3dcompiler_46.dll",
- L"d3dcompiler_45.dll",
- L"d3dcompiler_44.dll",
- L"d3dcompiler_43.dll",
- 0
- };
-
- // Load the first available known compiler DLL
- for (int i = 0; compilerDlls[i]; ++i)
- {
- // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
- mD3dCompilerModule = LoadLibrary(compilerDlls[i]);
- if (mD3dCompilerModule)
- break;
- }
-
- if (!mD3dCompilerModule)
+ if (!mCapsInitialized)
{
- ERR("No D3D compiler module found - aborting!\n");
- return false;
+ generateCaps(&mCaps, &mTextureCaps, &mExtensions);
+ mCapsInitialized = true;
}
- mD3DCompileFunc = reinterpret_cast<pCompileFunc>(GetProcAddress(mD3dCompilerModule, "D3DCompile"));
- ASSERT(mD3DCompileFunc);
-
- return mD3DCompileFunc != NULL;
+ return mCaps;
}
-// Compiles HLSL code into executable binaries
-ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags)
+const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const
{
- if (!hlsl)
+ if (!mCapsInitialized)
{
- return NULL;
+ generateCaps(&mCaps, &mTextureCaps, &mExtensions);
+ mCapsInitialized = true;
}
- HRESULT result = S_OK;
- UINT flags = 0;
- std::string sourceText;
- if (gl::perfActive())
- {
- flags |= D3DCOMPILE_DEBUG;
-
-#ifdef NDEBUG
- flags |= optimizationFlags;
-#else
- flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
-#endif
+ return mTextureCaps;
+}
- std::string sourcePath = getTempPath();
- sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
- writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
- }
- else
+const gl::Extensions &Renderer::getRendererExtensions() const
+{
+ if (!mCapsInitialized)
{
- flags |= optimizationFlags;
- sourceText = hlsl;
+ generateCaps(&mCaps, &mTextureCaps, &mExtensions);
+ mCapsInitialized = true;
}
- // 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.
- const static UINT extraFlags[] =
- {
- 0,
- D3DCOMPILE_AVOID_FLOW_CONTROL,
- D3DCOMPILE_PREFER_FLOW_CONTROL
- };
-
- const static char * const extraFlagNames[] =
- {
- "default",
- "avoid flow control",
- "prefer flow control"
- };
-
- int attempts = alternateFlags ? ArraySize(extraFlags) : 1;
- pD3DCompile compileFunc = reinterpret_cast<pD3DCompile>(mD3DCompileFunc);
- for (int i = 0; i < attempts; ++i)
- {
- ID3DBlob *errorMessage = NULL;
- ID3DBlob *binary = NULL;
-
- result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL,
- "main", profile, flags | extraFlags[i], 0, &binary, &errorMessage);
- if (errorMessage)
- {
- const char *message = (const char*)errorMessage->GetBufferPointer();
-
- infoLog.appendSanitized(message);
- TRACE("\n%s", hlsl);
- TRACE("\n%s", message);
-
- errorMessage->Release();
- errorMessage = NULL;
- }
-
- if (SUCCEEDED(result))
- {
- return (ShaderBlob*)binary;
- }
- else
- {
- if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
- {
- return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*) NULL);
- }
+ return mExtensions;
+}
- infoLog.append("Warning: D3D shader compilation failed with ");
- infoLog.append(extraFlagNames[i]);
- infoLog.append(" flags.");
- if (i + 1 < attempts)
- {
- infoLog.append(" Retrying with ");
- infoLog.append(extraFlagNames[i + 1]);
- infoLog.append(".\n");
- }
- }
- }
+typedef Renderer *(*CreateRendererFunction)(egl::Display*, EGLNativeDisplayType, EGLint);
- return NULL;
+template <typename RendererType>
+Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType)
+{
+ return new RendererType(display, nativeDisplay, requestedDisplayType);
}
}
@@ -224,56 +91,64 @@ ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, co
extern "C"
{
-rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType displayId)
+rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType)
{
- rx::Renderer *renderer = NULL;
- EGLint status = EGL_BAD_ALLOC;
+ std::vector<rx::CreateRendererFunction> rendererCreationFunctions;
-#if defined(ANGLE_OS_WINRT)
- if (displayId == EGL_DEFAULT_DISPLAY)
- displayId = EGL_D3D11_ONLY_DISPLAY_ANGLE;
-#endif
-
-#if defined(ANGLE_ENABLE_D3D11)
- if (displayId == EGL_DEFAULT_DISPLAY ||
- displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
- displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE)
- {
- renderer = new rx::Renderer11(display);
-
- if (renderer)
+# 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 ||
+ requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE)
{
- status = renderer->initialize();
+ rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer11>);
}
+# endif
- if (status == EGL_SUCCESS)
+# if defined(ANGLE_ENABLE_D3D9)
+ if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+ requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
{
- return renderer;
+ rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer9>);
}
- else if (displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE)
- {
- return NULL;
- }
-
- // Failed to create a D3D11 renderer, try creating a D3D9 renderer
- delete renderer;
- }
-#endif // ANGLE_ENABLE_D3D11
-
-#if defined(ANGLE_ENABLE_D3D9)
- bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE);
- renderer = new rx::Renderer9(display, displayId, softwareDevice);
+# endif
- if (renderer)
+ if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
+ nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
+ requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
{
- status = renderer->initialize();
+ // 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(rx::CreateRenderer<rx::Renderer11>);
+# endif
+# if defined(ANGLE_ENABLE_D3D9)
+ rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer9>);
+# endif
+# else
+# if defined(ANGLE_ENABLE_D3D9)
+ rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer9>);
+# endif
+# if defined(ANGLE_ENABLE_D3D11)
+ rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer11>);
+# endif
+# endif
}
- if (status == EGL_SUCCESS)
+ for (size_t i = 0; i < rendererCreationFunctions.size(); i++)
{
- return renderer;
+ rx::Renderer *renderer = rendererCreationFunctions[i](display, nativeDisplay, requestedDisplayType);
+ if (renderer->initialize() == EGL_SUCCESS)
+ {
+ return renderer;
+ }
+ else
+ {
+ // Failed to create the renderer, try the next
+ SafeDelete(renderer);
+ }
}
-#endif // ANGLE_ENABLE_D3D9
return NULL;
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
index 79578b2458..b2249741ab 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
@@ -1,6 +1,5 @@
-#include "../precompiled.h"
//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -13,23 +12,18 @@
#include "libGLESv2/Uniform.h"
#include "libGLESv2/angletypes.h"
+#include "libGLESv2/Caps.h"
+#include "libGLESv2/Error.h"
-#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
-#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
-#endif
+#include <cstdint>
-const int versionWindowsVista = MAKEWORD(0x00, 0x06);
-const int versionWindows7 = MAKEWORD(0x01, 0x06);
+#include <EGL/egl.h>
-// Return the version of the operating system in a format suitable for ordering
-// comparison.
-inline int getComparableOSVersion()
-{
- DWORD version = GetVersion();
- int majorVersion = LOBYTE(LOWORD(version));
- int minorVersion = HIBYTE(LOWORD(version));
- return MAKEWORD(minorVersion, majorVersion);
-}
+#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
namespace egl
{
@@ -40,31 +34,35 @@ namespace gl
{
class InfoLog;
class ProgramBinary;
-class VertexAttribute;
+struct LinkedVarying;
+struct VertexAttribute;
class Buffer;
class Texture;
class Framebuffer;
+struct VertexAttribCurrentValueData;
}
namespace rx
{
-class TextureStorageInterface2D;
-class TextureStorageInterfaceCube;
+class TextureStorage;
class VertexBuffer;
class IndexBuffer;
class QueryImpl;
class FenceImpl;
+class BufferImpl;
+class VertexArrayImpl;
class BufferStorage;
-class Blit;
struct TranslatedIndexData;
+class ShaderImpl;
+class ProgramImpl;
class ShaderExecutable;
class SwapChain;
class RenderTarget;
class Image;
class TextureStorage;
-
-typedef void * ShaderBlob;
-typedef void (*pCompileFunc)();
+class UniformStorage;
+class TextureImpl;
+class TransformFeedbackImpl;
struct ConfigDesc
{
@@ -72,6 +70,7 @@ struct ConfigDesc
GLenum depthStencilFormat;
GLint multiSample;
bool fastConfig;
+ bool es3Capable;
};
struct dx_VertexConstants
@@ -94,12 +93,6 @@ enum ShaderType
SHADER_GEOMETRY
};
-enum D3DWorkaroundType
-{
- ANGLE_D3D_WORKAROUND_NONE,
- ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER
-};
-
class Renderer
{
public:
@@ -116,30 +109,37 @@ class Renderer
virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
- virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0;
- virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0;
+ virtual gl::Error generateSwizzle(gl::Texture *texture) = 0;
+ virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0;
+ virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0;
+
+ virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) = 0;
- virtual void setRasterizerState(const gl::RasterizerState &rasterState) = 0;
- virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor,
- unsigned int sampleMask) = 0;
- virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
- int stencilBackRef, bool frontFaceCCW) = 0;
+ virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0;
+ virtual gl::Error setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
+ unsigned int sampleMask) = 0;
+ virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
+ int stencilBackRef, bool frontFaceCCW) = 0;
virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0;
- virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
+ virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
bool ignoreViewport) = 0;
- virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0;
- virtual void applyShaders(gl::ProgramBinary *programBinary) = 0;
- virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) = 0;
+ virtual gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer) = 0;
+ virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
+ bool rasterizerDiscard, bool transformFeedbackActive) = 0;
+ virtual gl::Error applyUniforms(const gl::ProgramBinary &programBinary) = 0;
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
- virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) = 0;
- virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0;
+ virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[],
+ GLint first, GLsizei count, GLsizei instances) = 0;
+ virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0;
+ virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) = 0;
- virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances) = 0;
- virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0;
+ virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0;
+ virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
+ gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0;
- virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) = 0;
+ virtual gl::Error clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) = 0;
virtual void markAllStateDirty() = 0;
@@ -149,102 +149,119 @@ class Renderer
virtual bool testDeviceLost(bool notify) = 0;
virtual bool testDeviceResettable() = 0;
- // Renderer capabilities
+ // Renderer capabilities (virtual because it is used by egl::Display, do not override)
+ virtual const gl::Caps &getRendererCaps() const;
+ virtual const gl::TextureCapsMap &getRendererTextureCaps() const;
+ virtual const gl::Extensions &getRendererExtensions() const;
+
virtual DWORD getAdapterVendor() const = 0;
virtual std::string getRendererDescription() const = 0;
virtual GUID getAdapterIdentifier() const = 0;
- virtual bool getBGRATextureSupport() const = 0;
- virtual bool getDXT1TextureSupport() = 0;
- virtual bool getDXT3TextureSupport() = 0;
- virtual bool getDXT5TextureSupport() = 0;
- virtual bool getEventQuerySupport() = 0;
- virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable) = 0;
- virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable) = 0;
- virtual bool getLuminanceTextureSupport() = 0;
- virtual bool getLuminanceAlphaTextureSupport() = 0;
- bool getVertexTextureSupport() const { return getMaxVertexTextureImageUnits() > 0; }
- virtual unsigned int getMaxVertexTextureImageUnits() const = 0;
- virtual unsigned int getMaxCombinedTextureImageUnits() const = 0;
virtual unsigned int getReservedVertexUniformVectors() const = 0;
virtual unsigned int getReservedFragmentUniformVectors() const = 0;
- virtual unsigned int getMaxVertexUniformVectors() const = 0;
- virtual unsigned int getMaxFragmentUniformVectors() const = 0;
- virtual unsigned int getMaxVaryingVectors() const = 0;
- virtual bool getNonPower2TextureSupport() const = 0;
- virtual bool getDepthTextureSupport() const = 0;
- virtual bool getOcclusionQuerySupport() const = 0;
- virtual bool getInstancingSupport() const = 0;
- virtual bool getTextureFilterAnisotropySupport() const = 0;
- virtual float getTextureMaxAnisotropy() const = 0;
+ virtual unsigned int getReservedVertexUniformBuffers() const = 0;
+ virtual unsigned int getReservedFragmentUniformBuffers() const = 0;
virtual bool getShareHandleSupport() const = 0;
- virtual bool getDerivativeInstructionSupport() const = 0;
virtual bool getPostSubBufferSupport() const = 0;
virtual int getMajorShaderModel() const = 0;
- virtual float getMaxPointSize() const = 0;
- virtual int getMaxViewportDimension() const = 0;
- virtual int getMaxTextureWidth() const = 0;
- virtual int getMaxTextureHeight() const = 0;
- virtual bool get32BitIndexSupport() const = 0;
virtual int getMinSwapInterval() const = 0;
virtual int getMaxSwapInterval() const = 0;
- virtual GLsizei getMaxSupportedSamples() const = 0;
-
- virtual unsigned int getMaxRenderTargets() const = 0;
-
// Pixel operations
- virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) = 0;
- virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) = 0;
-
- virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) = 0;
- virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) = 0;
+ virtual bool copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source) = 0;
+ virtual bool copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source) = 0;
+ virtual bool copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source) = 0;
+ virtual bool copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source) = 0;
+
+ virtual bool copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) = 0;
+ virtual bool copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) = 0;
+ virtual bool copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0;
+ virtual bool copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0;
virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
- bool blitRenderTarget, bool blitDepthStencil) = 0;
- virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
- GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) = 0;
+ const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) = 0;
+
+ virtual gl::Error readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+ GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) = 0;
// RenderTarget creation
virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth) = 0;
- virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) = 0;
+ virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples) = 0;
+
+ // Shader creation
+ virtual ShaderImpl *createShader(GLenum type) = 0;
+ virtual ProgramImpl *createProgram() = 0;
// Shader operations
- virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type) = 0;
- virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) = 0;
+ virtual void releaseShaderCompiler() = 0;
+ virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
+ const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+ bool separatedOutputBuffers) = 0;
+ virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
+ const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+ bool separatedOutputBuffers, D3DWorkaroundType workaround) = 0;
+ virtual UniformStorage *createUniformStorage(size_t storageSize) = 0;
// Image operations
virtual Image *createImage() = 0;
virtual void generateMipmap(Image *dest, Image *source) = 0;
virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0;
- virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) = 0;
- virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) = 0;
+ virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) = 0;
+ virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) = 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;
+
+ // Texture creation
+ virtual TextureImpl *createTexture(GLenum target) = 0;
// Buffer creation
+ virtual BufferImpl *createBuffer() = 0;
virtual VertexBuffer *createVertexBuffer() = 0;
virtual IndexBuffer *createIndexBuffer() = 0;
- virtual BufferStorage *createBufferStorage() = 0;
+
+ // Vertex Array creation
+ virtual VertexArrayImpl *createVertexArray() = 0;
// Query and Fence creation
virtual QueryImpl *createQuery(GLenum type) = 0;
virtual FenceImpl *createFence() = 0;
+ // Transform Feedback creation
+ virtual TransformFeedbackImpl* createTransformFeedback() = 0;
+
+ // Current GLES client version
+ void setCurrentClientVersion(int clientVersion) { mCurrentClientVersion = clientVersion; }
+ int getCurrentClientVersion() const { return mCurrentClientVersion; }
+
+ // Buffer-to-texture and Texture-to-buffer copies
+ virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0;
+ virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+ GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0;
+
virtual bool getLUID(LUID *adapterLuid) const = 0;
+ virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0;
+ virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0;
protected:
- bool initializeCompiler();
- ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags);
-
egl::Display *mDisplay;
private:
DISALLOW_COPY_AND_ASSIGN(Renderer);
- HMODULE mD3dCompilerModule;
- pCompileFunc mD3DCompileFunc;
+ virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0;
+
+ mutable bool mCapsInitialized;
+ mutable gl::Caps mCaps;
+ mutable gl::TextureCapsMap mTextureCaps;
+ mutable gl::Extensions mExtensions;
+
+ int mCurrentClientVersion;
};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h
index 293e340845..f17195673d 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h
@@ -11,6 +11,10 @@
#define LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_
#include "common/angleutils.h"
+#include "common/debug.h"
+
+#include <vector>
+#include <cstdint>
namespace rx
{
@@ -18,32 +22,44 @@ namespace rx
class ShaderExecutable
{
public:
- ShaderExecutable(const void *function, size_t length) : mLength(length)
- {
- mFunction = new char[length];
- memcpy(mFunction, function, length);
- }
-
- virtual ~ShaderExecutable()
+ ShaderExecutable(const void *function, size_t length)
+ : mFunctionBuffer(length)
{
- delete[] mFunction;
+ memcpy(mFunctionBuffer.data(), function, length);
}
- void *getFunction() const
+ virtual ~ShaderExecutable() {}
+
+ const uint8_t *getFunction() const
{
- return mFunction;
+ return mFunctionBuffer.data();
}
size_t getLength() const
{
- return mLength;
+ return mFunctionBuffer.size();
}
private:
DISALLOW_COPY_AND_ASSIGN(ShaderExecutable);
- void *mFunction;
- const size_t mLength;
+ std::vector<uint8_t> mFunctionBuffer;
+};
+
+class UniformStorage
+{
+ public:
+ UniformStorage(size_t initialSize)
+ : mSize(initialSize)
+ {
+ }
+
+ virtual ~UniformStorage() {}
+
+ size_t size() const { return mSize; }
+
+ private:
+ size_t mSize;
};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h
new file mode 100644
index 0000000000..de5d30e6fe
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.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.
+//
+
+// ShaderImpl.h: Defines the abstract rx::ShaderImpl class.
+
+#ifndef LIBGLESV2_RENDERER_SHADERIMPL_H_
+#define LIBGLESV2_RENDERER_SHADERIMPL_H_
+
+#include <vector>
+
+#include "common/angleutils.h"
+#include "libGLESv2/Shader.h"
+
+namespace rx
+{
+
+class ShaderImpl
+{
+ public:
+ ShaderImpl() { }
+ virtual ~ShaderImpl() { }
+
+ virtual bool compile(const std::string &source) = 0;
+ virtual const std::string &getInfoLog() const = 0;
+ virtual const std::string &getTranslatedSource() const = 0;
+
+ const std::vector<gl::PackedVarying> &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::Attribute> &getActiveOutputVariables() const { return mActiveOutputVariables; }
+
+ std::vector<gl::PackedVarying> &getVaryings() { return mVaryings; }
+ std::vector<sh::Uniform> &getUniforms() { return mUniforms; }
+ std::vector<sh::InterfaceBlock> &getInterfaceBlocks() { return mInterfaceBlocks; }
+ std::vector<sh::Attribute> &getActiveAttributes() { return mActiveAttributes; }
+ std::vector<sh::Attribute> &getActiveOutputVariables() { return mActiveOutputVariables; }
+
+ protected:
+ DISALLOW_COPY_AND_ASSIGN(ShaderImpl);
+
+ std::vector<gl::PackedVarying> mVaryings;
+ std::vector<sh::Uniform> mUniforms;
+ std::vector<sh::InterfaceBlock> mInterfaceBlocks;
+ std::vector<sh::Attribute> mActiveAttributes;
+ std::vector<sh::Attribute> mActiveOutputVariables;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_SHADERIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
index 8231fbcb25..1ec702f299 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
@@ -1,4 +1,3 @@
-#include "../precompiled.h"
//
// 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
@@ -12,14 +11,23 @@
#define LIBGLESV2_RENDERER_SWAPCHAIN_H_
#include "common/angleutils.h"
+#include "common/platform.h"
-#if !defined(ANGLE_FORCE_VSYNC_OFF)
-#define ANGLE_FORCE_VSYNC_OFF 0
-#endif
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+#include <EGL/eglplatform.h>
namespace rx
{
+enum SwapFlags
+{
+ SWAP_NORMAL = 0,
+ SWAP_ROTATE_90 = 1,
+ SWAP_ROTATE_270 = 2,
+ SWAP_ROTATE_180 = SWAP_ROTATE_90|SWAP_ROTATE_270,
+};
+
class SwapChain
{
public:
@@ -32,13 +40,13 @@ class SwapChain
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 EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags) = 0;
virtual void recreate() = 0;
virtual HANDLE getShareHandle() {return mShareHandle;};
protected:
- const EGLNativeWindowType mWindow; // Window that the surface is created for.
+ const EGLNativeWindowType mWindow; // Window that the surface is created for.
const GLenum mBackBufferFormat;
const GLenum mDepthBufferFormat;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h
new file mode 100644
index 0000000000..e3cc50d680
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h
@@ -0,0 +1,70 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureImpl.h: Defines the abstract rx::TextureImpl classes.
+
+#ifndef LIBGLESV2_RENDERER_TEXTUREIMPL_H_
+#define LIBGLESV2_RENDERER_TEXTUREIMPL_H_
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+#include "libGLESv2/ImageIndex.h"
+
+namespace egl
+{
+class Surface;
+}
+
+namespace gl
+{
+class Framebuffer;
+struct PixelUnpackState;
+struct SamplerState;
+}
+
+namespace rx
+{
+
+class Image;
+class Renderer;
+class TextureStorage;
+
+class TextureImpl
+{
+ public:
+ virtual ~TextureImpl() {};
+
+ // TODO: If this methods could go away that would be ideal;
+ // TextureStorage should only be necessary for the D3D backend, and as such
+ // higher level code should not rely on it.
+ virtual TextureStorage *getNativeTexture() = 0;
+
+ // Deprecated in favour of the ImageIndex method
+ virtual Image *getImage(int level, int layer) const = 0;
+ virtual Image *getImage(const gl::ImageIndex &index) const = 0;
+ virtual GLsizei getLayerCount(int level) const = 0;
+
+ virtual void setUsage(GLenum usage) = 0;
+
+ virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
+ virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) = 0;
+ virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
+ virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) = 0;
+ virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
+ virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
+ virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0;
+
+ virtual void generateMipmaps() = 0;
+
+ virtual void bindTexImage(egl::Surface *surface) = 0;
+ virtual void releaseTexImage() = 0;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_TEXTUREIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp
deleted file mode 100644
index 00b316f1cc..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-#include "precompiled.h"
-//
-// 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.
-//
-
-// TextureStorage.cpp: Implements the abstract rx::TextureStorageInterface class and its concrete derived
-// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the
-// GPU-side texture.
-
-#include "libGLESv2/renderer/TextureStorage.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/Texture.h"
-
-#include "common/debug.h"
-
-namespace rx
-{
-unsigned int TextureStorageInterface::mCurrentTextureSerial = 1;
-
-TextureStorageInterface::TextureStorageInterface()
- : mTextureSerial(issueTextureSerial()),
- mInstance(NULL)
-{
-}
-
-TextureStorageInterface::~TextureStorageInterface()
-{
- delete mInstance;
-}
-
-bool TextureStorageInterface::isRenderTarget() const
-{
- return mInstance->isRenderTarget();
-}
-
-
-bool TextureStorageInterface::isManaged() const
-{
- return mInstance->isManaged();
-}
-
-unsigned int TextureStorageInterface::getTextureSerial() const
-{
- return mTextureSerial;
-}
-
-unsigned int TextureStorageInterface::issueTextureSerial()
-{
- return mCurrentTextureSerial++;
-}
-
-int TextureStorageInterface::getLodOffset() const
-{
- return mInstance->getLodOffset();
-}
-
-
-int TextureStorageInterface::levelCount()
-{
- return mInstance->levelCount();
-}
-
-TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain)
- : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial())
-{
- mInstance = renderer->createTextureStorage2D(swapchain);
-}
-
-TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
- : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial())
-{
- mInstance = renderer->createTextureStorage2D(levels, internalformat, usage, forceRenderable, width, height);
-}
-
-TextureStorageInterface2D::~TextureStorageInterface2D()
-{
-}
-
-RenderTarget *TextureStorageInterface2D::getRenderTarget() const
-{
- return mInstance->getRenderTarget();
-}
-
-void TextureStorageInterface2D::generateMipmap(int level)
-{
- mInstance->generateMipmap(level);
-}
-
-unsigned int TextureStorageInterface2D::getRenderTargetSerial(GLenum target) const
-{
- return mRenderTargetSerial;
-}
-
-TextureStorageInterfaceCube::TextureStorageInterfaceCube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
- : mFirstRenderTargetSerial(gl::RenderbufferStorage::issueCubeSerials())
-{
- mInstance = renderer->createTextureStorageCube(levels, internalformat, usage, forceRenderable, size);
-}
-
-TextureStorageInterfaceCube::~TextureStorageInterfaceCube()
-{
-}
-
-RenderTarget *TextureStorageInterfaceCube::getRenderTarget(GLenum faceTarget) const
-{
- return mInstance->getRenderTarget(faceTarget);
-}
-
-void TextureStorageInterfaceCube::generateMipmap(int face, int level)
-{
- mInstance->generateMipmap(face, level);
-}
-
-unsigned int TextureStorageInterfaceCube::getRenderTargetSerial(GLenum target) const
-{
- return mFirstRenderTargetSerial + gl::TextureCubeMap::faceIndex(target);
-}
-
-} \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h
deleted file mode 100644
index edddb75f3f..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h
+++ /dev/null
@@ -1,110 +0,0 @@
-//
-// 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.
-//
-
-// TextureStorage.h: Defines the abstract rx::TextureStorageInterface class and its concrete derived
-// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the
-// GPU-side texture.
-
-#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
-#define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
-
-#include "common/debug.h"
-
-namespace rx
-{
-class Renderer;
-class SwapChain;
-class RenderTarget;
-class Blit;
-
-class TextureStorage
-{
- public:
- TextureStorage() {};
- virtual ~TextureStorage() {};
-
- virtual int getLodOffset() const = 0;
- virtual bool isRenderTarget() const = 0;
- virtual bool isManaged() const = 0;
- virtual int levelCount() = 0;
-
- virtual RenderTarget *getRenderTarget() = 0;
- virtual RenderTarget *getRenderTarget(GLenum faceTarget) = 0;
- virtual void generateMipmap(int level) = 0;
- virtual void generateMipmap(int face, int level) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage);
-
-};
-
-class TextureStorageInterface
-{
- public:
- TextureStorageInterface();
- virtual ~TextureStorageInterface();
-
- TextureStorage *getStorageInstance() { return mInstance; }
-
- unsigned int getTextureSerial() const;
- virtual unsigned int getRenderTargetSerial(GLenum target) const = 0;
-
- virtual int getLodOffset() const;
- virtual bool isRenderTarget() const;
- virtual bool isManaged() const;
- virtual int levelCount();
-
- protected:
- TextureStorage *mInstance;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface);
-
- const unsigned int mTextureSerial;
- static unsigned int issueTextureSerial();
-
- static unsigned int mCurrentTextureSerial;
-};
-
-class TextureStorageInterface2D : public TextureStorageInterface
-{
- public:
- TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain);
- TextureStorageInterface2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
- virtual ~TextureStorageInterface2D();
-
- void generateMipmap(int level);
- RenderTarget *getRenderTarget() const;
-
- virtual unsigned int getRenderTargetSerial(GLenum target) const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface2D);
-
- const unsigned int mRenderTargetSerial;
-};
-
-class TextureStorageInterfaceCube : public TextureStorageInterface
-{
- public:
- TextureStorageInterfaceCube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
- virtual ~TextureStorageInterfaceCube();
-
- void generateMipmap(int face, int level);
- RenderTarget *getRenderTarget(GLenum faceTarget) const;
-
- virtual unsigned int getRenderTargetSerial(GLenum target) const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorageInterfaceCube);
-
- const unsigned int mFirstRenderTargetSerial;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
-
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h
new file mode 100644
index 0000000000..8425604d87
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.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.
+//
+
+// TransformFeedbackImpl.h: Defines the abstract rx::TransformFeedbackImpl class.
+
+#ifndef LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_
+#define LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_
+
+#include "common/angleutils.h"
+#include "libGLESv2/TransformFeedback.h"
+
+namespace rx
+{
+
+class TransformFeedbackImpl
+{
+ public:
+ virtual ~TransformFeedbackImpl() { }
+
+ virtual void begin(GLenum primitiveMode) = 0;
+ virtual void end() = 0;
+ virtual void pause() = 0;
+ virtual void resume() = 0;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h
new file mode 100644
index 0000000000..b013f9cdf4
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexAttribImpl.h: Defines the abstract rx::VertexAttribImpl class.
+
+#ifndef LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_
+#define LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_
+
+#include "common/angleutils.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/VertexAttribute.h"
+
+namespace rx
+{
+
+class VertexArrayImpl
+{
+ public:
+ virtual ~VertexArrayImpl() { }
+
+ virtual void setElementArrayBuffer(const gl::Buffer *buffer) = 0;
+ virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) = 0;
+ virtual void setAttributeDivisor(size_t idx, GLuint divisor) = 0;
+ virtual void enableAttribute(size_t idx, bool enabledState) = 0;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp
deleted file mode 100644
index a073d95033..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp
+++ /dev/null
@@ -1,292 +0,0 @@
-#include "precompiled.h"
-//
-// 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 "libGLESv2/renderer/VertexBuffer.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/Context.h"
-
-namespace rx
-{
-
-unsigned int VertexBuffer::mNextSerial = 1;
-
-VertexBuffer::VertexBuffer()
-{
- updateSerial();
-}
-
-VertexBuffer::~VertexBuffer()
-{
-}
-
-void VertexBuffer::updateSerial()
-{
- mSerial = mNextSerial++;
-}
-
-unsigned int VertexBuffer::getSerial() const
-{
- return mSerial;
-}
-
-VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer)
-{
- mDynamic = dynamic;
- mWritePosition = 0;
- mReservedSpace = 0;
-
- mVertexBuffer = renderer->createVertexBuffer();
-}
-
-VertexBufferInterface::~VertexBufferInterface()
-{
- delete mVertexBuffer;
-}
-
-unsigned int VertexBufferInterface::getSerial() const
-{
- return mVertexBuffer->getSerial();
-}
-
-unsigned int VertexBufferInterface::getBufferSize() const
-{
- return mVertexBuffer->getBufferSize();
-}
-
-bool VertexBufferInterface::setBufferSize(unsigned int size)
-{
- if (mVertexBuffer->getBufferSize() == 0)
- {
- return mVertexBuffer->initialize(size, mDynamic);
- }
- else
- {
- return mVertexBuffer->setBufferSize(size);
- }
-}
-
-unsigned int VertexBufferInterface::getWritePosition() const
-{
- return mWritePosition;
-}
-
-void VertexBufferInterface::setWritePosition(unsigned int writePosition)
-{
- mWritePosition = writePosition;
-}
-
-bool VertexBufferInterface::discard()
-{
- return mVertexBuffer->discard();
-}
-
-bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
- unsigned int *outStreamOffset)
-{
- unsigned int spaceRequired;
- if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired))
- {
- return false;
- }
-
- if (mWritePosition + spaceRequired < mWritePosition)
- {
- return false;
- }
-
- if (!reserveSpace(mReservedSpace))
- {
- return false;
- }
- mReservedSpace = 0;
-
- if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition))
- {
- return false;
- }
-
- if (outStreamOffset)
- {
- *outStreamOffset = mWritePosition;
- }
-
- mWritePosition += spaceRequired;
-
- return true;
-}
-
-bool VertexBufferInterface::storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset)
-{
- if (mWritePosition + size < mWritePosition)
- {
- return false;
- }
-
- if (!reserveSpace(mReservedSpace))
- {
- return false;
- }
- mReservedSpace = 0;
-
- if (!mVertexBuffer->storeRawData(data, size, mWritePosition))
- {
- return false;
- }
-
- if (outStreamOffset)
- {
- *outStreamOffset = mWritePosition;
- }
-
- mWritePosition += size;
-
- return true;
-}
-
-bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances)
-{
- unsigned int requiredSpace;
- if (!mVertexBuffer->getSpaceRequired(attribute, count, instances, &requiredSpace))
- {
- return false;
- }
-
- // Protect against integer overflow
- if (mReservedSpace + requiredSpace < mReservedSpace)
- {
- return false;
- }
-
- mReservedSpace += requiredSpace;
- return true;
-}
-
-bool VertexBufferInterface::reserveRawDataSpace(unsigned int size)
-{
- // Protect against integer overflow
- if (mReservedSpace + size < mReservedSpace)
- {
- return false;
- }
-
- mReservedSpace += size;
- return true;
-}
-
-VertexBuffer* VertexBufferInterface::getVertexBuffer() const
-{
- return mVertexBuffer;
-}
-
-
-StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true)
-{
- setBufferSize(initialSize);
-}
-
-StreamingVertexBufferInterface::~StreamingVertexBufferInterface()
-{
-}
-
-bool StreamingVertexBufferInterface::reserveSpace(unsigned int size)
-{
- bool result = true;
- unsigned int curBufferSize = getBufferSize();
- if (size > curBufferSize)
- {
- result = setBufferSize(std::max(size, 3 * curBufferSize / 2));
- setWritePosition(0);
- }
- else if (getWritePosition() + size > curBufferSize)
- {
- if (!discard())
- {
- return false;
- }
- setWritePosition(0);
- }
-
- return result;
-}
-
-StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false)
-{
-}
-
-StaticVertexBufferInterface::~StaticVertexBufferInterface()
-{
-}
-
-bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset)
-{
- for (unsigned int element = 0; element < mCache.size(); element++)
- {
- if (mCache[element].type == attribute.mType &&
- mCache[element].size == attribute.mSize &&
- mCache[element].stride == attribute.stride() &&
- mCache[element].normalized == attribute.mNormalized)
- {
- if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride())
- {
- if (outStreamOffset)
- {
- *outStreamOffset = mCache[element].streamOffset;
- }
- return true;
- }
- }
- }
-
- return false;
-}
-
-bool StaticVertexBufferInterface::reserveSpace(unsigned int size)
-{
- unsigned int curSize = getBufferSize();
- if (curSize == 0)
- {
- setBufferSize(size);
- return true;
- }
- else if (curSize >= size)
- {
- return true;
- }
- else
- {
- UNREACHABLE(); // Static vertex buffers can't be resized
- return false;
- }
-}
-
-bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
- unsigned int *outStreamOffset)
-{
- unsigned int streamOffset;
- if (VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances, &streamOffset))
- {
- int attributeOffset = attrib.mOffset % attrib.stride();
- VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, streamOffset };
- mCache.push_back(element);
-
- if (outStreamOffset)
- {
- *outStreamOffset = streamOffset;
- }
-
- return true;
- }
- else
- {
- return false;
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp
deleted file mode 100644
index 8034aed8c9..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp
+++ /dev/null
@@ -1,304 +0,0 @@
-#include "precompiled.h"
-//
-// 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 "libGLESv2/renderer/VertexDataManager.h"
-#include "libGLESv2/renderer/BufferStorage.h"
-
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/renderer/VertexBuffer.h"
-
-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 };
-}
-
-namespace rx
-{
-
-static int elementsInBuffer(const gl::VertexAttribute &attribute, 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 = attribute.stride();
- return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride;
-}
-
-static int StreamingBufferElementCount(const gl::VertexAttribute &attribute, int vertexDrawCount, int instanceDrawCount)
-{
- // 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 (instanceDrawCount > 0 && attribute.mDivisor > 0)
- {
- return instanceDrawCount / attribute.mDivisor;
- }
-
- return vertexDrawCount;
-}
-
-VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer)
-{
- for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
- {
- mCurrentValue[i][0] = std::numeric_limits<float>::quiet_NaN();
- mCurrentValue[i][1] = std::numeric_limits<float>::quiet_NaN();
- mCurrentValue[i][2] = std::numeric_limits<float>::quiet_NaN();
- mCurrentValue[i][3] = std::numeric_limits<float>::quiet_NaN();
- mCurrentValueBuffer[i] = NULL;
- mCurrentValueOffsets[i] = 0;
- }
-
- mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE);
-
- if (!mStreamingBuffer)
- {
- ERR("Failed to allocate the streaming vertex buffer.");
- }
-}
-
-VertexDataManager::~VertexDataManager()
-{
- delete mStreamingBuffer;
-
- for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
- {
- delete mCurrentValueBuffer[i];
- }
-}
-
-static bool directStoragePossible(VertexBufferInterface* vb, const gl::VertexAttribute& attrib)
-{
- gl::Buffer *buffer = attrib.mBoundBuffer.get();
- BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
-
- const bool isAligned = (attrib.stride() % 4 == 0) && (attrib.mOffset % 4 == 0);
-
- return storage && storage->supportsDirectBinding() && !vb->getVertexBuffer()->requiresConversion(attrib) && isAligned;
-}
-
-GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances)
-{
- if (!mStreamingBuffer)
- {
- return GL_OUT_OF_MEMORY;
- }
-
- for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
- {
- translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1);
- }
-
- // Invalidate static buffers that don't contain matching attributes
- for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
- {
- if (translated[i].active && attribs[i].mArrayEnabled)
- {
- gl::Buffer *buffer = attribs[i].mBoundBuffer.get();
- StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
-
- if (staticBuffer && staticBuffer->getBufferSize() > 0 && !staticBuffer->lookupAttribute(attribs[i], NULL) &&
- !directStoragePossible(staticBuffer, attribs[i]))
- {
- buffer->invalidateStaticData();
- }
- }
- }
-
- // Reserve the required space in the buffers
- for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
- {
- if (translated[i].active && attribs[i].mArrayEnabled)
- {
- gl::Buffer *buffer = attribs[i].mBoundBuffer.get();
- StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
- VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
-
- if (!directStoragePossible(vertexBuffer, attribs[i]))
- {
- if (staticBuffer)
- {
- if (staticBuffer->getBufferSize() == 0)
- {
- int totalCount = elementsInBuffer(attribs[i], buffer->size());
- if (!staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0))
- {
- return GL_OUT_OF_MEMORY;
- }
- }
- }
- else
- {
- int totalCount = StreamingBufferElementCount(attribs[i], count, instances);
-
- // Undefined behaviour:
- // We can return INVALID_OPERATION if our vertex attribute does not have enough backing data.
- if (buffer && elementsInBuffer(attribs[i], buffer->size()) < totalCount)
- {
- return GL_INVALID_OPERATION;
- }
-
- if (!mStreamingBuffer->reserveVertexSpace(attribs[i], totalCount, instances))
- {
- return GL_OUT_OF_MEMORY;
- }
- }
- }
- }
- }
-
- // Perform the vertex data translations
- for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
- {
- if (translated[i].active)
- {
- if (attribs[i].mArrayEnabled)
- {
- gl::Buffer *buffer = attribs[i].mBoundBuffer.get();
-
- if (!buffer && attribs[i].mPointer == NULL)
- {
- // This is an application error that would normally result in a crash, but we catch it and return an error
- ERR("An enabled vertex array has no buffer and no pointer.");
- return GL_INVALID_OPERATION;
- }
-
- StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
- VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
-
- BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
- bool directStorage = directStoragePossible(vertexBuffer, attribs[i]);
-
- unsigned int streamOffset = 0;
- unsigned int outputElementSize = 0;
-
- if (directStorage)
- {
- outputElementSize = attribs[i].stride();
- streamOffset = attribs[i].mOffset + outputElementSize * start;
- storage->markBufferUsage();
- }
- else if (staticBuffer)
- {
- if (!staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize))
- {
- return GL_OUT_OF_MEMORY;
- }
-
- if (!staticBuffer->lookupAttribute(attribs[i], &streamOffset))
- {
- // Convert the entire buffer
- int totalCount = elementsInBuffer(attribs[i], storage->getSize());
- int startIndex = attribs[i].mOffset / attribs[i].stride();
-
- if (!staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0, &streamOffset))
- {
- return GL_OUT_OF_MEMORY;
- }
- }
-
- unsigned int firstElementOffset = (attribs[i].mOffset / attribs[i].stride()) * outputElementSize;
- unsigned int startOffset = (instances == 0 || attribs[i].mDivisor == 0) ? start * outputElementSize : 0;
- if (streamOffset + firstElementOffset + startOffset < streamOffset)
- {
- return GL_OUT_OF_MEMORY;
- }
-
- streamOffset += firstElementOffset + startOffset;
- }
- else
- {
- int totalCount = StreamingBufferElementCount(attribs[i], count, instances);
- if (!mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize) ||
- !mStreamingBuffer->storeVertexAttributes(attribs[i], start, totalCount, instances, &streamOffset))
- {
- return GL_OUT_OF_MEMORY;
- }
- }
-
- translated[i].storage = directStorage ? storage : NULL;
- translated[i].vertexBuffer = vertexBuffer->getVertexBuffer();
- translated[i].serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial();
- translated[i].divisor = attribs[i].mDivisor;
-
- translated[i].attribute = &attribs[i];
- translated[i].stride = outputElementSize;
- translated[i].offset = streamOffset;
- }
- else
- {
- if (!mCurrentValueBuffer[i])
- {
- mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE);
- }
-
- StreamingVertexBufferInterface *buffer = mCurrentValueBuffer[i];
-
- if (mCurrentValue[i][0] != attribs[i].mCurrentValue[0] ||
- mCurrentValue[i][1] != attribs[i].mCurrentValue[1] ||
- mCurrentValue[i][2] != attribs[i].mCurrentValue[2] ||
- mCurrentValue[i][3] != attribs[i].mCurrentValue[3])
- {
- unsigned int requiredSpace = sizeof(float) * 4;
- if (!buffer->reserveRawDataSpace(requiredSpace))
- {
- return GL_OUT_OF_MEMORY;
- }
-
- unsigned int streamOffset;
- if (!buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace, &streamOffset))
- {
- return GL_OUT_OF_MEMORY;
- }
-
- mCurrentValue[i][0] = attribs[i].mCurrentValue[0];
- mCurrentValue[i][1] = attribs[i].mCurrentValue[1];
- mCurrentValue[i][2] = attribs[i].mCurrentValue[2];
- mCurrentValue[i][3] = attribs[i].mCurrentValue[3];
- mCurrentValueOffsets[i] = streamOffset;
- }
-
- translated[i].storage = NULL;
- translated[i].vertexBuffer = mCurrentValueBuffer[i]->getVertexBuffer();
- translated[i].serial = mCurrentValueBuffer[i]->getSerial();
- translated[i].divisor = 0;
-
- translated[i].attribute = &attribs[i];
- translated[i].stride = 0;
- translated[i].offset = mCurrentValueOffsets[i];
- }
- }
- }
-
- for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
- {
- if (translated[i].active && attribs[i].mArrayEnabled)
- {
- gl::Buffer *buffer = attribs[i].mBoundBuffer.get();
-
- if (buffer)
- {
- buffer->promoteStaticUsage(count * attribs[i].typeSize());
- }
- }
- }
-
- return GL_NO_ERROR;
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h
deleted file mode 100644
index 1a8786552a..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// 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 LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_
-#define LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_
-
-#include "libGLESv2/Constants.h"
-#include "common/angleutils.h"
-
-namespace gl
-{
-class VertexAttribute;
-class ProgramBinary;
-}
-
-namespace rx
-{
-class BufferStorage;
-class StreamingVertexBufferInterface;
-class VertexBuffer;
-class Renderer;
-
-struct TranslatedAttribute
-{
- bool active;
-
- const gl::VertexAttribute *attribute;
- unsigned int offset;
- unsigned int stride; // 0 means not to advance the read pointer at all
-
- VertexBuffer *vertexBuffer;
- BufferStorage *storage;
- unsigned int serial;
- unsigned int divisor;
-};
-
-class VertexDataManager
-{
- public:
- VertexDataManager(rx::Renderer *renderer);
- virtual ~VertexDataManager();
-
- GLenum prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(VertexDataManager);
-
- rx::Renderer *const mRenderer;
-
- StreamingVertexBufferInterface *mStreamingBuffer;
-
- float mCurrentValue[gl::MAX_VERTEX_ATTRIBS][4];
- StreamingVertexBufferInterface *mCurrentValueBuffer[gl::MAX_VERTEX_ATTRIBS];
- std::size_t mCurrentValueOffsets[gl::MAX_VERTEX_ATTRIBS];
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp
new file mode 100644
index 0000000000..004223d70f
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp
@@ -0,0 +1,22 @@
+//
+// 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.
+//
+
+// copyimage.cpp: Defines image copying functions
+
+#include "libGLESv2/renderer/copyImage.h"
+
+namespace rx
+{
+
+void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest)
+{
+ uint32_t argb = *reinterpret_cast<const uint32_t*>(source);
+ *reinterpret_cast<uint32_t*>(dest) = (argb & 0xFF00FF00) | // Keep alpha and green
+ (argb & 0x00FF0000) >> 16 | // Move red to blue
+ (argb & 0x000000FF) << 16; // Move blue to red
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h
new file mode 100644
index 0000000000..513eb5cb3d
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h
@@ -0,0 +1,35 @@
+//
+// 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.
+//
+
+// copyimage.h: Defines image copying functions
+
+#ifndef LIBGLESV2_RENDERER_COPYIMAGE_H_
+#define LIBGLESV2_RENDERER_COPYIMAGE_H_
+
+#include "common/mathutil.h"
+#include "libGLESv2/angletypes.h"
+
+#include <cstdint>
+
+namespace rx
+{
+
+template <typename sourceType, typename colorDataType>
+void ReadColor(const uint8_t *source, uint8_t *dest);
+
+template <typename destType, typename colorDataType>
+void WriteColor(const uint8_t *source, uint8_t *dest);
+
+template <typename sourceType, typename destType, typename colorDataType>
+void CopyPixel(const uint8_t *source, uint8_t *dest);
+
+void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest);
+
+}
+
+#include "copyimage.inl"
+
+#endif // LIBGLESV2_RENDERER_COPYIMAGE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl
new file mode 100644
index 0000000000..0498cf7750
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl
@@ -0,0 +1,32 @@
+//
+// 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.
+//
+
+// copyimage.inl: Defines image copying functions
+
+namespace rx
+{
+
+template <typename sourceType, typename colorDataType>
+inline void ReadColor(const uint8_t *source, uint8_t *dest)
+{
+ sourceType::readColor(reinterpret_cast<gl::Color<colorDataType>*>(dest), reinterpret_cast<const sourceType*>(source));
+}
+
+template <typename destType, typename colorDataType>
+inline void WriteColor(const uint8_t *source, uint8_t *dest)
+{
+ destType::writeColor(reinterpret_cast<destType*>(dest), reinterpret_cast<const gl::Color<colorDataType>*>(source));
+}
+
+template <typename sourceType, typename destType, typename colorDataType>
+inline void CopyPixel(const uint8_t *source, uint8_t *dest)
+{
+ colorDataType temp;
+ ReadColor<sourceType, colorDataType>(source, &temp);
+ WriteColor<destType, colorDataType>(&temp, dest);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h
new file mode 100644
index 0000000000..e0e8af166b
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h
@@ -0,0 +1,35 @@
+//
+// 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.
+//
+
+// copyvertex.h: Defines vertex buffer copying and conversion functions
+
+#ifndef LIBGLESV2_RENDERER_COPYVERTEX_H_
+#define LIBGLESV2_RENDERER_COPYVERTEX_H_
+
+#include "common/mathutil.h"
+
+namespace rx
+{
+
+// 'widenDefaultValueBits' gives the default value for the alpha channel (4th component)
+// the sentinel value 0 means we do not want to widen the input or add an alpha channel
+template <typename T, size_t componentCount, uint32_t widenDefaultValueBits>
+inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <size_t componentCount>
+inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <typename T, size_t componentCount, 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 // LIBGLESV2_RENDERER_COPYVERTEX_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl
new file mode 100644
index 0000000000..7eef17b22b
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl
@@ -0,0 +1,288 @@
+//
+// 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.
+//
+
+namespace rx
+{
+
+template <typename T, size_t componentCount, uint32_t widenDefaultValueBits>
+inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+ const size_t attribSize = sizeof(T)* componentCount;
+ const T defaultValue = gl::bitCast<T>(widenDefaultValueBits);
+ const bool widen = (widenDefaultValueBits != 0);
+
+ if (attribSize == stride && !widen)
+ {
+ memcpy(output, input, count * attribSize);
+ }
+ else
+ {
+ size_t outputStride = widen ? 4 : componentCount;
+
+ 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 * outputStride;
+
+ for (size_t j = 0; j < componentCount; j++)
+ {
+ offsetOutput[j] = offsetInput[j];
+ }
+
+ if (widen)
+ {
+ offsetOutput[3] = defaultValue;
+ }
+ }
+ }
+}
+
+template <size_t componentCount>
+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 * componentCount;
+
+ for (size_t j = 0; j < componentCount; j++)
+ {
+ offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor;
+ }
+ }
+}
+
+template <typename T, size_t componentCount, 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 * componentCount;
+
+ for (size_t j = 0; j < componentCount; 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]);
+ }
+ }
+ }
+}
+
+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 = data | negativeMask;
+ }
+ else
+ {
+ *intOutput = data;
+ }
+ }
+ else
+ {
+ GLushort *uintOutput = reinterpret_cast<GLushort*>(output);
+ *uintOutput = 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/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp
new file mode 100644
index 0000000000..a34ef03fb8
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp
@@ -0,0 +1,82 @@
+//
+// 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 "libGLESv2/renderer/d3d/BufferD3D.h"
+#include "libGLESv2/renderer/d3d/VertexBuffer.h"
+#include "libGLESv2/renderer/d3d/IndexBuffer.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+unsigned int BufferD3D::mNextSerial = 1;
+
+BufferD3D::BufferD3D()
+ : BufferImpl(),
+ mStaticVertexBuffer(NULL),
+ mStaticIndexBuffer(NULL)
+{
+ updateSerial();
+}
+
+BufferD3D::~BufferD3D()
+{
+ SafeDelete(mStaticVertexBuffer);
+ SafeDelete(mStaticIndexBuffer);
+}
+
+BufferD3D *BufferD3D::makeBufferD3D(BufferImpl *buffer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(BufferD3D*, buffer));
+ return static_cast<BufferD3D*>(buffer);
+}
+
+void BufferD3D::updateSerial()
+{
+ mSerial = mNextSerial++;
+}
+
+void BufferD3D::initializeStaticData()
+{
+ if (!mStaticVertexBuffer)
+ {
+ mStaticVertexBuffer = new rx::StaticVertexBufferInterface(getRenderer());
+ }
+ if (!mStaticIndexBuffer)
+ {
+ mStaticIndexBuffer = new rx::StaticIndexBufferInterface(getRenderer());
+ }
+}
+
+void BufferD3D::invalidateStaticData()
+{
+ if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0))
+ {
+ SafeDelete(mStaticVertexBuffer);
+ SafeDelete(mStaticIndexBuffer);
+ }
+
+ mUnmodifiedDataUse = 0;
+}
+
+// Creates static buffers if sufficient used data has been left unmodified
+void BufferD3D::promoteStaticUsage(int dataSize)
+{
+ if (!mStaticVertexBuffer && !mStaticIndexBuffer)
+ {
+ mUnmodifiedDataUse += dataSize;
+
+ if (mUnmodifiedDataUse > 3 * getSize())
+ {
+ initializeStaticData();
+ }
+ }
+}
+
+} \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h
new file mode 100644
index 0000000000..44f14cee58
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h
@@ -0,0 +1,56 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BufferImpl.h: Defines the abstract rx::BufferImpl class.
+
+#ifndef LIBGLESV2_RENDERER_BUFFERD3D_H_
+#define LIBGLESV2_RENDERER_BUFFERD3D_H_
+
+#include "libGLESv2/renderer/BufferImpl.h"
+#include "libGLESv2/angletypes.h"
+
+namespace rx
+{
+
+class Renderer;
+class StaticIndexBufferInterface;
+class StaticVertexBufferInterface;
+
+class BufferD3D : public BufferImpl
+{
+ public:
+ BufferD3D();
+ virtual ~BufferD3D();
+
+ static BufferD3D *makeBufferD3D(BufferImpl *buffer);
+
+ unsigned int getSerial() const { return mSerial; }
+
+ virtual size_t getSize() const = 0;
+ virtual bool supportsDirectBinding() const = 0;
+ virtual Renderer* getRenderer() = 0;
+
+ rx::StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; }
+ rx::StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; }
+
+ void initializeStaticData();
+ void invalidateStaticData();
+ void promoteStaticUsage(int dataSize);
+
+ protected:
+ unsigned int mSerial;
+ static unsigned int mNextSerial;
+
+ void updateSerial();
+
+ rx::StaticVertexBufferInterface *mStaticVertexBuffer;
+ rx::StaticIndexBufferInterface *mStaticIndexBuffer;
+ unsigned int mUnmodifiedDataUse;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_BUFFERIMPLD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp
new file mode 100644
index 0000000000..13411ebe64
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp
@@ -0,0 +1,1144 @@
+//
+// 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 "libGLESv2/renderer/d3d/DynamicHLSL.h"
+#include "libGLESv2/renderer/d3d/ShaderD3D.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/Program.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/formatutils.h"
+
+#include "common/utilities.h"
+#include "common/blocklayout.h"
+
+// For use with ArrayString, see angleutils.h
+META_ASSERT(GL_INVALID_INDEX == UINT_MAX);
+
+using namespace gl;
+
+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 rx::PixelShaderOutputVariable &GetOutputAtLocation(const std::vector<rx::PixelShaderOutputVariable> &outputVariables,
+ unsigned int location)
+{
+ for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex)
+ {
+ if (outputVariables[variableIndex].outputIndex == location)
+ {
+ return outputVariables[variableIndex];
+ }
+ }
+
+ UNREACHABLE();
+ return outputVariables[0];
+}
+
+}
+
+namespace rx
+{
+
+const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
+const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@";
+
+DynamicHLSL::DynamicHLSL(rx::Renderer *const renderer)
+ : mRenderer(renderer)
+{
+}
+
+static bool packVarying(PackedVarying *varying, const int maxVaryingVectors, VaryingPacking packing)
+{
+ GLenum transposedType = TransposeMatrixType(varying->type);
+
+ // matrices within varying structs are not transposed
+ int registers = (varying->isStruct() ? HLSLVariableRegisterCount(*varying) : VariableRowCount(transposedType)) * varying->elementCount();
+ int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType));
+
+ if (elements >= 2 && elements <= 4)
+ {
+ for (int r = 0; r <= maxVaryingVectors - registers; r++)
+ {
+ bool available = true;
+
+ for (int y = 0; y < registers && available; y++)
+ {
+ for (int x = 0; x < elements && available; x++)
+ {
+ if (packing[r + y][x])
+ {
+ available = false;
+ }
+ }
+ }
+
+ if (available)
+ {
+ varying->registerIndex = r;
+ varying->columnIndex = 0;
+
+ for (int y = 0; y < registers; y++)
+ {
+ for (int x = 0; x < elements; x++)
+ {
+ packing[r + y][x] = &*varying;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ if (elements == 2)
+ {
+ for (int r = maxVaryingVectors - registers; r >= 0; r--)
+ {
+ bool available = true;
+
+ for (int y = 0; y < registers && available; y++)
+ {
+ for (int x = 2; x < 4 && available; x++)
+ {
+ if (packing[r + y][x])
+ {
+ available = false;
+ }
+ }
+ }
+
+ if (available)
+ {
+ varying->registerIndex = r;
+ varying->columnIndex = 2;
+
+ for (int y = 0; y < registers; y++)
+ {
+ for (int x = 2; x < 4; x++)
+ {
+ packing[r + y][x] = &*varying;
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+ }
+ else if (elements == 1)
+ {
+ int space[4] = { 0 };
+
+ for (int y = 0; y < maxVaryingVectors; y++)
+ {
+ for (int x = 0; x < 4; x++)
+ {
+ space[x] += packing[y][x] ? 0 : 1;
+ }
+ }
+
+ int column = 0;
+
+ for (int x = 0; x < 4; x++)
+ {
+ if (space[x] >= registers && (space[column] < registers || space[x] < space[column]))
+ {
+ column = x;
+ }
+ }
+
+ if (space[column] >= registers)
+ {
+ for (int r = 0; r < maxVaryingVectors; r++)
+ {
+ if (!packing[r][column])
+ {
+ varying->registerIndex = r;
+ varying->columnIndex = column;
+
+ for (int y = r; y < r + registers; y++)
+ {
+ packing[y][column] = &*varying;
+ }
+
+ break;
+ }
+ }
+
+ return true;
+ }
+ }
+ else UNREACHABLE();
+
+ return false;
+}
+
+// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
+// Returns the number of used varying registers, or -1 if unsuccesful
+int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, rx::ShaderD3D *fragmentShader,
+ rx::ShaderD3D *vertexShader, const std::vector<std::string>& transformFeedbackVaryings)
+{
+ // TODO (geofflang): Use context's caps
+ const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors;
+
+ vertexShader->resetVaryingsRegisterAssignment();
+ fragmentShader->resetVaryingsRegisterAssignment();
+
+ std::set<std::string> packedVaryings;
+
+ std::vector<gl::PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
+ std::vector<gl::PackedVarying> &vertexVaryings = vertexShader->getVaryings();
+ for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++)
+ {
+ PackedVarying *varying = &fragmentVaryings[varyingIndex];
+
+ // Do not assign registers to built-in or unreferenced varyings
+ if (varying->isBuiltIn() || !varying->staticUse)
+ {
+ continue;
+ }
+
+ if (packVarying(varying, maxVaryingVectors, packing))
+ {
+ packedVaryings.insert(varying->name);
+ }
+ else
+ {
+ infoLog.append("Could not pack varying %s", varying->name.c_str());
+ return -1;
+ }
+ }
+
+ for (unsigned int feedbackVaryingIndex = 0; feedbackVaryingIndex < transformFeedbackVaryings.size(); feedbackVaryingIndex++)
+ {
+ const std::string &transformFeedbackVarying = transformFeedbackVaryings[feedbackVaryingIndex];
+ if (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end())
+ {
+ bool found = false;
+ for (unsigned int varyingIndex = 0; varyingIndex < vertexVaryings.size(); varyingIndex++)
+ {
+ PackedVarying *varying = &vertexVaryings[varyingIndex];
+ if (transformFeedbackVarying == varying->name)
+ {
+ if (!packVarying(varying, maxVaryingVectors, packing))
+ {
+ infoLog.append("Could not pack varying %s", varying->name.c_str());
+ return -1;
+ }
+
+ found = true;
+ break;
+ }
+ }
+
+ if (!found && transformFeedbackVarying != "gl_Position" && transformFeedbackVarying != "gl_PointSize")
+ {
+ infoLog.append("Transform feedback varying %s does not exist in the vertex shader.", transformFeedbackVarying.c_str());
+ return -1;
+ }
+ }
+ }
+
+ // Return the number of used registers
+ int registers = 0;
+
+ for (int r = 0; r < maxVaryingVectors; r++)
+ {
+ if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
+ {
+ registers++;
+ }
+ }
+
+ return registers;
+}
+
+std::string DynamicHLSL::generateVaryingHLSL(const ShaderD3D *shader) const
+{
+ std::string varyingSemantic = getVaryingSemantic(shader->mUsesPointSize);
+ std::string varyingHLSL;
+
+ const std::vector<gl::PackedVarying> &varyings = shader->getVaryings();
+
+ for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++)
+ {
+ const PackedVarying &varying = varyings[varyingIndex];
+ if (varying.registerAssigned())
+ {
+ ASSERT(!varying.isBuiltIn());
+ GLenum transposedType = TransposeMatrixType(varying.type);
+ int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
+
+ for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
+ {
+ for (int row = 0; row < variableRows; row++)
+ {
+ // 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 (varying.interpolation)
+ {
+ case sh::INTERPOLATION_SMOOTH: varyingHLSL += " "; break;
+ case sh::INTERPOLATION_FLAT: varyingHLSL += " nointerpolation "; break;
+ case sh::INTERPOLATION_CENTROID: varyingHLSL += " centroid "; break;
+ default: UNREACHABLE();
+ }
+
+ unsigned int semanticIndex = elementIndex * variableRows + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + varying.registerIndex + row;
+ std::string n = Str(semanticIndex);
+
+ std::string typeString;
+
+ if (varying.isStruct())
+ {
+ // matrices within structs are not transposed, so
+ // do not use the special struct prefix "rm"
+ typeString = decorateVariable(varying.structName);
+ }
+ else
+ {
+ GLenum componentType = VariableComponentType(transposedType);
+ int columnCount = VariableColumnCount(transposedType);
+ typeString = HLSLComponentTypeString(componentType, columnCount);
+ }
+ varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n";
+ }
+ }
+ }
+ }
+
+ return varyingHLSL;
+}
+
+std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &sourceShader,
+ const VertexFormat inputLayout[],
+ const sh::Attribute shaderAttributes[]) const
+{
+ std::string structHLSL, initHLSL;
+
+ int semanticIndex = 0;
+ unsigned int inputIndex = 0;
+
+ for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex];
+ if (!shaderAttribute.name.empty())
+ {
+ ASSERT(inputIndex < MAX_VERTEX_ATTRIBS);
+ const VertexFormat &vertexFormat = inputLayout[inputIndex];
+
+ // HLSL code for input structure
+ if (IsMatrixType(shaderAttribute.type))
+ {
+ // Matrix types are always transposed
+ structHLSL += " " + HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type));
+ }
+ else
+ {
+ GLenum componentType = mRenderer->getVertexComponentType(vertexFormat);
+ structHLSL += " " + HLSLComponentTypeString(componentType, VariableComponentCount(shaderAttribute.type));
+ }
+
+ structHLSL += " " + decorateVariable(shaderAttribute.name) + " : TEXCOORD" + Str(semanticIndex) + ";\n";
+ semanticIndex += VariableRegisterCount(shaderAttribute.type);
+
+ // HLSL code for initialization
+ initHLSL += " " + 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(vertexFormat) & rx::VERTEX_CONVERT_GPU) != 0)
+ {
+ initHLSL += generateAttributeConversionHLSL(vertexFormat, shaderAttribute);
+ }
+ else
+ {
+ initHLSL += "input." + decorateVariable(shaderAttribute.name);
+ }
+
+ initHLSL += ";\n";
+
+ inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type));
+ }
+ }
+
+ std::string replacementHLSL = "struct VS_INPUT\n"
+ "{\n" +
+ structHLSL +
+ "};\n"
+ "\n"
+ "void initAttributes(VS_INPUT input)\n"
+ "{\n" +
+ initHLSL +
+ "}\n";
+
+ std::string vertexHLSL(sourceShader);
+
+ size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING);
+ vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), replacementHLSL);
+
+ 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::string declarationHLSL;
+ std::string copyHLSL;
+
+ 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 = GetOutputAtLocation(outputVariables, location);
+
+ declarationHLSL += " " + HLSLTypeString(outputVariable.type) + " " + outputVariable.name +
+ " : " + targetSemantic + Str(layoutIndex) + ";\n";
+
+ copyHLSL += " output." + outputVariable.name + " = " + outputVariable.source + ";\n";
+ }
+ }
+
+ if (usesFragDepth)
+ {
+ declarationHLSL += " float gl_Depth : " + depthSemantic + ";\n";
+ copyHLSL += " output.gl_Depth = gl_Depth; \n";
+ }
+
+ std::string replacementHLSL = "struct PS_OUTPUT\n"
+ "{\n" +
+ declarationHLSL +
+ "};\n"
+ "\n"
+ "PS_OUTPUT generateOutput()\n"
+ "{\n"
+ " PS_OUTPUT output;\n" +
+ copyHLSL +
+ " return output;\n"
+ "}\n";
+
+ std::string pixelHLSL(sourceShader);
+
+ size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING);
+ pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(), replacementHLSL);
+
+ return pixelHLSL;
+}
+
+std::string DynamicHLSL::getVaryingSemantic(bool pointSize) const
+{
+ // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
+ // In D3D11 we manually compute gl_PointCoord in the GS.
+ int shaderModel = mRenderer->getMajorShaderModel();
+ return ((pointSize && shaderModel < 4) ? "COLOR" : "TEXCOORD");
+}
+
+struct DynamicHLSL::SemanticInfo
+{
+ struct BuiltinInfo
+ {
+ BuiltinInfo()
+ : enabled(false),
+ index(0),
+ systemValue(false)
+ {}
+
+ bool enabled;
+ std::string semantic;
+ unsigned int index;
+ bool systemValue;
+
+ std::string str() const
+ {
+ return (systemValue ? semantic : (semantic + Str(index)));
+ }
+
+ void enableSystem(const std::string &systemValueSemantic)
+ {
+ enabled = true;
+ semantic = systemValueSemantic;
+ systemValue = true;
+ }
+
+ void enable(const std::string &semanticVal, unsigned int indexVal)
+ {
+ enabled = true;
+ semantic = semanticVal;
+ index = indexVal;
+ }
+ };
+
+ BuiltinInfo dxPosition;
+ BuiltinInfo glPosition;
+ BuiltinInfo glFragCoord;
+ BuiltinInfo glPointCoord;
+ BuiltinInfo glPointSize;
+};
+
+DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord,
+ bool pointSize, bool pixelShader) const
+{
+ SemanticInfo info;
+ bool hlsl4 = (mRenderer->getMajorShaderModel() >= 4);
+ const std::string &varyingSemantic = getVaryingSemantic(pointSize);
+
+ int reservedRegisterIndex = startRegisters;
+
+ if (hlsl4)
+ {
+ info.dxPosition.enableSystem("SV_Position");
+ }
+ else if (pixelShader)
+ {
+ info.dxPosition.enableSystem("VPOS");
+ }
+ else
+ {
+ info.dxPosition.enableSystem("POSITION");
+ }
+
+ info.glPosition.enable(varyingSemantic, reservedRegisterIndex++);
+
+ if (fragCoord)
+ {
+ info.glFragCoord.enable(varyingSemantic, reservedRegisterIndex++);
+ }
+
+ 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)
+ {
+ info.glPointCoord.enable(varyingSemantic, reservedRegisterIndex++);
+ }
+ else
+ {
+ info.glPointCoord.enable("TEXCOORD", 0);
+ }
+ }
+
+ // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
+ if (pointSize && (!pixelShader || hlsl4))
+ {
+ info.glPointSize.enableSystem("PSIZE");
+ }
+
+ return info;
+}
+
+std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const
+{
+ std::string linkHLSL = "{\n";
+
+ ASSERT(info.dxPosition.enabled && info.glPosition.enabled);
+
+ linkHLSL += " float4 dx_Position : " + info.dxPosition.str() + ";\n";
+ linkHLSL += " float4 gl_Position : " + info.glPosition.str() + ";\n";
+
+ if (info.glFragCoord.enabled)
+ {
+ linkHLSL += " float4 gl_FragCoord : " + info.glFragCoord.str() + ";\n";
+ }
+
+ if (info.glPointCoord.enabled)
+ {
+ linkHLSL += " float2 gl_PointCoord : " + info.glPointCoord.str() + ";\n";
+ }
+
+ linkHLSL += varyingHLSL;
+
+ if (info.glPointSize.enabled)
+ {
+ linkHLSL += " float gl_PointSize : " + info.glPointSize.str() + ";\n";
+ }
+
+ linkHLSL += "};\n";
+
+ return linkHLSL;
+}
+
+void DynamicHLSL::storeBuiltinLinkedVaryings(const SemanticInfo &info,
+ std::vector<LinkedVarying> *linkedVaryings) const
+{
+ ASSERT(info.glPosition.enabled);
+
+ linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, info.glPosition.semantic,
+ info.glPosition.index, 1));
+
+ if (info.glFragCoord.enabled)
+ {
+ linkedVaryings->push_back(LinkedVarying("gl_FragCoord", GL_FLOAT_VEC4, 1, info.glFragCoord.semantic,
+ info.glFragCoord.index, 1));
+ }
+
+ if (info.glPointSize.enabled)
+ {
+ linkedVaryings->push_back(LinkedVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1));
+ }
+}
+
+void DynamicHLSL::storeUserLinkedVaryings(const rx::ShaderD3D *vertexShader,
+ std::vector<LinkedVarying> *linkedVaryings) const
+{
+ const std::string &varyingSemantic = getVaryingSemantic(vertexShader->mUsesPointSize);
+ const std::vector<PackedVarying> &varyings = vertexShader->getVaryings();
+
+ for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++)
+ {
+ const PackedVarying &varying = varyings[varyingIndex];
+
+ if (varying.registerAssigned())
+ {
+ ASSERT(!varying.isBuiltIn());
+ GLenum transposedType = TransposeMatrixType(varying.type);
+ int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
+
+ linkedVaryings->push_back(LinkedVarying(varying.name, varying.type, varying.elementCount(),
+ varyingSemantic, varying.registerIndex,
+ variableRows * varying.elementCount()));
+ }
+ }
+}
+
+bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const VaryingPacking packing,
+ std::string& pixelHLSL, std::string& vertexHLSL,
+ rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader,
+ const std::vector<std::string>& transformFeedbackVaryings,
+ std::vector<LinkedVarying> *linkedVaryings,
+ std::map<int, VariableLocation> *programOutputVars,
+ std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
+ bool *outUsesFragDepth) const
+{
+ if (pixelHLSL.empty() || vertexHLSL.empty())
+ {
+ return false;
+ }
+
+ bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
+ bool usesFragColor = fragmentShader->mUsesFragColor;
+ bool usesFragData = fragmentShader->mUsesFragData;
+ bool usesFragCoord = fragmentShader->mUsesFragCoord;
+ bool usesPointCoord = fragmentShader->mUsesPointCoord;
+ bool usesPointSize = vertexShader->mUsesPointSize;
+
+ if (usesFragColor && usesFragData)
+ {
+ infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
+ return false;
+ }
+
+ // Write the HLSL input/output declarations
+ const int shaderModel = mRenderer->getMajorShaderModel();
+
+ // TODO (geofflang): Use context's caps
+ const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors;
+
+ const int registersNeeded = registers + (usesFragCoord ? 1 : 0) + (usesPointCoord ? 1 : 0);
+
+ // 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
+ const bool broadcast = (fragmentShader->mUsesFragColor && mRenderer->getCurrentClientVersion() < 3);
+ const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getRendererCaps().maxDrawBuffers : 1);
+
+ int shaderVersion = vertexShader->getShaderVersion();
+
+ if (registersNeeded > maxVaryingVectors)
+ {
+ infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
+ return false;
+ }
+
+ const std::string &varyingHLSL = generateVaryingHLSL(vertexShader);
+ const SemanticInfo &vertexSemantics = getSemanticInfo(registers, usesFragCoord,
+ false, usesPointSize, false);
+
+ storeUserLinkedVaryings(vertexShader, linkedVaryings);
+ storeBuiltinLinkedVaryings(vertexSemantics, linkedVaryings);
+
+ // Add stub string to be replaced when shader is dynamically defined by its layout
+ vertexHLSL += "\n" + VERTEX_ATTRIBUTE_STUB_STRING + "\n"
+ "struct VS_OUTPUT\n" + generateVaryingLinkHLSL(vertexSemantics, varyingHLSL) + "\n"
+ "VS_OUTPUT main(VS_INPUT input)\n"
+ "{\n"
+ " initAttributes(input);\n";
+
+ if (shaderModel >= 4)
+ {
+ vertexHLSL += "\n"
+ " gl_main();\n"
+ "\n"
+ " VS_OUTPUT output;\n"
+ " output.gl_Position = gl_Position;\n"
+ " output.dx_Position.x = gl_Position.x;\n"
+ " output.dx_Position.y = -gl_Position.y;\n"
+ " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+ " output.dx_Position.w = gl_Position.w;\n";
+ }
+ else
+ {
+ vertexHLSL += "\n"
+ " gl_main();\n"
+ "\n"
+ " VS_OUTPUT output;\n"
+ " output.gl_Position = gl_Position;\n"
+ " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
+ " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
+ " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+ " output.dx_Position.w = gl_Position.w;\n";
+ }
+
+ if (usesPointSize && shaderModel >= 3)
+ {
+ vertexHLSL += " output.gl_PointSize = gl_PointSize;\n";
+ }
+
+ if (usesFragCoord)
+ {
+ vertexHLSL += " output.gl_FragCoord = gl_Position;\n";
+ }
+
+ const std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings();
+ for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++)
+ {
+ const PackedVarying &varying = vertexVaryings[vertVaryingIndex];
+ if (varying.registerAssigned())
+ {
+ for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
+ {
+ int variableRows = (varying.isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying.type)));
+
+ for (int row = 0; row < variableRows; row++)
+ {
+ int r = varying.registerIndex + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + elementIndex * variableRows + row;
+ vertexHLSL += " output.v" + Str(r);
+
+ vertexHLSL += " = _" + varying.name;
+
+ if (varying.isArray())
+ {
+ vertexHLSL += ArrayString(elementIndex);
+ }
+
+ if (variableRows > 1)
+ {
+ vertexHLSL += ArrayString(row);
+ }
+
+ vertexHLSL += ";\n";
+ }
+ }
+ }
+ }
+
+ vertexHLSL += "\n"
+ " return output;\n"
+ "}\n";
+
+ const SemanticInfo &pixelSemantics = getSemanticInfo(registers, usesFragCoord, usesPointCoord,
+ usesPointSize, true);
+
+ pixelHLSL += "struct PS_INPUT\n" + generateVaryingLinkHLSL(pixelSemantics, varyingHLSL) + "\n";
+
+ if (shaderVersion < 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);
+ }
+
+ *outUsesFragDepth = fragmentShader->mUsesFragDepth;
+ }
+ else
+ {
+ defineOutputVariables(fragmentShader, programOutputVars);
+
+ const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getActiveOutputVariables();
+ for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++)
+ {
+ const VariableLocation &outputLocation = locationIt->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 = locationIt->first;
+
+ outPixelShaderKey->push_back(outputKeyVariable);
+ }
+
+ *outUsesFragDepth = false;
+ }
+
+ pixelHLSL += PIXEL_OUTPUT_STUB_STRING + "\n";
+
+ if (fragmentShader->mUsesFrontFacing)
+ {
+ if (shaderModel >= 4)
+ {
+ pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
+ "{\n";
+ }
+ else
+ {
+ pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
+ "{\n";
+ }
+ }
+ else
+ {
+ pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n"
+ "{\n";
+ }
+
+ if (usesFragCoord)
+ {
+ pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
+
+ if (shaderModel >= 4)
+ {
+ pixelHLSL += " gl_FragCoord.x = input.dx_Position.x;\n"
+ " gl_FragCoord.y = input.dx_Position.y;\n";
+ }
+ else if (shaderModel >= 3)
+ {
+ pixelHLSL += " 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()
+ pixelHLSL += " 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";
+ }
+
+ pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n"
+ " gl_FragCoord.w = rhw;\n";
+ }
+
+ if (usesPointCoord && shaderModel >= 3)
+ {
+ pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n";
+ pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
+ }
+
+ if (fragmentShader->mUsesFrontFacing)
+ {
+ if (shaderModel <= 3)
+ {
+ pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
+ }
+ else
+ {
+ pixelHLSL += " gl_FrontFacing = isFrontFace;\n";
+ }
+ }
+
+ const std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
+ for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++)
+ {
+ const PackedVarying &varying = fragmentVaryings[varyingIndex];
+ if (varying.registerAssigned())
+ {
+ ASSERT(!varying.isBuiltIn());
+ for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
+ {
+ GLenum transposedType = TransposeMatrixType(varying.type);
+ int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
+ for (int row = 0; row < variableRows; row++)
+ {
+ std::string n = Str(varying.registerIndex + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + elementIndex * variableRows + row);
+ pixelHLSL += " _" + varying.name;
+
+ if (varying.isArray())
+ {
+ pixelHLSL += ArrayString(elementIndex);
+ }
+
+ if (variableRows > 1)
+ {
+ pixelHLSL += ArrayString(row);
+ }
+
+ if (varying.isStruct())
+ {
+ pixelHLSL += " = input.v" + n + ";\n"; break;
+ }
+ else
+ {
+ switch (VariableColumnCount(transposedType))
+ {
+ case 1: pixelHLSL += " = input.v" + n + ".x;\n"; break;
+ case 2: pixelHLSL += " = input.v" + n + ".xy;\n"; break;
+ case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break;
+ case 4: pixelHLSL += " = input.v" + n + ";\n"; break;
+ default: UNREACHABLE();
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ ASSERT(varying.isBuiltIn() || !varying.staticUse);
+ }
+ }
+
+ pixelHLSL += "\n"
+ " gl_main();\n"
+ "\n"
+ " return generateOutput();\n"
+ "}\n";
+
+ return true;
+}
+
+void DynamicHLSL::defineOutputVariables(rx::ShaderD3D *fragmentShader, std::map<int, VariableLocation> *programOutputVars) const
+{
+ const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getActiveOutputVariables();
+
+ for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size(); outputVariableIndex++)
+ {
+ const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex];
+ const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location;
+
+ ASSERT(outputVariable.staticUse);
+
+ if (outputVariable.arraySize > 0)
+ {
+ for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++)
+ {
+ const int location = baseLocation + elementIndex;
+ ASSERT(programOutputVars->count(location) == 0);
+ (*programOutputVars)[location] = VariableLocation(outputVariable.name, elementIndex, outputVariableIndex);
+ }
+ }
+ else
+ {
+ ASSERT(programOutputVars->count(baseLocation) == 0);
+ (*programOutputVars)[baseLocation] = VariableLocation(outputVariable.name, GL_INVALID_INDEX, outputVariableIndex);
+ }
+ }
+}
+
+std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const
+{
+ // for now we only handle point sprite emulation
+ ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4);
+ return generatePointSpriteHLSL(registers, fragmentShader, vertexShader);
+}
+
+std::string DynamicHLSL::generatePointSpriteHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const
+{
+ ASSERT(registers >= 0);
+ ASSERT(vertexShader->mUsesPointSize);
+ ASSERT(mRenderer->getMajorShaderModel() >= 4);
+
+ std::string geomHLSL;
+
+ const SemanticInfo &inSemantics = getSemanticInfo(registers, fragmentShader->mUsesFragCoord,
+ false, true, false);
+ const SemanticInfo &outSemantics = getSemanticInfo(registers, fragmentShader->mUsesFragCoord,
+ fragmentShader->mUsesPointCoord, true, false);
+
+ std::string varyingHLSL = generateVaryingHLSL(vertexShader);
+ std::string inLinkHLSL = generateVaryingLinkHLSL(inSemantics, varyingHLSL);
+ std::string outLinkHLSL = generateVaryingLinkHLSL(outSemantics, varyingHLSL);
+
+ // TODO(geofflang): use context's caps
+ geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n"
+ "\n"
+ "struct GS_INPUT\n" + inLinkHLSL + "\n" +
+ "struct GS_OUTPUT\n" + outLinkHLSL + "\n" +
+ "\n"
+ "static float2 pointSpriteCorners[] = \n"
+ "{\n"
+ " float2( 0.5f, -0.5f),\n"
+ " float2( 0.5f, 0.5f),\n"
+ " float2(-0.5f, -0.5f),\n"
+ " float2(-0.5f, 0.5f)\n"
+ "};\n"
+ "\n"
+ "static float2 pointSpriteTexcoords[] = \n"
+ "{\n"
+ " float2(1.0f, 1.0f),\n"
+ " float2(1.0f, 0.0f),\n"
+ " float2(0.0f, 1.0f),\n"
+ " float2(0.0f, 0.0f)\n"
+ "};\n"
+ "\n"
+ "static float minPointSize = " + Str(mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n"
+ "static float maxPointSize = " + Str(mRenderer->getRendererCaps().maxAliasedPointSize) + ".0f;\n"
+ "\n"
+ "[maxvertexcount(4)]\n"
+ "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n"
+ "{\n"
+ " GS_OUTPUT output = (GS_OUTPUT)0;\n"
+ " output.gl_Position = input[0].gl_Position;\n";
+ " output.gl_PointSize = input[0].gl_PointSize;\n";
+
+ for (int r = 0; r < registers; r++)
+ {
+ geomHLSL += " output.v" + Str(r) + " = input[0].v" + Str(r) + ";\n";
+ }
+
+ if (fragmentShader->mUsesFragCoord)
+ {
+ geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n";
+ }
+
+ geomHLSL += " \n"
+ " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n"
+ " float4 dx_Position = input[0].dx_Position;\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++)
+ {
+ geomHLSL += " \n"
+ " output.dx_Position = dx_Position + float4(pointSpriteCorners[" + Str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
+
+ if (fragmentShader->mUsesPointCoord)
+ {
+ geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + Str(corner) + "];\n";
+ }
+
+ geomHLSL += " outStream.Append(output);\n";
+ }
+
+ geomHLSL += " \n"
+ " outStream.RestartStrip();\n"
+ "}\n";
+
+ return geomHLSL;
+}
+
+// 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(const VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const
+{
+ 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.mType != GL_FLOAT);
+
+ if (requiresTypeConversion)
+ {
+ // TODO: normalization for 32-bit integer formats
+ ASSERT(!vertexFormat.mNormalized && !vertexFormat.mPureInteger);
+ return "float" + Str(shaderComponentCount) + "(" + attribString + ")";
+ }
+
+ // No conversion necessary
+ return attribString;
+}
+
+void DynamicHLSL::getInputLayoutSignature(const VertexFormat inputLayout[], GLenum signature[]) const
+{
+ for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++)
+ {
+ const VertexFormat &vertexFormat = inputLayout[inputIndex];
+
+ if (vertexFormat.mType == GL_NONE)
+ {
+ signature[inputIndex] = GL_NONE;
+ }
+ else
+ {
+ bool gpuConverted = ((mRenderer->getVertexConversionType(vertexFormat) & rx::VERTEX_CONVERT_GPU) != 0);
+ signature[inputIndex] = (gpuConverted ? GL_TRUE : GL_FALSE);
+ }
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h
new file mode 100644
index 0000000000..f68ed98401
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.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.
+//
+// DynamicHLSL.h: Interface for link and run-time HLSL generation
+//
+
+#ifndef LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_
+#define LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_
+
+#include "common/angleutils.h"
+#include "libGLESv2/constants.h"
+
+#include "angle_gl.h"
+
+#include <vector>
+#include <map>
+
+namespace rx
+{
+class Renderer;
+}
+
+namespace sh
+{
+struct Attribute;
+struct ShaderVariable;
+}
+
+namespace gl
+{
+class InfoLog;
+struct VariableLocation;
+struct LinkedVarying;
+struct VertexAttribute;
+struct VertexFormat;
+struct PackedVarying;
+}
+
+namespace rx
+{
+class Renderer;
+class ShaderD3D;
+
+typedef const gl::PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4];
+
+struct PixelShaderOutputVariable
+{
+ GLenum type;
+ std::string name;
+ std::string source;
+ size_t outputIndex;
+};
+
+class DynamicHLSL
+{
+ public:
+ explicit DynamicHLSL(rx::Renderer *const renderer);
+
+ int packVaryings(gl::InfoLog &infoLog, VaryingPacking packing, rx::ShaderD3D *fragmentShader,
+ rx::ShaderD3D *vertexShader, const std::vector<std::string>& transformFeedbackVaryings);
+ std::string generateVertexShaderForInputLayout(const std::string &sourceShader, const gl::VertexFormat inputLayout[],
+ const 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(gl::InfoLog &infoLog, int registers, const VaryingPacking packing,
+ std::string& pixelHLSL, std::string& vertexHLSL,
+ rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader,
+ const std::vector<std::string>& transformFeedbackVaryings,
+ std::vector<gl::LinkedVarying> *linkedVaryings,
+ std::map<int, gl::VariableLocation> *programOutputVars,
+ std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
+ bool *outUsesFragDepth) const;
+
+ std::string generateGeometryShaderHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const;
+ void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DynamicHLSL);
+
+ rx::Renderer *const mRenderer;
+
+ struct SemanticInfo;
+
+ std::string getVaryingSemantic(bool pointSize) const;
+ SemanticInfo getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord, bool pointSize,
+ bool pixelShader) const;
+ std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const;
+ std::string generateVaryingHLSL(const ShaderD3D *shader) const;
+ void storeUserLinkedVaryings(const rx::ShaderD3D *vertexShader, std::vector<gl::LinkedVarying> *linkedVaryings) const;
+ void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector<gl::LinkedVarying> *linkedVaryings) const;
+ void defineOutputVariables(rx::ShaderD3D *fragmentShader, std::map<int, gl::VariableLocation> *programOutputVars) const;
+ std::string generatePointSpriteHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const;
+
+ // Prepend an underscore
+ static std::string decorateVariable(const std::string &name);
+
+ std::string generateAttributeConversionHLSL(const gl::VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
new file mode 100644
index 0000000000..d0131974ee
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
@@ -0,0 +1,164 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
+#include "libGLESv2/Program.h"
+#include "libGLESv2/main.h"
+
+#include "common/utilities.h"
+#include "common/platform.h"
+
+#if defined(__MINGW32__) && !defined(D3DCOMPILER_DLL)
+
+// Add define + typedefs for older MinGW-w64 headers (pre 5783)
+
+#define D3DCOMPILER_DLL L"d3dcompiler_43.dll"
+
+HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename,
+ const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
+ const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages);
+typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const char *filename,
+ const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
+ const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages);
+
+#endif // __MINGW32__ && !D3DCOMPILER_DLL
+
+#ifndef QT_D3DCOMPILER_DLL
+#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL
+#endif
+
+namespace rx
+{
+
+HLSLCompiler::HLSLCompiler()
+ : mD3DCompilerModule(NULL),
+ mD3DCompileFunc(NULL)
+{
+}
+
+HLSLCompiler::~HLSLCompiler()
+{
+ release();
+}
+
+bool HLSLCompiler::initialize()
+{
+#if !defined(ANGLE_PLATFORM_WINRT)
+#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
+
+ // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL
+ const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL");
+ if (!defaultCompiler)
+ defaultCompiler = QT_D3DCOMPILER_DLL;
+
+ const wchar_t *compilerDlls[] = {
+ defaultCompiler,
+ L"d3dcompiler_47.dll",
+ L"d3dcompiler_46.dll",
+ L"d3dcompiler_45.dll",
+ L"d3dcompiler_44.dll",
+ L"d3dcompiler_43.dll",
+ 0
+ };
+
+ // Load the first available known compiler DLL
+ for (int i = 0; compilerDlls[i]; ++i)
+ {
+ mD3DCompilerModule = LoadLibrary(compilerDlls[i]);
+ if (mD3DCompilerModule)
+ break;
+ }
+
+ if (!mD3DCompilerModule)
+ {
+ ERR("No D3D compiler module found - aborting!\n");
+ return false;
+ }
+
+ mD3DCompileFunc = reinterpret_cast<CompileFuncPtr>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
+ ASSERT(mD3DCompileFunc);
+#else
+ mD3DCompileFunc = reinterpret_cast<CompileFuncPtr>(&D3DCompile);
+#endif
+ return mD3DCompileFunc != NULL;
+}
+
+void HLSLCompiler::release()
+{
+ if (mD3DCompilerModule)
+ {
+ FreeLibrary(mD3DCompilerModule);
+ mD3DCompilerModule = NULL;
+ mD3DCompileFunc = NULL;
+ }
+}
+
+ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile,
+ const UINT optimizationFlags[], const char *flagNames[], int attempts) const
+{
+#if !defined(ANGLE_PLATFORM_WINRT)
+ ASSERT(mD3DCompilerModule && mD3DCompileFunc);
+#endif
+
+ if (!hlsl)
+ {
+ return NULL;
+ }
+
+ pD3DCompile compileFunc = reinterpret_cast<pD3DCompile>(mD3DCompileFunc);
+ for (int i = 0; i < attempts; ++i)
+ {
+ ID3DBlob *errorMessage = NULL;
+ ID3DBlob *binary = NULL;
+
+ HRESULT result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL, "main", profile, optimizationFlags[i], 0, &binary, &errorMessage);
+
+ if (errorMessage)
+ {
+ const char *message = (const char*)errorMessage->GetBufferPointer();
+
+ infoLog.appendSanitized(message);
+ TRACE("\n%s", hlsl);
+ TRACE("\n%s", message);
+
+ SafeRelease(errorMessage);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ return (ShaderBlob*)binary;
+ }
+ else
+ {
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*)NULL);
+ }
+
+ infoLog.append("Warning: D3D shader compilation failed with %s flags.", flagNames[i]);
+
+ if (i + 1 < attempts)
+ {
+ infoLog.append(" Retrying with %s.\n", flagNames[i + 1]);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h
new file mode 100644
index 0000000000..0ce9e44be5
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h
@@ -0,0 +1,38 @@
+#ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
+#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
+
+#include "common/angleutils.h"
+
+namespace gl
+{
+class InfoLog;
+}
+
+namespace rx
+{
+
+typedef void* ShaderBlob;
+typedef void(*CompileFuncPtr)();
+
+class HLSLCompiler
+{
+ public:
+ HLSLCompiler();
+ ~HLSLCompiler();
+
+ bool initialize();
+ void release();
+
+ ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile,
+ const UINT optimizationFlags[], const char *flagNames[], int attempts) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HLSLCompiler);
+
+ HMODULE mD3DCompilerModule;
+ CompileFuncPtr mD3DCompileFunc;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp
new file mode 100644
index 0000000000..0854b968da
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp
@@ -0,0 +1,26 @@
+//
+// 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.
+//
+
+// 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 "libGLESv2/renderer/d3d/ImageD3D.h"
+
+namespace rx
+{
+
+ImageD3D::ImageD3D()
+{
+}
+
+ImageD3D *ImageD3D::makeImageD3D(Image *img)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(rx::ImageD3D*, img));
+ return static_cast<rx::ImageD3D*>(img);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h
new file mode 100644
index 0000000000..60a6ffdf37
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h
@@ -0,0 +1,51 @@
+//
+// 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.
+//
+
+// Image.h: Defines the rx::Image class, an abstract base class for the
+// renderer-specific classes which will define the interface to the underlying
+// surfaces or resources.
+
+#ifndef LIBGLESV2_RENDERER_IMAGED3D_H_
+#define LIBGLESV2_RENDERER_IMAGED3D_H_
+
+#include "common/debug.h"
+#include "libGLESv2/renderer/Image.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class TextureStorage;
+
+class ImageD3D : public Image
+{
+ public:
+ ImageD3D();
+ virtual ~ImageD3D() {};
+
+ static ImageD3D *makeImageD3D(Image *img);
+
+ virtual bool isDirty() const = 0;
+
+ virtual void setManagedSurface2D(TextureStorage *storage, int level) {};
+ virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level) {};
+ virtual void setManagedSurface3D(TextureStorage *storage, int level) {};
+ virtual void setManagedSurface2DArray(TextureStorage *storage, int layer, int level) {};
+ virtual bool copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
+ virtual bool copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
+ virtual bool copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) = 0;
+ virtual bool copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ImageD3D);
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_IMAGED3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp
index 37dbd3e195..1dce1270d8 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -8,7 +7,7 @@
// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface
// class with derivations, classes that perform graphics API agnostic index buffer operations.
-#include "libGLESv2/renderer/IndexBuffer.h"
+#include "libGLESv2/renderer/d3d/IndexBuffer.h"
#include "libGLESv2/renderer/Renderer.h"
namespace rx
@@ -67,21 +66,22 @@ unsigned int IndexBufferInterface::getSerial() const
return mIndexBuffer->getSerial();
}
-bool IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset)
+gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset)
{
// Protect against integer overflow
if (mWritePosition + size < mWritePosition)
{
- return false;
+ return gl::Error(GL_OUT_OF_MEMORY, "Mapping of internal index buffer would cause an integer overflow.");
}
- if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory))
+ gl::Error error = mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory);
+ if (error.isError())
{
if (outMappedMemory)
{
*outMappedMemory = NULL;
}
- return false;
+ return error;
}
if (streamOffset)
@@ -90,10 +90,10 @@ bool IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory,
}
mWritePosition += size;
- return true;
+ return gl::Error(GL_NO_ERROR);
}
-bool IndexBufferInterface::unmapBuffer()
+gl::Error IndexBufferInterface::unmapBuffer()
{
return mIndexBuffer->unmapBuffer();
}
@@ -113,12 +113,12 @@ void IndexBufferInterface::setWritePosition(unsigned int writePosition)
mWritePosition = writePosition;
}
-bool IndexBufferInterface::discard()
+gl::Error IndexBufferInterface::discard()
{
return mIndexBuffer->discard();
}
-bool IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType)
+gl::Error IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType)
{
if (mIndexBuffer->getBufferSize() == 0)
{
@@ -138,26 +138,30 @@ StreamingIndexBufferInterface::~StreamingIndexBufferInterface()
{
}
-bool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
+gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
{
- bool result = true;
unsigned int curBufferSize = getBufferSize();
unsigned int writePos = getWritePosition();
if (size > curBufferSize)
{
- result = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
+ 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)
{
- if (!discard())
+ gl::Error error = discard();
+ if (error.isError())
{
- return false;
+ return error;
}
setWritePosition(0);
}
- return result;
+ return gl::Error(GL_NO_ERROR);
}
@@ -169,7 +173,7 @@ StaticIndexBufferInterface::~StaticIndexBufferInterface()
{
}
-bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
+gl::Error StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
{
unsigned int curSize = getBufferSize();
if (curSize == 0)
@@ -178,13 +182,12 @@ bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum in
}
else if (curSize >= size && indexType == getIndexType())
{
- return true;
+ return gl::Error(GL_NO_ERROR);
}
else
{
- ERR("Static index buffers can't be resized");
UNREACHABLE();
- return false;
+ return gl::Error(GL_INVALID_OPERATION, "Internal static index buffers can't be resized");
}
}
@@ -194,4 +197,3 @@ IndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache()
}
}
-
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h
index 6fb885a1cd..1bb5ae2c4a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h
@@ -11,6 +11,7 @@
#define LIBGLESV2_RENDERER_INDEXBUFFER_H_
#include "common/angleutils.h"
+#include "libGLESv2/Error.h"
#include "libGLESv2/renderer/IndexRangeCache.h"
namespace rx
@@ -23,16 +24,16 @@ class IndexBuffer
IndexBuffer();
virtual ~IndexBuffer();
- virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0;
+ virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0;
- virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0;
- virtual bool unmapBuffer() = 0;
+ virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0;
+ virtual gl::Error unmapBuffer() = 0;
- virtual bool discard() = 0;
+ virtual gl::Error discard() = 0;
virtual GLenum getIndexType() const = 0;
virtual unsigned int getBufferSize() const = 0;
- virtual bool setSize(unsigned int bufferSize, GLenum indexType) = 0;
+ virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType) = 0;
unsigned int getSerial() const;
@@ -52,15 +53,15 @@ class IndexBufferInterface
IndexBufferInterface(Renderer *renderer, bool dynamic);
virtual ~IndexBufferInterface();
- virtual bool reserveBufferSpace(unsigned int size, GLenum indexType) = 0;
+ virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) = 0;
GLenum getIndexType() const;
unsigned int getBufferSize() const;
unsigned int getSerial() const;
- bool mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset);
- bool unmapBuffer();
+ gl::Error mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset);
+ gl::Error unmapBuffer();
IndexBuffer *getIndexBuffer() const;
@@ -68,9 +69,9 @@ class IndexBufferInterface
unsigned int getWritePosition() const;
void setWritePosition(unsigned int writePosition);
- bool discard();
+ gl::Error discard();
- bool setBufferSize(unsigned int bufferSize, GLenum indexType);
+ gl::Error setBufferSize(unsigned int bufferSize, GLenum indexType);
private:
DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface);
@@ -89,7 +90,7 @@ class StreamingIndexBufferInterface : public IndexBufferInterface
StreamingIndexBufferInterface(Renderer *renderer);
~StreamingIndexBufferInterface();
- virtual bool reserveBufferSpace(unsigned int size, GLenum indexType);
+ virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType);
};
class StaticIndexBufferInterface : public IndexBufferInterface
@@ -98,7 +99,7 @@ class StaticIndexBufferInterface : public IndexBufferInterface
explicit StaticIndexBufferInterface(Renderer *renderer);
~StaticIndexBufferInterface();
- virtual bool reserveBufferSpace(unsigned int size, GLenum indexType);
+ virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType);
IndexRangeCache *getIndexRangeCache();
@@ -108,4 +109,4 @@ class StaticIndexBufferInterface : public IndexBufferInterface
}
-#endif // LIBGLESV2_RENDERER_INDEXBUFFER_H_ \ No newline at end of file
+#endif // LIBGLESV2_RENDERER_INDEXBUFFER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp
new file mode 100644
index 0000000000..8d455b4bf3
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp
@@ -0,0 +1,255 @@
+//
+// 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 "libGLESv2/renderer/d3d/IndexDataManager.h"
+#include "libGLESv2/renderer/d3d/BufferD3D.h"
+#include "libGLESv2/renderer/d3d/IndexBuffer.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/formatutils.h"
+
+namespace rx
+{
+
+static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void *input, GLsizei count, void *output)
+{
+ if (sourceType == GL_UNSIGNED_BYTE)
+ {
+ ASSERT(destinationType == GL_UNSIGNED_SHORT);
+ const GLubyte *in = static_cast<const GLubyte*>(input);
+ GLushort *out = static_cast<GLushort*>(output);
+
+ for (GLsizei i = 0; i < count; i++)
+ {
+ out[i] = in[i];
+ }
+ }
+ else if (sourceType == GL_UNSIGNED_INT)
+ {
+ ASSERT(destinationType == GL_UNSIGNED_INT);
+ memcpy(output, input, count * sizeof(GLuint));
+ }
+ else if (sourceType == GL_UNSIGNED_SHORT)
+ {
+ if (destinationType == GL_UNSIGNED_SHORT)
+ {
+ memcpy(output, input, count * sizeof(GLushort));
+ }
+ else if (destinationType == GL_UNSIGNED_INT)
+ {
+ const GLushort *in = static_cast<const GLushort*>(input);
+ GLuint *out = static_cast<GLuint*>(output);
+
+ for (GLsizei i = 0; i < count; i++)
+ {
+ out[i] = in[i];
+ }
+ }
+ else UNREACHABLE();
+ }
+ else UNREACHABLE();
+}
+
+IndexDataManager::IndexDataManager(Renderer *renderer)
+ : mRenderer(renderer),
+ mStreamingBufferShort(NULL),
+ mStreamingBufferInt(NULL)
+{
+}
+
+IndexDataManager::~IndexDataManager()
+{
+ SafeDelete(mStreamingBufferShort);
+ SafeDelete(mStreamingBufferInt);
+}
+
+gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated)
+{
+ const gl::Type &typeInfo = gl::GetTypeInfo(type);
+
+ GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
+
+ unsigned int offset = 0;
+ bool alignedOffset = false;
+
+ BufferD3D *storage = NULL;
+
+ if (buffer != NULL)
+ {
+ offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
+
+ storage = BufferD3D::makeBufferD3D(buffer->getImplementation());
+
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break;
+ case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;
+ case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break;
+ default: UNREACHABLE(); alignedOffset = false;
+ }
+
+ ASSERT(typeInfo.bytes * static_cast<unsigned int>(count) + offset <= storage->getSize());
+
+ indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+ }
+
+ StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL;
+ IndexBufferInterface *indexBuffer = NULL;
+ bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() &&
+ destinationIndexType == type;
+ unsigned int streamOffset = 0;
+
+ if (directStorage)
+ {
+ streamOffset = offset;
+
+ if (!buffer->getIndexRangeCache()->findRange(type, offset, count, NULL, NULL))
+ {
+ buffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, offset);
+ }
+ }
+ else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset)
+ {
+ indexBuffer = staticBuffer;
+
+ if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, NULL, &streamOffset))
+ {
+ streamOffset = (offset / typeInfo.bytes) * gl::GetTypeInfo(destinationIndexType).bytes;
+ staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset);
+ }
+ }
+
+ // Avoid D3D11's primitive restart index value
+ // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
+ if (translated->indexRange.end == 0xFFFF && type == GL_UNSIGNED_SHORT && mRenderer->getMajorShaderModel() > 3)
+ {
+ destinationIndexType = GL_UNSIGNED_INT;
+ directStorage = false;
+ indexBuffer = NULL;
+ }
+
+ const gl::Type &destTypeInfo = gl::GetTypeInfo(destinationIndexType);
+
+ if (!directStorage && !indexBuffer)
+ {
+ gl::Error error = getStreamingIndexBuffer(destinationIndexType, &indexBuffer);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ unsigned int convertCount = count;
+
+ if (staticBuffer)
+ {
+ if (staticBuffer->getBufferSize() == 0 && alignedOffset)
+ {
+ indexBuffer = staticBuffer;
+ convertCount = storage->getSize() / typeInfo.bytes;
+ }
+ else
+ {
+ storage->invalidateStaticData();
+ staticBuffer = NULL;
+ }
+ }
+
+ ASSERT(indexBuffer);
+
+ if (convertCount > std::numeric_limits<unsigned int>::max() / destTypeInfo.bytes)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Reserving %u indices of %u bytes each exceeds the maximum buffer size.",
+ convertCount, destTypeInfo.bytes);
+ }
+
+ unsigned int bufferSizeRequired = convertCount * destTypeInfo.bytes;
+ error = indexBuffer->reserveBufferSpace(bufferSizeRequired, type);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ void* output = NULL;
+ error = indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ConvertIndices(type, destinationIndexType, staticBuffer ? storage->getData() : indices, convertCount, output);
+
+ error = indexBuffer->unmapBuffer();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (staticBuffer)
+ {
+ streamOffset = (offset / typeInfo.bytes) * destTypeInfo.bytes;
+ staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset);
+ }
+ }
+
+ translated->storage = directStorage ? storage : NULL;
+ translated->indexBuffer = indexBuffer ? indexBuffer->getIndexBuffer() : NULL;
+ translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial();
+ translated->startIndex = streamOffset / destTypeInfo.bytes;
+ translated->startOffset = streamOffset;
+ translated->indexType = destinationIndexType;
+
+ if (storage)
+ {
+ storage->promoteStaticUsage(count * typeInfo.bytes);
+ }
+
+ 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(mRenderer);
+ 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(mRenderer);
+ 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/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h
index 0e77c81d1b..6d0b89e6d4 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -11,6 +11,10 @@
#define LIBGLESV2_INDEXDATAMANAGER_H_
#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libGLESv2/Error.h"
+
+#include <GLES2/gl2.h>
namespace
{
@@ -24,21 +28,22 @@ class Buffer;
namespace rx
{
+class IndexBufferInterface;
class StaticIndexBufferInterface;
class StreamingIndexBufferInterface;
class IndexBuffer;
-class BufferStorage;
+class BufferD3D;
class Renderer;
struct TranslatedIndexData
{
- unsigned int minIndex;
- unsigned int maxIndex;
+ RangeUI indexRange;
unsigned int startIndex;
unsigned int startOffset; // In bytes
IndexBuffer *indexBuffer;
- BufferStorage *storage;
+ BufferD3D *storage;
+ GLenum indexType;
unsigned int serial;
};
@@ -48,17 +53,17 @@ class IndexDataManager
explicit IndexDataManager(Renderer *renderer);
virtual ~IndexDataManager();
- GLenum prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated);
- StaticIndexBufferInterface *getCountingIndices(GLsizei count);
+ gl::Error prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated);
private:
+ gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer);
+
DISALLOW_COPY_AND_ASSIGN(IndexDataManager);
Renderer *const mRenderer;
StreamingIndexBufferInterface *mStreamingBufferShort;
StreamingIndexBufferInterface *mStreamingBufferInt;
- StaticIndexBufferInterface *mCountingBuffer;
};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp
new file mode 100644
index 0000000000..2b5b09a324
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp
@@ -0,0 +1,74 @@
+//
+// 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 "libGLESv2/renderer/d3d/MemoryBuffer.h"
+#include "common/debug.h"
+
+#include <algorithm>
+#include <cstdlib>
+
+namespace rx
+{
+
+MemoryBuffer::MemoryBuffer()
+ : mSize(0),
+ mData(NULL)
+{
+}
+
+MemoryBuffer::~MemoryBuffer()
+{
+ free(mData);
+ mData = NULL;
+}
+
+bool MemoryBuffer::resize(size_t size)
+{
+ if (size == 0)
+ {
+ free(mData);
+ mData = NULL;
+ mSize = 0;
+ }
+ else
+ {
+ uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size));
+ if (newMemory == NULL)
+ {
+ return false;
+ }
+
+ if (mData)
+ {
+ // Copy the intersection of the old data and the new data
+ std::copy(mData, mData + std::min(mSize, size), newMemory);
+ free(mData);
+ }
+
+ mData = newMemory;
+ mSize = size;
+ }
+
+ return true;
+}
+
+size_t MemoryBuffer::size() const
+{
+ return mSize;
+}
+
+const uint8_t *MemoryBuffer::data() const
+{
+ return mData;
+}
+
+uint8_t *MemoryBuffer::data()
+{
+ ASSERT(mData);
+ return mData;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h
new file mode 100644
index 0000000000..c65f79fe10
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h
@@ -0,0 +1,36 @@
+//
+// 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 LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_
+#define LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_
+
+#include <cstddef>
+#include <cstdint>
+
+namespace rx
+{
+
+class MemoryBuffer
+{
+ public:
+ MemoryBuffer();
+ ~MemoryBuffer();
+
+ bool resize(size_t size);
+ size_t size() const;
+ bool empty() const { return mSize == 0; }
+
+ const uint8_t *data() const;
+ uint8_t *data();
+
+ private:
+ size_t mSize;
+ uint8_t *mData;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp
new file mode 100644
index 0000000000..d7d97cc2bd
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp
@@ -0,0 +1,205 @@
+//
+// 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 "libGLESv2/renderer/d3d/ProgramD3D.h"
+
+#include "common/utilities.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/ShaderExecutable.h"
+#include "libGLESv2/renderer/d3d/DynamicHLSL.h"
+#include "libGLESv2/renderer/d3d/ShaderD3D.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+ProgramD3D::ProgramD3D(rx::Renderer *renderer)
+ : ProgramImpl(),
+ mRenderer(renderer),
+ mDynamicHLSL(NULL),
+ mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
+ mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
+ mVertexUniformStorage(NULL),
+ mFragmentUniformStorage(NULL)
+{
+ mDynamicHLSL = new rx::DynamicHLSL(renderer);
+}
+
+ProgramD3D::~ProgramD3D()
+{
+ reset();
+ SafeDelete(mDynamicHLSL);
+}
+
+ProgramD3D *ProgramD3D::makeProgramD3D(ProgramImpl *impl)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(ProgramD3D*, impl));
+ return static_cast<ProgramD3D*>(impl);
+}
+
+const ProgramD3D *ProgramD3D::makeProgramD3D(const ProgramImpl *impl)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(const ProgramD3D*, impl));
+ return static_cast<const ProgramD3D*>(impl);
+}
+
+bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
+{
+ stream->readString(&mVertexHLSL);
+ stream->readInt(&mVertexWorkarounds);
+ stream->readString(&mPixelHLSL);
+ stream->readInt(&mPixelWorkarounds);
+ stream->readBool(&mUsesFragDepth);
+
+ 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);
+ }
+
+ return true;
+}
+
+bool ProgramD3D::save(gl::BinaryOutputStream *stream)
+{
+ stream->writeString(mVertexHLSL);
+ stream->writeInt(mVertexWorkarounds);
+ stream->writeString(mPixelHLSL);
+ stream->writeInt(mPixelWorkarounds);
+ stream->writeInt(mUsesFragDepth);
+
+ const std::vector<rx::PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
+ stream->writeInt(pixelShaderKey.size());
+ for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
+ {
+ const rx::PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
+ stream->writeInt(variable.type);
+ stream->writeString(variable.name);
+ stream->writeString(variable.source);
+ stream->writeInt(variable.outputIndex);
+ }
+
+ return true;
+}
+
+rx::ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector<GLenum> &outputSignature,
+ const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
+ bool separatedOutputBuffers)
+{
+ std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
+ outputSignature);
+
+ // Generate new pixel executable
+ rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(infoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL,
+ transformFeedbackLinkedVaryings, separatedOutputBuffers,
+ mPixelWorkarounds);
+
+ return pixelExecutable;
+}
+
+rx::ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(gl::InfoLog &infoLog,
+ const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
+ const sh::Attribute shaderAttributes[],
+ const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
+ bool separatedOutputBuffers)
+{
+ // Generate new dynamic layout with attribute conversions
+ std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, shaderAttributes);
+
+ // Generate new vertex executable
+ rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(infoLog, finalVertexHLSL.c_str(),
+ rx::SHADER_VERTEX,
+ transformFeedbackLinkedVaryings, separatedOutputBuffers,
+ mVertexWorkarounds);
+
+ return vertexExecutable;
+}
+
+bool ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
+ const std::vector<std::string> &transformFeedbackVaryings, int *registers,
+ std::vector<gl::LinkedVarying> *linkedVaryings, std::map<int, gl::VariableLocation> *outputVariables)
+{
+ rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
+ rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
+
+ mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
+ mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
+
+ mVertexHLSL = vertexShaderD3D->getTranslatedSource();
+ mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
+
+ // Map the varyings to the register file
+ rx::VaryingPacking packing = { NULL };
+ *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings);
+
+ if (*registers < 0)
+ {
+ return false;
+ }
+
+ if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader))
+ {
+ return false;
+ }
+
+ if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
+ fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
+ linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void ProgramD3D::initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms)
+{
+ // Compute total default block size
+ unsigned int vertexRegisters = 0;
+ unsigned int fragmentRegisters = 0;
+ for (size_t uniformIndex = 0; uniformIndex < uniforms.size(); uniformIndex++)
+ {
+ const gl::LinkedUniform &uniform = *uniforms[uniformIndex];
+
+ if (!gl::IsSampler(uniform.type))
+ {
+ if (uniform.isReferencedByVertexShader())
+ {
+ vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
+ }
+ if (uniform.isReferencedByFragmentShader())
+ {
+ fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
+ }
+ }
+ }
+
+ mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
+ mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
+}
+
+void ProgramD3D::reset()
+{
+ mVertexHLSL.clear();
+ mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
+
+ mPixelHLSL.clear();
+ mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
+ mUsesFragDepth = false;
+ mPixelShaderKey.clear();
+
+ SafeDelete(mVertexUniformStorage);
+ SafeDelete(mFragmentUniformStorage);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h
new file mode 100644
index 0000000000..d645c57daa
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h
@@ -0,0 +1,87 @@
+//
+// 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 LIBGLESV2_RENDERER_PROGRAMD3D_H_
+#define LIBGLESV2_RENDERER_PROGRAMD3D_H_
+
+#include "libGLESv2/renderer/ProgramImpl.h"
+
+#include <string>
+#include <vector>
+
+namespace gl
+{
+struct LinkedUniform;
+struct VariableLocation;
+struct VertexFormat;
+}
+
+namespace rx
+{
+
+class UniformStorage;
+
+class ProgramD3D : public ProgramImpl
+{
+ public:
+ ProgramD3D(rx::Renderer *renderer);
+ virtual ~ProgramD3D();
+
+ static ProgramD3D *makeProgramD3D(ProgramImpl *impl);
+ static const ProgramD3D *makeProgramD3D(const ProgramImpl *impl);
+
+ Renderer *getRenderer() { return mRenderer; }
+ DynamicHLSL *getDynamicHLSL() { return mDynamicHLSL; }
+ const std::vector<rx::PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; }
+
+ GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; }
+ bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
+ bool save(gl::BinaryOutputStream *stream);
+
+ ShaderExecutable *getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector<GLenum> &outputSignature,
+ const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
+ bool separatedOutputBuffers);
+ ShaderExecutable *getVertexExecutableForInputLayout(gl::InfoLog &infoLog,
+ const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
+ const sh::Attribute shaderAttributes[],
+ const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
+ bool separatedOutputBuffers);
+
+ bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
+ const std::vector<std::string> &transformFeedbackVaryings, int *registers,
+ std::vector<gl::LinkedVarying> *linkedVaryings, std::map<int, gl::VariableLocation> *outputVariables);
+
+ // D3D only
+ void initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms);
+
+ const UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; }
+ const UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
+
+ void reset();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ProgramD3D);
+
+ Renderer *mRenderer;
+ DynamicHLSL *mDynamicHLSL;
+
+ std::string mVertexHLSL;
+ rx::D3DWorkaroundType mVertexWorkarounds;
+
+ std::string mPixelHLSL;
+ rx::D3DWorkaroundType mPixelWorkarounds;
+ bool mUsesFragDepth;
+ std::vector<rx::PixelShaderOutputVariable> mPixelShaderKey;
+
+ UniformStorage *mVertexUniformStorage;
+ UniformStorage *mFragmentUniformStorage;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_PROGRAMD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp
new file mode 100644
index 0000000000..c472113eba
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp
@@ -0,0 +1,457 @@
+//
+// 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 "libGLESv2/renderer/d3d/ShaderD3D.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/main.h"
+
+#include "common/utilities.h"
+
+namespace rx
+{
+
+template <typename VarT>
+void FilterInactiveVariables(std::vector<VarT> *variableList)
+{
+ ASSERT(variableList);
+
+ for (size_t varIndex = 0; varIndex < variableList->size();)
+ {
+ if (!(*variableList)[varIndex].staticUse)
+ {
+ variableList->erase(variableList->begin() + varIndex);
+ }
+ else
+ {
+ varIndex++;
+ }
+ }
+}
+
+void *ShaderD3D::mFragmentCompiler = NULL;
+void *ShaderD3D::mVertexCompiler = NULL;
+
+template <typename VarT>
+const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableList)
+{
+ ASSERT(variableList);
+ return variableList;
+}
+
+ShaderD3D::ShaderD3D(GLenum type, rx::Renderer *renderer)
+ : mType(type),
+ mRenderer(renderer),
+ mShaderVersion(100)
+{
+ uncompile();
+ initializeCompiler();
+}
+
+ShaderD3D::~ShaderD3D()
+{
+}
+
+ShaderD3D *ShaderD3D::makeShaderD3D(ShaderImpl *impl)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(ShaderD3D*, impl));
+ return static_cast<ShaderD3D*>(impl);
+}
+
+const ShaderD3D *ShaderD3D::makeShaderD3D(const ShaderImpl *impl)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(const ShaderD3D*, impl));
+ return static_cast<const ShaderD3D*>(impl);
+}
+
+// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
+void ShaderD3D::initializeCompiler()
+{
+ if (!mFragmentCompiler)
+ {
+ int result = ShInitialize();
+
+ if (result)
+ {
+ ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
+
+ ShBuiltInResources resources;
+ ShInitBuiltInResources(&resources);
+
+ // TODO(geofflang): use context's caps
+ const gl::Caps &caps = mRenderer->getRendererCaps();
+ const gl::Extensions &extensions = mRenderer->getRendererExtensions();
+
+ resources.MaxVertexAttribs = caps.maxVertexAttributes;
+ resources.MaxVertexUniformVectors = caps.maxVertexUniformVectors;
+ resources.MaxVaryingVectors = caps.maxVaryingVectors;
+ resources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits;
+ resources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
+ resources.MaxTextureImageUnits = caps.maxTextureImageUnits;
+ resources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors;
+ resources.MaxDrawBuffers = caps.maxDrawBuffers;
+ resources.OES_standard_derivatives = extensions.standardDerivatives;
+ resources.EXT_draw_buffers = extensions.drawBuffers;
+ resources.EXT_shader_texture_lod = 1;
+ // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
+ resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
+ resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
+ // GLSL ES 3.0 constants
+ resources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4;
+ resources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
+ resources.MinProgramTexelOffset = caps.minProgramTexelOffset;
+ resources.MaxProgramTexelOffset = caps.maxProgramTexelOffset;
+
+ mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
+ mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
+ }
+ }
+}
+
+void ShaderD3D::releaseCompiler()
+{
+ ShDestruct(mFragmentCompiler);
+ ShDestruct(mVertexCompiler);
+
+ mFragmentCompiler = NULL;
+ mVertexCompiler = NULL;
+
+ ShFinalize();
+}
+
+void ShaderD3D::parseVaryings(void *compiler)
+{
+ if (!mHlsl.empty())
+ {
+ const std::vector<sh::Varying> *varyings = ShGetVaryings(compiler);
+ ASSERT(varyings);
+
+ for (size_t varyingIndex = 0; varyingIndex < varyings->size(); varyingIndex++)
+ {
+ mVaryings.push_back(gl::PackedVarying((*varyings)[varyingIndex]));
+ }
+
+ mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos;
+ mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos;
+ mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos;
+ mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos;
+ mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos;
+ mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos;
+ mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos;
+ mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos;
+ mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos;
+ mUsesDiscardRewriting = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
+ mUsesNestedBreak = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
+ }
+}
+
+void ShaderD3D::resetVaryingsRegisterAssignment()
+{
+ for (size_t varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++)
+ {
+ mVaryings[varyingIndex].resetRegisterAssignment();
+ }
+}
+
+// initialize/clean up previous state
+void ShaderD3D::uncompile()
+{
+ // set by compileToHLSL
+ mHlsl.clear();
+ mInfoLog.clear();
+
+ mUsesMultipleRenderTargets = false;
+ mUsesFragColor = false;
+ mUsesFragData = false;
+ mUsesFragCoord = false;
+ mUsesFrontFacing = false;
+ mUsesPointSize = false;
+ mUsesPointCoord = false;
+ mUsesDepthRange = false;
+ mUsesFragDepth = false;
+ mShaderVersion = 100;
+ mUsesDiscardRewriting = false;
+ mUsesNestedBreak = false;
+
+ mVaryings.clear();
+ mUniforms.clear();
+ mInterfaceBlocks.clear();
+ mActiveAttributes.clear();
+ mActiveOutputVariables.clear();
+}
+
+void ShaderD3D::compileToHLSL(void *compiler, const std::string &source)
+{
+ // ensure the compiler is loaded
+ initializeCompiler();
+
+ int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES);
+ std::string sourcePath;
+ if (gl::perfActive())
+ {
+ sourcePath = getTempPath();
+ writeFile(sourcePath.c_str(), source.c_str(), source.length());
+ compileOptions |= SH_LINE_DIRECTIVES;
+ }
+
+ int result;
+ if (sourcePath.empty())
+ {
+ const char* sourceStrings[] =
+ {
+ source.c_str(),
+ };
+
+ result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions);
+ }
+ else
+ {
+ const char* sourceStrings[] =
+ {
+ sourcePath.c_str(),
+ source.c_str(),
+ };
+
+ result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH);
+ }
+
+ size_t shaderVersion = 100;
+ ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion);
+
+ mShaderVersion = static_cast<int>(shaderVersion);
+
+ if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3)
+ {
+ mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts";
+ TRACE("\n%s", mInfoLog.c_str());
+ }
+ else if (result)
+ {
+ size_t objCodeLen = 0;
+ ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
+
+ char* outputHLSL = new char[objCodeLen];
+ ShGetObjectCode(compiler, outputHLSL);
+
+#ifdef _DEBUG
+ std::ostringstream hlslStream;
+ hlslStream << "// GLSL\n";
+ hlslStream << "//\n";
+
+ size_t curPos = 0;
+ while (curPos != std::string::npos)
+ {
+ size_t nextLine = source.find("\n", curPos);
+ size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);
+
+ hlslStream << "// " << source.substr(curPos, len);
+
+ curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
+ }
+ hlslStream << "\n\n";
+ hlslStream << outputHLSL;
+ mHlsl = hlslStream.str();
+#else
+ mHlsl = outputHLSL;
+#endif
+
+ SafeDeleteArray(outputHLSL);
+
+ mUniforms = *GetShaderVariables(ShGetUniforms(compiler));
+
+ for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+ {
+ const sh::Uniform &uniform = mUniforms[uniformIndex];
+
+ if (uniform.staticUse)
+ {
+ unsigned int index = -1;
+ bool result = ShGetUniformRegister(compiler, uniform.name.c_str(), &index);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(result);
+
+ mUniformRegisterMap[uniform.name] = index;
+ }
+ }
+
+ mInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler));
+
+ for (size_t blockIndex = 0; blockIndex < mInterfaceBlocks.size(); blockIndex++)
+ {
+ const sh::InterfaceBlock &interfaceBlock = mInterfaceBlocks[blockIndex];
+
+ if (interfaceBlock.staticUse)
+ {
+ unsigned int index = -1;
+ bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name.c_str(), &index);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(result);
+
+ mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
+ }
+ }
+ }
+ else
+ {
+ size_t infoLogLen = 0;
+ ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
+
+ char* infoLog = new char[infoLogLen];
+ ShGetInfoLog(compiler, infoLog);
+ mInfoLog = infoLog;
+
+ TRACE("\n%s", mInfoLog.c_str());
+ }
+}
+
+rx::D3DWorkaroundType ShaderD3D::getD3DWorkarounds() const
+{
+ if (mUsesDiscardRewriting)
+ {
+ // ANGLE issue 486:
+ // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
+ return rx::ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION;
+ }
+
+ 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
+ return rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION;
+ }
+
+ return rx::ANGLE_D3D_WORKAROUND_NONE;
+}
+
+// true if varying x has a higher priority in packing than y
+bool ShaderD3D::compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &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);
+}
+
+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;
+}
+
+void *ShaderD3D::getCompiler()
+{
+ if (mType == GL_VERTEX_SHADER)
+ {
+ return mVertexCompiler;
+ }
+ else
+ {
+ ASSERT(mType == GL_FRAGMENT_SHADER);
+ return mFragmentCompiler;
+ }
+}
+
+ShShaderOutput ShaderD3D::getCompilerOutputType(GLenum shader)
+{
+ void *compiler = NULL;
+
+ switch (shader)
+ {
+ case GL_VERTEX_SHADER: compiler = mVertexCompiler; break;
+ case GL_FRAGMENT_SHADER: compiler = mFragmentCompiler; break;
+ default: UNREACHABLE(); return SH_HLSL9_OUTPUT;
+ }
+
+ size_t outputType = 0;
+ ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType);
+
+ return static_cast<ShShaderOutput>(outputType);
+}
+
+bool ShaderD3D::compile(const std::string &source)
+{
+ uncompile();
+
+ void *compiler = getCompiler();
+
+ compileToHLSL(compiler, source);
+
+ if (mType == GL_VERTEX_SHADER)
+ {
+ parseAttributes(compiler);
+ }
+
+ parseVaryings(compiler);
+
+ if (mType == GL_FRAGMENT_SHADER)
+ {
+ std::sort(mVaryings.begin(), mVaryings.end(), compareVarying);
+
+ const std::string &hlsl = getTranslatedSource();
+ if (!hlsl.empty())
+ {
+ mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(compiler));
+ FilterInactiveVariables(&mActiveOutputVariables);
+ }
+ }
+
+ return !getTranslatedSource().empty();
+}
+
+void ShaderD3D::parseAttributes(void *compiler)
+{
+ const std::string &hlsl = getTranslatedSource();
+ if (!hlsl.empty())
+ {
+ mActiveAttributes = *GetShaderVariables(ShGetAttributes(compiler));
+ FilterInactiveVariables(&mActiveAttributes);
+ }
+}
+
+int ShaderD3D::getSemanticIndex(const std::string &attributeName) const
+{
+ if (!attributeName.empty())
+ {
+ int semanticIndex = 0;
+ for (size_t attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++)
+ {
+ const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex];
+
+ if (attribute.name == attributeName)
+ {
+ return semanticIndex;
+ }
+
+ semanticIndex += gl::VariableRegisterCount(attribute.type);
+ }
+ }
+
+ return -1;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h
new file mode 100644
index 0000000000..40e64cf36c
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.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.
+//
+
+// ShaderD3D.h: Defines the rx::ShaderD3D class which implements rx::ShaderImpl.
+
+#ifndef LIBGLESV2_RENDERER_SHADERD3D_H_
+#define LIBGLESV2_RENDERER_SHADERD3D_H_
+
+#include "libGLESv2/renderer/ShaderImpl.h"
+#include "libGLESv2/Shader.h"
+
+#include <map>
+
+namespace rx
+{
+class DynamicHLSL;
+class Renderer;
+
+class ShaderD3D : public ShaderImpl
+{
+ friend class DynamicHLSL;
+
+ public:
+ ShaderD3D(GLenum type, rx::Renderer *renderer);
+ virtual ~ShaderD3D();
+
+ static ShaderD3D *makeShaderD3D(ShaderImpl *impl);
+ static const ShaderD3D *makeShaderD3D(const ShaderImpl *impl);
+
+ // ShaderImpl implementation
+ const std::string &getInfoLog() const { return mInfoLog; }
+ const std::string &getTranslatedSource() const { return mHlsl; }
+
+ // D3D-specific methods
+ virtual void uncompile();
+ void resetVaryingsRegisterAssignment();
+ unsigned int getUniformRegister(const std::string &uniformName) const;
+ unsigned int getInterfaceBlockRegister(const std::string &blockName) const;
+ int getSemanticIndex(const std::string &attributeName) const;
+
+ rx::D3DWorkaroundType getD3DWorkarounds() const;
+ int getShaderVersion() const { return mShaderVersion; }
+ bool usesDepthRange() const { return mUsesDepthRange; }
+ bool usesPointSize() const { return mUsesPointSize; }
+
+ static void releaseCompiler();
+ static ShShaderOutput getCompilerOutputType(GLenum shader);
+
+ virtual bool compile(const std::string &source);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShaderD3D);
+
+ void compileToHLSL(void *compiler, const std::string &source);
+ void parseVaryings(void *compiler);
+
+ void initializeCompiler();
+ void parseAttributes(void *compiler);
+ void *getCompiler();
+
+ static bool compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &y);
+
+ static void *mFragmentCompiler;
+ static void *mVertexCompiler;
+
+ GLenum mType;
+ rx::Renderer *mRenderer;
+
+ int mShaderVersion;
+
+ bool mUsesMultipleRenderTargets;
+ bool mUsesFragColor;
+ bool mUsesFragData;
+ bool mUsesFragCoord;
+ bool mUsesFrontFacing;
+ bool mUsesPointSize;
+ bool mUsesPointCoord;
+ bool mUsesDepthRange;
+ bool mUsesFragDepth;
+ bool mUsesDiscardRewriting;
+ bool mUsesNestedBreak;
+
+ std::string mHlsl;
+ std::string mInfoLog;
+ std::map<std::string, unsigned int> mUniformRegisterMap;
+ std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_SHADERD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp
new file mode 100644
index 0000000000..96c84977cb
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp
@@ -0,0 +1,2260 @@
+//
+// 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 "libGLESv2/renderer/d3d/TextureD3D.h"
+#include "libGLESv2/renderer/d3d/TextureStorage.h"
+#include "libGLESv2/renderer/d3d/ImageD3D.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/formatutils.h"
+#include "libGLESv2/renderer/BufferImpl.h"
+#include "libGLESv2/renderer/RenderTarget.h"
+#include "libGLESv2/renderer/Renderer.h"
+
+#include "libEGL/Surface.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+namespace rx
+{
+
+bool IsRenderTargetUsage(GLenum usage)
+{
+ return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+}
+
+TextureD3D::TextureD3D(Renderer *renderer)
+ : mRenderer(renderer),
+ mUsage(GL_NONE),
+ mDirtyImages(true),
+ mImmutable(false)
+{
+}
+
+TextureD3D::~TextureD3D()
+{
+}
+
+TextureD3D *TextureD3D::makeTextureD3D(TextureImpl *texture)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(TextureD3D*, texture));
+ return static_cast<TextureD3D*>(texture);
+}
+
+TextureStorage *TextureD3D::getNativeTexture()
+{
+ // ensure the underlying texture is created
+ initializeStorage(false);
+
+ TextureStorage *storage = getBaseLevelStorage();
+ if (storage)
+ {
+ updateStorage();
+ }
+
+ return storage;
+}
+
+GLint TextureD3D::getBaseLevelWidth() const
+{
+ const Image *baseImage = getBaseLevelImage();
+ return (baseImage ? baseImage->getWidth() : 0);
+}
+
+GLint TextureD3D::getBaseLevelHeight() const
+{
+ const Image *baseImage = getBaseLevelImage();
+ return (baseImage ? baseImage->getHeight() : 0);
+}
+
+GLint TextureD3D::getBaseLevelDepth() const
+{
+ const Image *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 Image *baseImage = getBaseLevelImage();
+ return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
+}
+
+void TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, Image *image)
+{
+ // No-op
+ if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
+ {
+ return;
+ }
+
+ // 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 void *pixelData = pixels;
+
+ 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: setImage/subImage 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.
+ const void *bufferData = pixelBuffer->getImplementation()->getData();
+ pixelData = static_cast<const unsigned char *>(bufferData) + offset;
+ }
+
+ if (pixelData != NULL)
+ {
+ image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData);
+ mDirtyImages = true;
+ }
+}
+
+bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index)
+{
+ const void *pixelData = pixels;
+
+ // CPU readback & copy where direct GPU copy is not supported
+ if (unpack.pixelBuffer.id() != 0)
+ {
+ gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
+ ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
+ // TODO: setImage/subImage 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.
+ const void *bufferData = pixelBuffer->getImplementation()->getData();
+ pixelData = static_cast<const unsigned char *>(bufferData) + offset;
+ }
+
+ if (pixelData != NULL)
+ {
+ Image *image = getImage(index);
+ ASSERT(image);
+
+ image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, type, pixelData);
+ mDirtyImages = true;
+ }
+
+ return true;
+}
+
+void TextureD3D::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)
+{
+ if (pixels != NULL)
+ {
+ image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixels);
+ mDirtyImages = true;
+ }
+}
+
+bool TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLsizei imageSize, const void *pixels, Image *image)
+{
+ if (pixels != NULL)
+ {
+ image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixels);
+ mDirtyImages = true;
+ }
+
+ return true;
+}
+
+bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat)
+{
+ return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
+}
+
+bool TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
+ GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget)
+{
+ if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
+ {
+ return true;
+ }
+
+ // 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));
+
+ ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
+
+ return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea);
+}
+
+GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
+{
+ if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) || mRenderer->getRendererExtensions().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;
+ }
+}
+
+int TextureD3D::mipLevels() const
+{
+ return gl::log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
+}
+
+
+TextureD3D_2D::TextureD3D_2D(Renderer *renderer)
+ : TextureD3D(renderer),
+ mTexStorage(NULL)
+{
+ for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+ {
+ mImageArray[i] = ImageD3D::makeImageD3D(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);
+}
+
+Image *TextureD3D_2D::getImage(int level, int layer) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(layer == 0);
+ return mImageArray[level];
+}
+
+Image *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;
+}
+
+GLenum TextureD3D_2D::getActualFormat(GLint level) const
+{
+ if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[level]->getActualFormat();
+ else
+ return GL_NONE;
+}
+
+bool TextureD3D_2D::isDepth(GLint level) const
+{
+ return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+}
+
+void TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D && depth == 1);
+
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+
+ bool fastUnpacked = false;
+
+ redefineImage(level, sizedInternalFormat, width, height);
+
+ // Attempt a fast gpu copy of the pixel data to the surface
+ if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level))
+ {
+ gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+
+ // Will try to create RT storage if it does not exist
+ RenderTarget *destRenderTarget = getRenderTarget(index);
+ gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
+
+ if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget))
+ {
+ // Ensure we don't overwrite our newly initialized data
+ mImageArray[level]->markClean();
+
+ fastUnpacked = true;
+ }
+ }
+
+ if (!fastUnpacked)
+ {
+ TextureD3D::setImage(unpack, type, pixels, mImageArray[level]);
+ }
+}
+
+void TextureD3D_2D::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D && depth == 1);
+
+ // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+ redefineImage(level, format, width, height);
+
+ TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]);
+}
+
+void TextureD3D_2D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0);
+
+ bool fastUnpacked = false;
+
+ gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+ if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
+ {
+ RenderTarget *renderTarget = getRenderTarget(index);
+ gl::Box destArea(xoffset, yoffset, 0, width, height, 1);
+
+ if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget))
+ {
+ // Ensure we don't overwrite our newly initialized data
+ mImageArray[level]->markClean();
+
+ fastUnpacked = true;
+ }
+ }
+
+ if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index))
+ {
+ commitRect(level, xoffset, yoffset, width, height);
+ }
+}
+
+void TextureD3D_2D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0);
+
+ if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[level]))
+ {
+ commitRect(level, xoffset, yoffset, width, height);
+ }
+}
+
+void TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+{
+ ASSERT(target == GL_TEXTURE_2D);
+
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
+ redefineImage(level, sizedInternalFormat, width, height);
+
+ if (!mImageArray[level]->isRenderableFormat())
+ {
+ mImageArray[level]->copy(0, 0, 0, x, y, width, height, source);
+ mDirtyImages = true;
+ }
+ else
+ {
+ ensureRenderTarget();
+ mImageArray[level]->markClean();
+
+ if (width != 0 && height != 0 && isValidLevel(level))
+ {
+ gl::Rectangle sourceRect;
+ sourceRect.x = x;
+ sourceRect.width = width;
+ sourceRect.y = y;
+ sourceRect.height = height;
+
+ mRenderer->copyImage2D(source, sourceRect, format, 0, 0, mTexStorage, level);
+ }
+ }
+}
+
+void TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+{
+ ASSERT(target == GL_TEXTURE_2D && zoffset == 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)
+ bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
+
+ if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
+ {
+ mImageArray[level]->copy(xoffset, yoffset, 0, x, y, width, height, source);
+ mDirtyImages = true;
+ }
+ else
+ {
+ ensureRenderTarget();
+
+ if (isValidLevel(level))
+ {
+ updateStorageLevel(level);
+
+ gl::Rectangle sourceRect;
+ sourceRect.x = x;
+ sourceRect.width = width;
+ sourceRect.y = y;
+ sourceRect.height = height;
+
+ mRenderer->copyImage2D(source, sourceRect,
+ gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
+ xoffset, yoffset, mTexStorage, level);
+ }
+ }
+}
+
+void TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+{
+ ASSERT(target == GL_TEXTURE_2D && depth == 1);
+
+ for (int level = 0; level < levels; level++)
+ {
+ GLsizei levelWidth = std::max(1, width >> level);
+ GLsizei levelHeight = std::max(1, height >> level);
+ mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, levelWidth, levelHeight, 1, true);
+ }
+
+ for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
+ }
+
+ mImmutable = true;
+
+ bool renderTarget = IsRenderTargetUsage(mUsage);
+ TextureStorage *storage = mRenderer->createTextureStorage2D(internalformat, renderTarget, width, height, levels);
+ setCompleteTexStorage(storage);
+}
+
+void TextureD3D_2D::bindTexImage(egl::Surface *surface)
+{
+ GLenum internalformat = surface->getFormat();
+
+ mImageArray[0]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, surface->getWidth(), surface->getHeight(), 1, true);
+
+ if (mTexStorage)
+ {
+ SafeDelete(mTexStorage);
+ }
+
+ mTexStorage = mRenderer->createTextureStorage2D(surface->getSwapChain());
+
+ mDirtyImages = true;
+}
+
+void TextureD3D_2D::releaseTexImage()
+{
+ if (mTexStorage)
+ {
+ SafeDelete(mTexStorage);
+ }
+
+ for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mImageArray[i]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
+ }
+}
+
+void TextureD3D_2D::generateMipmaps()
+{
+ // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
+ int levelCount = mipLevels();
+ for (int level = 1; level < levelCount; level++)
+ {
+ redefineImage(level, getBaseLevelInternalFormat(),
+ std::max(getBaseLevelWidth() >> level, 1),
+ std::max(getBaseLevelHeight() >> level, 1));
+ }
+
+ if (mTexStorage && mTexStorage->isRenderTarget())
+ {
+ mTexStorage->generateMipmaps();
+ for (int level = 1; level < levelCount; level++)
+ {
+ mImageArray[level]->markClean();
+ }
+ }
+ else
+ {
+ for (int level = 1; level < levelCount; level++)
+ {
+ mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]);
+ }
+ }
+}
+
+unsigned int TextureD3D_2D::getRenderTargetSerial(const gl::ImageIndex &index)
+{
+ ASSERT(!index.hasLayer());
+ return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0);
+}
+
+RenderTarget *TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index)
+{
+ ASSERT(!index.hasLayer());
+
+ // ensure the underlying texture is created
+ if (!ensureRenderTarget())
+ {
+ return NULL;
+ }
+
+ updateStorageLevel(index.mipIndex);
+ return mTexStorage->getRenderTarget(index);
+}
+
+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;
+ }
+
+ const Image *baseImage = getBaseLevelImage();
+
+ GLsizei width = baseImage->getWidth();
+ GLsizei height = baseImage->getHeight();
+
+ if (width <= 0 || height <= 0)
+ {
+ return false;
+ }
+
+ // The base image level is complete if the width and height are positive
+ if (level == 0)
+ {
+ return true;
+ }
+
+ ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
+ ImageD3D *image = mImageArray[level];
+
+ if (image->getInternalFormat() != baseImage->getInternalFormat())
+ {
+ return false;
+ }
+
+ if (image->getWidth() != std::max(1, width >> level))
+ {
+ return false;
+ }
+
+ if (image->getHeight() != std::max(1, height >> level))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Constructs a native texture resource from the texture images
+void TextureD3D_2D::initializeStorage(bool renderTarget)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return;
+ }
+
+ // do not attempt to create storage for nonexistant data
+ if (!isLevelComplete(0))
+ {
+ return;
+ }
+
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
+
+ setCompleteTexStorage(createCompleteStorage(createRenderTarget));
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ updateStorage();
+}
+
+TextureStorage *TextureD3D_2D::createCompleteStorage(bool renderTarget) const
+{
+ GLsizei width = getBaseLevelWidth();
+ GLsizei height = getBaseLevelHeight();
+ 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));
+
+ return mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels);
+}
+
+void TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+ SafeDelete(mTexStorage);
+ mTexStorage = newCompleteTexStorage;
+
+ if (mTexStorage && mTexStorage->isManaged())
+ {
+ for (int level = 0; level < mTexStorage->getLevelCount(); level++)
+ {
+ mImageArray[level]->setManagedSurface2D(mTexStorage, level);
+ }
+ }
+
+ mDirtyImages = true;
+}
+
+void TextureD3D_2D::updateStorage()
+{
+ ASSERT(mTexStorage != NULL);
+ GLint storageLevels = mTexStorage->getLevelCount();
+ for (int level = 0; level < storageLevels; level++)
+ {
+ if (mImageArray[level]->isDirty() && isLevelComplete(level))
+ {
+ updateStorageLevel(level);
+ }
+ }
+}
+
+bool TextureD3D_2D::ensureRenderTarget()
+{
+ initializeStorage(true);
+
+ if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0)
+ {
+ ASSERT(mTexStorage);
+ if (!mTexStorage->isRenderTarget())
+ {
+ TextureStorage *newRenderTargetStorage = createCompleteStorage(true);
+
+ if (!mRenderer->copyToRenderTarget2D(newRenderTargetStorage, mTexStorage))
+ {
+ delete newRenderTargetStorage;
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ setCompleteTexStorage(newRenderTargetStorage);
+ }
+ }
+
+ return (mTexStorage && mTexStorage->isRenderTarget());
+}
+
+TextureStorage *TextureD3D_2D::getBaseLevelStorage()
+{
+ return mTexStorage;
+}
+
+const ImageD3D *TextureD3D_2D::getBaseLevelImage() const
+{
+ return mImageArray[0];
+}
+
+void TextureD3D_2D::updateStorageLevel(int level)
+{
+ ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
+ ASSERT(isLevelComplete(level));
+
+ if (mImageArray[level]->isDirty())
+ {
+ commitRect(level, 0, 0, getWidth(level), getHeight(level));
+ }
+}
+
+void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ // If there currently is a corresponding storage texture image, it has these parameters
+ const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
+ const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
+ const GLenum storageFormat = getBaseLevelInternalFormat();
+
+ mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, width, height, 1, false);
+
+ if (mTexStorage)
+ {
+ const int storageLevels = mTexStorage->getLevelCount();
+
+ if ((level >= storageLevels && storageLevels != 0) ||
+ width != storageWidth ||
+ height != storageHeight ||
+ internalformat != storageFormat) // Discard mismatched storage
+ {
+ for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mImageArray[i]->markDirty();
+ }
+
+ SafeDelete(mTexStorage);
+ mDirtyImages = true;
+ }
+ }
+}
+
+void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ if (isValidLevel(level))
+ {
+ ImageD3D *image = mImageArray[level];
+ if (image->copyToStorage2D(mTexStorage, level, xoffset, yoffset, width, height))
+ {
+ image->markClean();
+ }
+ }
+}
+
+
+TextureD3D_Cube::TextureD3D_Cube(Renderer *renderer)
+ : TextureD3D(renderer),
+ mTexStorage(NULL)
+{
+ for (int i = 0; i < 6; i++)
+ {
+ for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
+ {
+ mImageArray[i][j] = ImageD3D::makeImageD3D(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);
+}
+
+Image *TextureD3D_Cube::getImage(int level, int layer) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(layer < 6);
+ return mImageArray[layer][level];
+}
+
+Image *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const
+{
+ ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(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;
+}
+
+void TextureD3D_Cube::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+{
+ ASSERT(depth == 1);
+
+ int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+
+ redefineImage(faceIndex, level, sizedInternalFormat, width, height);
+
+ TextureD3D::setImage(unpack, type, pixels, mImageArray[faceIndex][level]);
+}
+
+void TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+{
+ ASSERT(depth == 1);
+
+ // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+ int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
+
+ redefineImage(faceIndex, level, format, width, height);
+
+ TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[faceIndex][level]);
+}
+
+void TextureD3D_Cube::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+{
+ ASSERT(depth == 1 && zoffset == 0);
+
+ int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
+
+ gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
+ if (TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index))
+ {
+ commitRect(faceIndex, level, xoffset, yoffset, width, height);
+ }
+}
+
+void TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
+{
+ ASSERT(depth == 1 && zoffset == 0);
+
+ int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
+
+ if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[faceIndex][level]))
+ {
+ commitRect(faceIndex, level, xoffset, yoffset, width, height);
+ }
+}
+
+void TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+{
+ int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
+
+ redefineImage(faceIndex, level, sizedInternalFormat, width, height);
+
+ if (!mImageArray[faceIndex][level]->isRenderableFormat())
+ {
+ mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source);
+ mDirtyImages = true;
+ }
+ else
+ {
+ ensureRenderTarget();
+ mImageArray[faceIndex][level]->markClean();
+
+ ASSERT(width == height);
+
+ if (width > 0 && isValidFaceLevel(faceIndex, level))
+ {
+ gl::Rectangle sourceRect;
+ sourceRect.x = x;
+ sourceRect.width = width;
+ sourceRect.y = y;
+ sourceRect.height = height;
+
+ mRenderer->copyImageCube(source, sourceRect, format, 0, 0, mTexStorage, target, level);
+ }
+ }
+}
+
+void TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+{
+ int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
+
+ // We can only make our texture storage to a render target if the level we're copying *to* is complete
+ // and the base level is cube-complete. The base level must be cube complete (common case) because we cannot
+ // rely on the "getBaseLevel*" methods reliably otherwise.
+ bool canCreateRenderTarget = isFaceLevelComplete(faceIndex, level) && isCubeComplete();
+
+ if (!mImageArray[faceIndex][level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
+ {
+ mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source);
+ mDirtyImages = true;
+ }
+ else
+ {
+ ensureRenderTarget();
+
+ if (isValidFaceLevel(faceIndex, level))
+ {
+ updateStorageFaceLevel(faceIndex, level);
+
+ gl::Rectangle sourceRect;
+ sourceRect.x = x;
+ sourceRect.width = width;
+ sourceRect.y = y;
+ sourceRect.height = height;
+
+ mRenderer->copyImageCube(source, sourceRect, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
+ xoffset, yoffset, mTexStorage, target, level);
+ }
+ }
+}
+
+void TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+{
+ ASSERT(width == height);
+ ASSERT(depth == 1);
+
+ for (int level = 0; level < levels; level++)
+ {
+ GLsizei mipSize = std::max(1, width >> level);
+ for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+ {
+ mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, mipSize, mipSize, 1, true);
+ }
+ }
+
+ for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+ {
+ mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, GL_NONE, 0, 0, 0, true);
+ }
+ }
+
+ mImmutable = true;
+
+ bool renderTarget = IsRenderTargetUsage(mUsage);
+ TextureStorage *storage = mRenderer->createTextureStorageCube(internalformat, renderTarget, width, levels);
+ setCompleteTexStorage(storage);
+}
+
+// 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][0];
+
+ 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::generateMipmaps()
+{
+ // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
+ int levelCount = mipLevels();
+ for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+ {
+ for (int level = 1; level < levelCount; level++)
+ {
+ int faceLevelSize = (std::max(mImageArray[faceIndex][0]->getWidth() >> level, 1));
+ redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), faceLevelSize, faceLevelSize);
+ }
+ }
+
+ if (mTexStorage && mTexStorage->isRenderTarget())
+ {
+ mTexStorage->generateMipmaps();
+
+ for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+ {
+ for (int level = 1; level < levelCount; level++)
+ {
+ mImageArray[faceIndex][level]->markClean();
+ }
+ }
+ }
+ else
+ {
+ for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+ {
+ for (int level = 1; level < levelCount; level++)
+ {
+ mRenderer->generateMipmap(mImageArray[faceIndex][level], mImageArray[faceIndex][level - 1]);
+ }
+ }
+ }
+}
+
+unsigned int TextureD3D_Cube::getRenderTargetSerial(const gl::ImageIndex &index)
+{
+ return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0);
+}
+
+RenderTarget *TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index)
+{
+ ASSERT(gl::IsCubemapTextureTarget(index.type));
+
+ // ensure the underlying texture is created
+ if (!ensureRenderTarget())
+ {
+ return NULL;
+ }
+
+ updateStorageFaceLevel(index.layerIndex, index.mipIndex);
+ return mTexStorage->getRenderTarget(index);
+}
+
+void TextureD3D_Cube::initializeStorage(bool renderTarget)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return;
+ }
+
+ // do not attempt to create storage for nonexistant data
+ if (!isFaceLevelComplete(0, 0))
+ {
+ return;
+ }
+
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
+
+ setCompleteTexStorage(createCompleteStorage(createRenderTarget));
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ updateStorage();
+}
+
+TextureStorage *TextureD3D_Cube::createCompleteStorage(bool renderTarget) const
+{
+ GLsizei size = getBaseLevelWidth();
+
+ ASSERT(size > 0);
+
+ // use existing storage level count, when previously specified by TexStorage*D
+ GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1));
+
+ return mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels);
+}
+
+void TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+{
+ SafeDelete(mTexStorage);
+ mTexStorage = newCompleteTexStorage;
+
+ if (mTexStorage && mTexStorage->isManaged())
+ {
+ for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+ {
+ for (int level = 0; level < mTexStorage->getLevelCount(); level++)
+ {
+ mImageArray[faceIndex][level]->setManagedSurfaceCube(mTexStorage, faceIndex, level);
+ }
+ }
+ }
+
+ mDirtyImages = true;
+}
+
+void 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))
+ {
+ updateStorageFaceLevel(face, level);
+ }
+ }
+ }
+}
+
+bool TextureD3D_Cube::ensureRenderTarget()
+{
+ initializeStorage(true);
+
+ if (getBaseLevelWidth() > 0)
+ {
+ ASSERT(mTexStorage);
+ if (!mTexStorage->isRenderTarget())
+ {
+ TextureStorage *newRenderTargetStorage = createCompleteStorage(true);
+
+ if (!mRenderer->copyToRenderTargetCube(newRenderTargetStorage, mTexStorage))
+ {
+ delete newRenderTargetStorage;
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ setCompleteTexStorage(newRenderTargetStorage);
+ }
+ }
+
+ return (mTexStorage && mTexStorage->isRenderTarget());
+}
+
+TextureStorage *TextureD3D_Cube::getBaseLevelStorage()
+{
+ return mTexStorage;
+}
+
+const ImageD3D *TextureD3D_Cube::getBaseLevelImage() const
+{
+ // Note: if we are not cube-complete, there is no single base level image that can describe all
+ // cube faces, so this method is only well-defined for a cube-complete base level.
+ return mImageArray[0][0];
+}
+
+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
+{
+ ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL);
+
+ if (isImmutable())
+ {
+ return true;
+ }
+
+ int baseSize = getBaseLevelWidth();
+
+ if (baseSize <= 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, baseSize >> level))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void 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())
+ {
+ commitRect(faceIndex, level, 0, 0, image->getWidth(), image->getHeight());
+ }
+}
+
+void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ // If there currently is a corresponding storage texture image, it has these parameters
+ const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
+ const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
+ const GLenum storageFormat = getBaseLevelInternalFormat();
+
+ mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, width, height, 1, false);
+
+ if (mTexStorage)
+ {
+ const int storageLevels = mTexStorage->getLevelCount();
+
+ if ((level >= storageLevels && storageLevels != 0) ||
+ width != storageWidth ||
+ height != storageHeight ||
+ internalformat != storageFormat) // Discard mismatched storage
+ {
+ for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+ {
+ mImageArray[faceIndex][level]->markDirty();
+ }
+ }
+
+ SafeDelete(mTexStorage);
+
+ mDirtyImages = true;
+ }
+ }
+}
+
+void TextureD3D_Cube::commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ if (isValidFaceLevel(faceIndex, level))
+ {
+ ImageD3D *image = mImageArray[faceIndex][level];
+ if (image->copyToStorageCube(mTexStorage, faceIndex, level, xoffset, yoffset, width, height))
+ image->markClean();
+ }
+}
+
+
+TextureD3D_3D::TextureD3D_3D(Renderer *renderer)
+ : TextureD3D(renderer),
+ mTexStorage(NULL)
+{
+ for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+ {
+ mImageArray[i] = ImageD3D::makeImageD3D(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);
+}
+
+Image *TextureD3D_3D::getImage(int level, int layer) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(layer == 0);
+ return mImageArray[level];
+}
+
+Image *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;
+}
+
+void TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+{
+ ASSERT(target == GL_TEXTURE_3D);
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+
+ redefineImage(level, sizedInternalFormat, width, height, depth);
+
+ bool fastUnpacked = false;
+
+ // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
+ if (isFastUnpackable(unpack, sizedInternalFormat))
+ {
+ // Will try to create RT storage if it does not exist
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+ RenderTarget *destRenderTarget = getRenderTarget(index);
+ gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
+
+ if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget))
+ {
+ // Ensure we don't overwrite our newly initialized data
+ mImageArray[level]->markClean();
+
+ fastUnpacked = true;
+ }
+ }
+
+ if (!fastUnpacked)
+ {
+ TextureD3D::setImage(unpack, type, pixels, mImageArray[level]);
+ }
+}
+
+void TextureD3D_3D::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+{
+ ASSERT(target == GL_TEXTURE_3D);
+
+ // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+ redefineImage(level, format, width, height, depth);
+
+ TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]);
+}
+
+void TextureD3D_3D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+{
+ ASSERT(target == GL_TEXTURE_3D);
+
+ 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, getInternalFormat(level)))
+ {
+ RenderTarget *destRenderTarget = getRenderTarget(index);
+ gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth);
+
+ if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget))
+ {
+ // Ensure we don't overwrite our newly initialized data
+ mImageArray[level]->markClean();
+
+ fastUnpacked = true;
+ }
+ }
+
+ if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, index))
+ {
+ commitRect(level, xoffset, yoffset, zoffset, width, height, depth);
+ }
+}
+
+void TextureD3D_3D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
+{
+ ASSERT(target == GL_TEXTURE_3D);
+
+ if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, mImageArray[level]))
+ {
+ commitRect(level, xoffset, yoffset, zoffset, width, height, depth);
+ }
+}
+
+void TextureD3D_3D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+{
+ UNIMPLEMENTED();
+}
+
+void TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+{
+ ASSERT(target == GL_TEXTURE_3D);
+
+ // 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)
+ bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
+
+ if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
+ {
+ mImageArray[level]->copy(xoffset, yoffset, zoffset, x, y, width, height, source);
+ mDirtyImages = true;
+ }
+ else
+ {
+ ensureRenderTarget();
+
+ if (isValidLevel(level))
+ {
+ updateStorageLevel(level);
+
+ gl::Rectangle sourceRect;
+ sourceRect.x = x;
+ sourceRect.width = width;
+ sourceRect.y = y;
+ sourceRect.height = height;
+
+ mRenderer->copyImage3D(source, sourceRect,
+ gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
+ xoffset, yoffset, zoffset, mTexStorage, level);
+ }
+ }
+}
+
+void TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+{
+ ASSERT(target == GL_TEXTURE_3D);
+
+ for (int level = 0; level < levels; level++)
+ {
+ GLsizei levelWidth = std::max(1, width >> level);
+ GLsizei levelHeight = std::max(1, height >> level);
+ GLsizei levelDepth = std::max(1, depth >> level);
+ mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, levelWidth, levelHeight, levelDepth, true);
+ }
+
+ for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true);
+ }
+
+ mImmutable = true;
+
+ bool renderTarget = IsRenderTargetUsage(mUsage);
+ TextureStorage *storage = mRenderer->createTextureStorage3D(internalformat, renderTarget, width, height, depth, levels);
+ setCompleteTexStorage(storage);
+}
+
+void TextureD3D_3D::bindTexImage(egl::Surface *surface)
+{
+ UNREACHABLE();
+}
+
+void TextureD3D_3D::releaseTexImage()
+{
+ UNREACHABLE();
+}
+
+
+void TextureD3D_3D::generateMipmaps()
+{
+ // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
+ int levelCount = mipLevels();
+ for (int level = 1; level < levelCount; level++)
+ {
+ redefineImage(level, getBaseLevelInternalFormat(),
+ std::max(getBaseLevelWidth() >> level, 1),
+ std::max(getBaseLevelHeight() >> level, 1),
+ std::max(getBaseLevelDepth() >> level, 1));
+ }
+
+ if (mTexStorage && mTexStorage->isRenderTarget())
+ {
+ mTexStorage->generateMipmaps();
+
+ for (int level = 1; level < levelCount; level++)
+ {
+ mImageArray[level]->markClean();
+ }
+ }
+ else
+ {
+ for (int level = 1; level < levelCount; level++)
+ {
+ mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]);
+ }
+ }
+}
+
+unsigned int TextureD3D_3D::getRenderTargetSerial(const gl::ImageIndex &index)
+{
+ return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0);
+}
+
+RenderTarget *TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index)
+{
+ // ensure the underlying texture is created
+ if (!ensureRenderTarget())
+ {
+ return NULL;
+ }
+
+ if (index.hasLayer())
+ {
+ updateStorage();
+ }
+ else
+ {
+ updateStorageLevel(index.mipIndex);
+ }
+
+ return mTexStorage->getRenderTarget(index);
+}
+
+void TextureD3D_3D::initializeStorage(bool renderTarget)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return;
+ }
+
+ // do not attempt to create storage for nonexistant data
+ if (!isLevelComplete(0))
+ {
+ return;
+ }
+
+ bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+
+ setCompleteTexStorage(createCompleteStorage(createRenderTarget));
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ updateStorage();
+}
+
+TextureStorage *TextureD3D_3D::createCompleteStorage(bool renderTarget) const
+{
+ GLsizei width = getBaseLevelWidth();
+ GLsizei height = getBaseLevelHeight();
+ GLsizei depth = getBaseLevelDepth();
+ 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));
+
+ return mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels);
+}
+
+void 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());
+}
+
+void TextureD3D_3D::updateStorage()
+{
+ ASSERT(mTexStorage != NULL);
+ GLint storageLevels = mTexStorage->getLevelCount();
+ for (int level = 0; level < storageLevels; level++)
+ {
+ if (mImageArray[level]->isDirty() && isLevelComplete(level))
+ {
+ updateStorageLevel(level);
+ }
+ }
+}
+
+bool TextureD3D_3D::ensureRenderTarget()
+{
+ initializeStorage(true);
+
+ if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getBaseLevelDepth() > 0)
+ {
+ ASSERT(mTexStorage);
+ if (!mTexStorage->isRenderTarget())
+ {
+ TextureStorage *newRenderTargetStorage = createCompleteStorage(true);
+
+ if (!mRenderer->copyToRenderTarget3D(newRenderTargetStorage, mTexStorage))
+ {
+ delete newRenderTargetStorage;
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ setCompleteTexStorage(newRenderTargetStorage);
+ }
+ }
+
+ return (mTexStorage && mTexStorage->isRenderTarget());
+}
+
+TextureStorage *TextureD3D_3D::getBaseLevelStorage()
+{
+ return mTexStorage;
+}
+
+const ImageD3D *TextureD3D_3D::getBaseLevelImage() const
+{
+ return mImageArray[0];
+}
+
+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 = getBaseLevelWidth();
+ GLsizei height = getBaseLevelHeight();
+ GLsizei depth = getBaseLevelDepth();
+
+ if (width <= 0 || height <= 0 || depth <= 0)
+ {
+ return false;
+ }
+
+ if (level == 0)
+ {
+ 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;
+}
+
+void TextureD3D_3D::updateStorageLevel(int level)
+{
+ ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
+ ASSERT(isLevelComplete(level));
+
+ if (mImageArray[level]->isDirty())
+ {
+ commitRect(level, 0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
+ }
+}
+
+void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+{
+ // If there currently is a corresponding storage texture image, it has these parameters
+ const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
+ const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
+ const int storageDepth = std::max(1, getBaseLevelDepth() >> level);
+ const GLenum storageFormat = getBaseLevelInternalFormat();
+
+ mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, width, height, depth, false);
+
+ if (mTexStorage)
+ {
+ const int storageLevels = mTexStorage->getLevelCount();
+
+ if ((level >= storageLevels && storageLevels != 0) ||
+ width != storageWidth ||
+ height != storageHeight ||
+ depth != storageDepth ||
+ internalformat != storageFormat) // Discard mismatched storage
+ {
+ for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mImageArray[i]->markDirty();
+ }
+
+ SafeDelete(mTexStorage);
+ mDirtyImages = true;
+ }
+ }
+}
+
+void TextureD3D_3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
+{
+ if (isValidLevel(level))
+ {
+ ImageD3D *image = mImageArray[level];
+ if (image->copyToStorage3D(mTexStorage, level, xoffset, yoffset, zoffset, width, height, depth))
+ {
+ image->markClean();
+ }
+ }
+}
+
+
+TextureD3D_2DArray::TextureD3D_2DArray(Renderer *renderer)
+ : TextureD3D(renderer),
+ mTexStorage(NULL)
+{
+ 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);
+}
+
+Image *TextureD3D_2DArray::getImage(int level, int layer) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(layer < mLayerCounts[level]);
+ return mImageArray[level][layer];
+}
+
+Image *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const
+{
+ ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(index.layerIndex < mLayerCounts[index.mipIndex]);
+ ASSERT(index.type == GL_TEXTURE_2D_ARRAY);
+ return mImageArray[index.mipIndex][index.layerIndex];
+}
+
+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;
+}
+
+GLsizei TextureD3D_2DArray::getLayers(GLint level) const
+{
+ return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mLayerCounts[level] : 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;
+}
+
+void TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+
+ redefineImage(level, sizedInternalFormat, width, height, depth);
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment);
+
+ for (int i = 0; i < depth; i++)
+ {
+ const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
+ TextureD3D::setImage(unpack, type, layerPixels, mImageArray[level][i]);
+ }
+}
+
+void TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+ // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+ redefineImage(level, format, width, height, depth);
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
+
+ for (int i = 0; i < depth; i++)
+ {
+ const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
+ TextureD3D::setCompressedImage(imageSize, layerPixels, mImageArray[level][i]);
+ }
+}
+
+void TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level));
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment);
+
+ for (int i = 0; i < depth; i++)
+ {
+ int layer = zoffset + i;
+ const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
+
+ gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
+ if (TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, unpack, layerPixels, index))
+ {
+ commitRect(level, xoffset, yoffset, layer, width, height);
+ }
+ }
+}
+
+void TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
+
+ for (int i = 0; i < depth; i++)
+ {
+ int layer = zoffset + i;
+ const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
+
+ if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, layerPixels, mImageArray[level][layer]))
+ {
+ commitRect(level, xoffset, yoffset, layer, width, height);
+ }
+ }
+}
+
+void TextureD3D_2DArray::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+{
+ UNIMPLEMENTED();
+}
+
+void TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+{
+ ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+ // 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)
+ bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
+
+ if (!mImageArray[level][0]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
+ {
+ mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, x, y, width, height, source);
+ mDirtyImages = true;
+ }
+ else
+ {
+ ensureRenderTarget();
+
+ if (isValidLevel(level))
+ {
+ updateStorageLevel(level);
+
+ gl::Rectangle sourceRect;
+ sourceRect.x = x;
+ sourceRect.width = width;
+ sourceRect.y = y;
+ sourceRect.height = height;
+
+ mRenderer->copyImage2DArray(source, sourceRect, gl::GetInternalFormatInfo(getInternalFormat(0)).format,
+ xoffset, yoffset, zoffset, mTexStorage, level);
+ }
+ }
+}
+
+void TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+{
+ ASSERT(target == GL_TEXTURE_2D_ARRAY);
+
+ deleteImages();
+
+ for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ GLsizei levelWidth = std::max(1, width >> level);
+ GLsizei levelHeight = std::max(1, height >> level);
+
+ mLayerCounts[level] = (level < levels ? 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] = ImageD3D::makeImageD3D(mRenderer->createImage());
+ mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, levelWidth,
+ levelHeight, 1, true);
+ }
+ }
+ }
+
+ mImmutable = true;
+
+ bool renderTarget = IsRenderTargetUsage(mUsage);
+ TextureStorage *storage = mRenderer->createTextureStorage2DArray(internalformat, renderTarget, width, height, depth, levels);
+ setCompleteTexStorage(storage);
+}
+
+void TextureD3D_2DArray::bindTexImage(egl::Surface *surface)
+{
+ UNREACHABLE();
+}
+
+void TextureD3D_2DArray::releaseTexImage()
+{
+ UNREACHABLE();
+}
+
+
+void TextureD3D_2DArray::generateMipmaps()
+{
+ int baseWidth = getBaseLevelWidth();
+ int baseHeight = getBaseLevelHeight();
+ int baseDepth = getBaseLevelDepth();
+ GLenum baseFormat = getBaseLevelInternalFormat();
+
+ // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
+ int levelCount = mipLevels();
+ for (int level = 1; level < levelCount; level++)
+ {
+ redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth);
+ }
+
+ if (mTexStorage && mTexStorage->isRenderTarget())
+ {
+ mTexStorage->generateMipmaps();
+
+ for (int level = 1; level < levelCount; level++)
+ {
+ for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ {
+ mImageArray[level][layer]->markClean();
+ }
+ }
+ }
+ else
+ {
+ for (int level = 1; level < levelCount; level++)
+ {
+ for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ {
+ mRenderer->generateMipmap(mImageArray[level][layer], mImageArray[level - 1][layer]);
+ }
+ }
+ }
+}
+
+unsigned int TextureD3D_2DArray::getRenderTargetSerial(const gl::ImageIndex &index)
+{
+ return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0);
+}
+
+RenderTarget *TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index)
+{
+ // ensure the underlying texture is created
+ if (!ensureRenderTarget())
+ {
+ return NULL;
+ }
+
+ updateStorageLevel(index.mipIndex);
+ return mTexStorage->getRenderTarget(index);
+}
+
+void TextureD3D_2DArray::initializeStorage(bool renderTarget)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return;
+ }
+
+ // do not attempt to create storage for nonexistant data
+ if (!isLevelComplete(0))
+ {
+ return;
+ }
+
+ bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+
+ setCompleteTexStorage(createCompleteStorage(createRenderTarget));
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ updateStorage();
+}
+
+TextureStorage *TextureD3D_2DArray::createCompleteStorage(bool renderTarget) const
+{
+ GLsizei width = getBaseLevelWidth();
+ GLsizei height = getBaseLevelHeight();
+ GLsizei depth = getLayers(0);
+ 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));
+
+ return mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels);
+}
+
+void 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());
+}
+
+void TextureD3D_2DArray::updateStorage()
+{
+ ASSERT(mTexStorage != NULL);
+ GLint storageLevels = mTexStorage->getLevelCount();
+ for (int level = 0; level < storageLevels; level++)
+ {
+ if (isLevelComplete(level))
+ {
+ updateStorageLevel(level);
+ }
+ }
+}
+
+bool TextureD3D_2DArray::ensureRenderTarget()
+{
+ initializeStorage(true);
+
+ if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getLayers(0) > 0)
+ {
+ ASSERT(mTexStorage);
+ if (!mTexStorage->isRenderTarget())
+ {
+ TextureStorage *newRenderTargetStorage = createCompleteStorage(true);
+
+ if (!mRenderer->copyToRenderTarget2DArray(newRenderTargetStorage, mTexStorage))
+ {
+ delete newRenderTargetStorage;
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ setCompleteTexStorage(newRenderTargetStorage);
+ }
+ }
+
+ return (mTexStorage && mTexStorage->isRenderTarget());
+}
+
+const ImageD3D *TextureD3D_2DArray::getBaseLevelImage() const
+{
+ return (mLayerCounts[0] > 0 ? mImageArray[0][0] : NULL);
+}
+
+TextureStorage *TextureD3D_2DArray::getBaseLevelStorage()
+{
+ return mTexStorage;
+}
+
+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 = getBaseLevelWidth();
+ GLsizei height = getBaseLevelHeight();
+ GLsizei layers = getLayers(0);
+
+ if (width <= 0 || height <= 0 || layers <= 0)
+ {
+ return false;
+ }
+
+ if (level == 0)
+ {
+ return true;
+ }
+
+ if (getInternalFormat(level) != getInternalFormat(0))
+ {
+ return false;
+ }
+
+ if (getWidth(level) != std::max(1, width >> level))
+ {
+ return false;
+ }
+
+ if (getHeight(level) != std::max(1, height >> level))
+ {
+ return false;
+ }
+
+ if (getLayers(level) != layers)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void 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())
+ {
+ commitRect(level, 0, 0, layer, getWidth(level), getHeight(level));
+ }
+ }
+}
+
+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, GLsizei width, GLsizei height, GLsizei depth)
+{
+ // If there currently is a corresponding storage texture image, it has these parameters
+ const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
+ const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
+ const int storageDepth = getLayers(0);
+ const GLenum storageFormat = getBaseLevelInternalFormat();
+
+ for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ {
+ delete mImageArray[level][layer];
+ }
+ delete[] mImageArray[level];
+ mImageArray[level] = NULL;
+ mLayerCounts[level] = depth;
+
+ if (depth > 0)
+ {
+ mImageArray[level] = new ImageD3D*[depth]();
+
+ for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ {
+ mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage());
+ mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, width, height, 1, false);
+ }
+ }
+
+ if (mTexStorage)
+ {
+ const int storageLevels = mTexStorage->getLevelCount();
+
+ if ((level >= storageLevels && storageLevels != 0) ||
+ width != storageWidth ||
+ height != storageHeight ||
+ depth != storageDepth ||
+ internalformat != storageFormat) // Discard mismatched storage
+ {
+ for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ {
+ mImageArray[level][layer]->markDirty();
+ }
+ }
+
+ delete mTexStorage;
+ mTexStorage = NULL;
+ mDirtyImages = true;
+ }
+ }
+}
+
+void TextureD3D_2DArray::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height)
+{
+ if (isValidLevel(level) && layerTarget < getLayers(level))
+ {
+ ImageD3D *image = mImageArray[level][layerTarget];
+ if (image->copyToStorage2DArray(mTexStorage, level, xoffset, yoffset, layerTarget, width, height))
+ {
+ image->markClean();
+ }
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h
new file mode 100644
index 0000000000..41c73180de
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h
@@ -0,0 +1,320 @@
+//
+// 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 LIBGLESV2_RENDERER_TEXTURED3D_H_
+#define LIBGLESV2_RENDERER_TEXTURED3D_H_
+
+#include "libGLESv2/renderer/TextureImpl.h"
+#include "libGLESv2/angletypes.h"
+#include "libGLESv2/constants.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+
+class Image;
+class ImageD3D;
+class Renderer;
+class RenderTarget;
+class TextureStorage;
+
+class TextureD3D : public TextureImpl
+{
+ public:
+ TextureD3D(Renderer *renderer);
+ virtual ~TextureD3D();
+
+ static TextureD3D *makeTextureD3D(TextureImpl *texture);
+
+ virtual TextureStorage *getNativeTexture();
+
+ virtual void setUsage(GLenum usage) { mUsage = usage; }
+ bool hasDirtyImages() const { return mDirtyImages; }
+ void resetDirty() { mDirtyImages = false; }
+
+ GLint getBaseLevelWidth() const;
+ GLint getBaseLevelHeight() const;
+ GLint getBaseLevelDepth() const;
+ GLenum getBaseLevelInternalFormat() const;
+
+ bool isImmutable() const { return mImmutable; }
+
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0;
+ virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index) = 0;
+
+ protected:
+ void setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, Image *image);
+ bool subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index);
+ void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image);
+ bool subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLsizei imageSize, const void *pixels, Image *image);
+ bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat);
+ bool fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
+ GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget);
+
+ GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const;
+ int mipLevels() const;
+
+ Renderer *mRenderer;
+
+ GLenum mUsage;
+
+ bool mDirtyImages;
+
+ bool mImmutable;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureD3D);
+
+ virtual void initializeStorage(bool renderTarget) = 0;
+
+ virtual void updateStorage() = 0;
+ virtual TextureStorage *getBaseLevelStorage() = 0;
+ virtual const ImageD3D *getBaseLevelImage() const = 0;
+};
+
+class TextureD3D_2D : public TextureD3D
+{
+ public:
+ TextureD3D_2D(Renderer *renderer);
+ virtual ~TextureD3D_2D();
+
+ virtual Image *getImage(int level, int layer) const;
+ virtual Image *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;
+ GLenum getActualFormat(GLint level) const;
+ bool isDepth(GLint level) const;
+
+ virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+ virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
+ virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+ virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
+ virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+ virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+ virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+
+ virtual void bindTexImage(egl::Surface *surface);
+ virtual void releaseTexImage();
+
+ virtual void generateMipmaps();
+
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
+ virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureD3D_2D);
+
+ virtual void initializeStorage(bool renderTarget);
+ TextureStorage *createCompleteStorage(bool renderTarget) const;
+ void setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+
+ virtual void updateStorage();
+ bool ensureRenderTarget();
+ virtual TextureStorage *getBaseLevelStorage();
+ virtual const ImageD3D *getBaseLevelImage() const;
+
+ bool isValidLevel(int level) const;
+ bool isLevelComplete(int level) const;
+
+ void updateStorageLevel(int level);
+
+ void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height);
+ void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+ TextureStorage *mTexStorage;
+ ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureD3D_Cube : public TextureD3D
+{
+ public:
+ TextureD3D_Cube(Renderer *renderer);
+ virtual ~TextureD3D_Cube();
+
+ virtual Image *getImage(int level, int layer) const;
+ virtual Image *getImage(const gl::ImageIndex &index) const;
+ virtual GLsizei getLayerCount(int level) const;
+
+ virtual bool hasDirtyImages() const { return mDirtyImages; }
+ virtual void resetDirty() { mDirtyImages = false; }
+ virtual void setUsage(GLenum usage) { mUsage = usage; }
+
+ GLenum getInternalFormat(GLint level, GLint layer) const;
+ bool isDepth(GLint level, GLint layer) const;
+
+ virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+ virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
+ virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+ virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
+ virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+ virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+ virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+
+ virtual void bindTexImage(egl::Surface *surface);
+ virtual void releaseTexImage();
+
+ virtual void generateMipmaps();
+
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
+ virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureD3D_Cube);
+
+ virtual void initializeStorage(bool renderTarget);
+ TextureStorage *createCompleteStorage(bool renderTarget) const;
+ void setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+
+ virtual void updateStorage();
+ bool ensureRenderTarget();
+ virtual TextureStorage *getBaseLevelStorage();
+ virtual const ImageD3D *getBaseLevelImage() const;
+
+ bool isValidFaceLevel(int faceIndex, int level) const;
+ bool isFaceLevelComplete(int faceIndex, int level) const;
+ bool isCubeComplete() const;
+ void updateStorageFaceLevel(int faceIndex, int level);
+
+ void redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height);
+ void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+ ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ TextureStorage *mTexStorage;
+};
+
+class TextureD3D_3D : public TextureD3D
+{
+ public:
+ TextureD3D_3D(Renderer *renderer);
+ virtual ~TextureD3D_3D();
+
+ virtual Image *getImage(int level, int layer) const;
+ virtual Image *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;
+
+ virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+ virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
+ virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+ virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
+ virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+ virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+ virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+
+ virtual void bindTexImage(egl::Surface *surface);
+ virtual void releaseTexImage();
+
+ virtual void generateMipmaps();
+
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
+ virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureD3D_3D);
+
+ virtual void initializeStorage(bool renderTarget);
+ TextureStorage *createCompleteStorage(bool renderTarget) const;
+ void setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+
+ virtual void updateStorage();
+ bool ensureRenderTarget();
+ virtual TextureStorage *getBaseLevelStorage();
+ virtual const ImageD3D *getBaseLevelImage() const;
+
+ bool isValidLevel(int level) const;
+ bool isLevelComplete(int level) const;
+ void updateStorageLevel(int level);
+
+ void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+ void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+
+ ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ TextureStorage *mTexStorage;
+};
+
+class TextureD3D_2DArray : public TextureD3D
+{
+ public:
+ TextureD3D_2DArray(Renderer *renderer);
+ virtual ~TextureD3D_2DArray();
+
+ virtual Image *getImage(int level, int layer) const;
+ virtual Image *getImage(const gl::ImageIndex &index) const;
+ virtual GLsizei getLayerCount(int level) const;
+
+ GLsizei getWidth(GLint level) const;
+ GLsizei getHeight(GLint level) const;
+ GLsizei getLayers(GLint level) const;
+ GLenum getInternalFormat(GLint level) const;
+ bool isDepth(GLint level) const;
+
+ virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+ virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
+ virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+ virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
+ virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+ virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+ virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+
+ virtual void bindTexImage(egl::Surface *surface);
+ virtual void releaseTexImage();
+
+ virtual void generateMipmaps();
+
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
+ virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureD3D_2DArray);
+
+ virtual void initializeStorage(bool renderTarget);
+ TextureStorage *createCompleteStorage(bool renderTarget) const;
+ void setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+
+ virtual void updateStorage();
+ bool ensureRenderTarget();
+ virtual TextureStorage *getBaseLevelStorage();
+ virtual const ImageD3D *getBaseLevelImage() const;
+
+ bool isValidLevel(int level) const;
+ bool isLevelComplete(int level) const;
+ void updateStorageLevel(int level);
+
+ void deleteImages();
+ void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+ void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height);
+
+ // 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];
+
+ TextureStorage *mTexStorage;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_TEXTURED3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp
new file mode 100644
index 0000000000..dedd266c09
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp
@@ -0,0 +1,51 @@
+//
+// 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.cpp: Shared members of abstract rx::TextureStorage class.
+
+#include "libGLESv2/renderer/d3d/TextureStorage.h"
+#include "libGLESv2/renderer/d3d/TextureD3D.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/Texture.h"
+
+#include "common/debug.h"
+#include "common/mathutil.h"
+
+namespace rx
+{
+
+unsigned int TextureStorage::mCurrentTextureSerial = 1;
+
+TextureStorage::TextureStorage()
+ : mTextureSerial(issueTextureSerial()),
+ mFirstRenderTargetSerial(0),
+ mRenderTargetSerialsLayerStride(0)
+{}
+
+void TextureStorage::initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride)
+{
+ mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(rtSerialsToReserve);
+ mRenderTargetSerialsLayerStride = rtSerialsLayerStride;
+}
+
+unsigned int TextureStorage::getRenderTargetSerial(const gl::ImageIndex &index) const
+{
+ unsigned int layerOffset = (index.hasLayer() ? (static_cast<unsigned int>(index.layerIndex) * mRenderTargetSerialsLayerStride) : 0);
+ return mFirstRenderTargetSerial + static_cast<unsigned int>(index.mipIndex) + layerOffset;
+}
+
+unsigned int TextureStorage::getTextureSerial() const
+{
+ return mTextureSerial;
+}
+
+unsigned int TextureStorage::issueTextureSerial()
+{
+ return mCurrentTextureSerial++;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h
new file mode 100644
index 0000000000..9cc2c2977b
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h
@@ -0,0 +1,61 @@
+//
+// 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 LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
+#define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
+
+#include "common/debug.h"
+
+#include <GLES2/gl2.h>
+
+namespace gl
+{
+struct ImageIndex;
+}
+
+namespace rx
+{
+class Renderer;
+class SwapChain;
+class RenderTarget;
+
+class TextureStorage
+{
+ public:
+ TextureStorage();
+ virtual ~TextureStorage() {};
+
+ virtual int getTopLevel() const = 0;
+ virtual bool isRenderTarget() const = 0;
+ virtual bool isManaged() const = 0;
+ virtual int getLevelCount() const = 0;
+
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0;
+ virtual void generateMipmaps() = 0;
+
+ unsigned int getRenderTargetSerial(const gl::ImageIndex &index) const;
+ unsigned int getTextureSerial() const;
+
+ protected:
+ void initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage);
+
+ const unsigned int mTextureSerial;
+ static unsigned int issueTextureSerial();
+
+ static unsigned int mCurrentTextureSerial;
+
+ unsigned int mFirstRenderTargetSerial;
+ unsigned int mRenderTargetSerialsLayerStride;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp
new file mode 100644
index 0000000000..11596006d0
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp
@@ -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.
+//
+
+// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers.
+
+#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h"
+
+namespace rx
+{
+
+TransformFeedbackD3D::TransformFeedbackD3D()
+{
+}
+
+TransformFeedbackD3D::~TransformFeedbackD3D()
+{
+}
+
+void TransformFeedbackD3D::begin(GLenum primitiveMode)
+{
+}
+
+void TransformFeedbackD3D::end()
+{
+}
+
+void TransformFeedbackD3D::pause()
+{
+}
+
+void TransformFeedbackD3D::resume()
+{
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h
new file mode 100644
index 0000000000..7c367aba1d
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedbackD3D.h: Implements the abstract rx::TransformFeedbackImpl class.
+
+#ifndef LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
+#define LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
+
+#include "libGLESv2/renderer/TransformFeedbackImpl.h"
+#include "libGLESv2/angletypes.h"
+
+namespace rx
+{
+
+class TransformFeedbackD3D : public TransformFeedbackImpl
+{
+ public:
+ TransformFeedbackD3D();
+ virtual ~TransformFeedbackD3D();
+
+ virtual void begin(GLenum primitiveMode);
+ virtual void end();
+ virtual void pause();
+ virtual void resume();
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp
new file mode 100644
index 0000000000..4f85eb94fa
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp
@@ -0,0 +1,307 @@
+//
+// 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 "libGLESv2/renderer/d3d/VertexBuffer.h"
+#include "libGLESv2/renderer/d3d/BufferD3D.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/VertexAttribute.h"
+
+#include "common/mathutil.h"
+
+namespace rx
+{
+
+unsigned int VertexBuffer::mNextSerial = 1;
+
+VertexBuffer::VertexBuffer()
+{
+ updateSerial();
+}
+
+VertexBuffer::~VertexBuffer()
+{
+}
+
+void VertexBuffer::updateSerial()
+{
+ mSerial = mNextSerial++;
+}
+
+unsigned int VertexBuffer::getSerial() const
+{
+ return mSerial;
+}
+
+VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer)
+{
+ mDynamic = dynamic;
+ mWritePosition = 0;
+ mReservedSpace = 0;
+
+ mVertexBuffer = renderer->createVertexBuffer();
+}
+
+VertexBufferInterface::~VertexBufferInterface()
+{
+ delete mVertexBuffer;
+}
+
+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);
+ }
+ else
+ {
+ return mVertexBuffer->setBufferSize(size);
+ }
+}
+
+unsigned int VertexBufferInterface::getWritePosition() const
+{
+ return mWritePosition;
+}
+
+void VertexBufferInterface::setWritePosition(unsigned int writePosition)
+{
+ mWritePosition = writePosition;
+}
+
+gl::Error VertexBufferInterface::discard()
+{
+ return mVertexBuffer->discard();
+}
+
+gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+ GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset)
+{
+ gl::Error error(GL_NO_ERROR);
+
+ unsigned int spaceRequired;
+ error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (mWritePosition + spaceRequired < mWritePosition)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal error, new vertex buffer write position would overflow.");
+ }
+
+ error = reserveSpace(mReservedSpace);
+ if (error.isError())
+ {
+ return error;
+ }
+ mReservedSpace = 0;
+
+ error = mVertexBuffer->storeVertexAttributes(attrib, currentValue, start, count, instances, mWritePosition);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (outStreamOffset)
+ {
+ *outStreamOffset = mWritePosition;
+ }
+
+ mWritePosition += spaceRequired;
+
+ // Align to 16-byte boundary
+ mWritePosition = rx::roundUp(mWritePosition, 16u);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances)
+{
+ gl::Error error(GL_NO_ERROR);
+
+ unsigned int requiredSpace;
+ error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &requiredSpace);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // Protect against integer overflow
+ if (mReservedSpace + requiredSpace < mReservedSpace)
+ {
+ 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 += requiredSpace;
+
+ // Align to 16-byte boundary
+ mReservedSpace = rx::roundUp(mReservedSpace, 16u);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+VertexBuffer* VertexBufferInterface::getVertexBuffer() const
+{
+ return mVertexBuffer;
+}
+
+bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &attrib,
+ const gl::VertexAttribCurrentValueData &currentValue) const
+{
+ gl::Buffer *buffer = attrib.buffer.get();
+ BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
+
+ if (!storage || !storage->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;
+ bool requiresConversion = false;
+
+ if (attrib.type != GL_FLOAT)
+ {
+ gl::VertexFormat vertexFormat(attrib, currentValue.Type);
+
+ unsigned int outputElementSize;
+ getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
+ alignment = std::min<size_t>(outputElementSize, 4);
+
+ requiresConversion = (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0;
+ }
+
+ bool isAligned = (static_cast<size_t>(ComputeVertexAttributeStride(attrib)) % alignment == 0) &&
+ (static_cast<size_t>(attrib.offset) % alignment == 0);
+
+ return !requiresConversion && isAligned;
+}
+
+StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true)
+{
+ setBufferSize(initialSize);
+}
+
+StreamingVertexBufferInterface::~StreamingVertexBufferInterface()
+{
+}
+
+gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size)
+{
+ unsigned int curBufferSize = getBufferSize();
+ if (size > curBufferSize)
+ {
+ gl::Error error = setBufferSize(std::max(size, 3 * curBufferSize / 2));
+ if (error.isError())
+ {
+ return error;
+ }
+ setWritePosition(0);
+ }
+ else if (getWritePosition() + size > curBufferSize)
+ {
+ gl::Error error = discard();
+ if (error.isError())
+ {
+ return error;
+ }
+ setWritePosition(0);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false)
+{
+}
+
+StaticVertexBufferInterface::~StaticVertexBufferInterface()
+{
+}
+
+bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attrib, unsigned int *outStreamOffset)
+{
+ for (unsigned int element = 0; element < mCache.size(); element++)
+ {
+ if (mCache[element].type == attrib.type &&
+ mCache[element].size == attrib.size &&
+ mCache[element].stride == ComputeVertexAttributeStride(attrib) &&
+ mCache[element].normalized == attrib.normalized &&
+ mCache[element].pureInteger == attrib.pureInteger)
+ {
+ size_t offset = (static_cast<size_t>(attrib.offset) % ComputeVertexAttributeStride(attrib));
+ if (mCache[element].attributeOffset == offset)
+ {
+ if (outStreamOffset)
+ {
+ *outStreamOffset = mCache[element].streamOffset;
+ }
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+gl::Error StaticVertexBufferInterface::reserveSpace(unsigned int size)
+{
+ unsigned int curSize = getBufferSize();
+ if (curSize == 0)
+ {
+ return setBufferSize(size);
+ }
+ else if (curSize >= size)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION, "Internal error, Static vertex buffers can't be resized.");
+ }
+}
+
+gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+ GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset)
+{
+ unsigned int streamOffset;
+ gl::Error error = VertexBufferInterface::storeVertexAttributes(attrib, currentValue, start, count, instances, &streamOffset);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ size_t attributeOffset = static_cast<size_t>(attrib.offset) % ComputeVertexAttributeStride(attrib);
+ VertexElement element = { attrib.type, attrib.size, ComputeVertexAttributeStride(attrib), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset };
+ mCache.push_back(element);
+
+ if (outStreamOffset)
+ {
+ *outStreamOffset = streamOffset;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h
index cbafdd20f6..fa747d9cb4 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h
@@ -11,10 +11,17 @@
#define LIBGLESV2_RENDERER_VERTEXBUFFER_H_
#include "common/angleutils.h"
+#include "libGLESv2/Error.h"
+
+#include <GLES2/gl2.h>
+
+#include <cstddef>
+#include <vector>
namespace gl
{
-class VertexAttribute;
+struct VertexAttribute;
+struct VertexAttribCurrentValueData;
}
namespace rx
@@ -27,20 +34,16 @@ class VertexBuffer
VertexBuffer();
virtual ~VertexBuffer();
- virtual bool initialize(unsigned int size, bool dynamicUsage) = 0;
-
- virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
- GLsizei instances, unsigned int offset) = 0;
- virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset) = 0;
+ virtual gl::Error initialize(unsigned int size, bool dynamicUsage) = 0;
- virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
- unsigned int *outSpaceRequired) const = 0;
-
- virtual bool requiresConversion(const gl::VertexAttribute &attrib) const = 0;
+ virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+ GLint start, GLsizei count, GLsizei instances, unsigned int offset) = 0;
+ virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
+ unsigned int *outSpaceRequired) const = 0;
virtual unsigned int getBufferSize() const = 0;
- virtual bool setBufferSize(unsigned int size) = 0;
- virtual bool discard() = 0;
+ virtual gl::Error setBufferSize(unsigned int size) = 0;
+ virtual gl::Error discard() = 0;
unsigned int getSerial() const;
@@ -60,28 +63,29 @@ class VertexBufferInterface
VertexBufferInterface(rx::Renderer *renderer, bool dynamic);
virtual ~VertexBufferInterface();
- bool reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances);
- bool reserveRawDataSpace(unsigned int size);
+ gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances);
unsigned int getBufferSize() const;
unsigned int getSerial() const;
- virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
- unsigned int *outStreamOffset);
- virtual bool storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset);
+ virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+ GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset);
+
+ bool directStoragePossible(const gl::VertexAttribute &attrib,
+ const gl::VertexAttribCurrentValueData &currentValue) const;
VertexBuffer* getVertexBuffer() const;
protected:
- virtual bool reserveSpace(unsigned int size) = 0;
+ virtual gl::Error reserveSpace(unsigned int size) = 0;
unsigned int getWritePosition() const;
void setWritePosition(unsigned int writePosition);
- bool discard();
+ gl::Error discard();
- bool setBufferSize(unsigned int size);
+ gl::Error setBufferSize(unsigned int size);
private:
DISALLOW_COPY_AND_ASSIGN(VertexBufferInterface);
@@ -102,7 +106,7 @@ class StreamingVertexBufferInterface : public VertexBufferInterface
~StreamingVertexBufferInterface();
protected:
- bool reserveSpace(unsigned int size);
+ gl::Error reserveSpace(unsigned int size);
};
class StaticVertexBufferInterface : public VertexBufferInterface
@@ -111,22 +115,23 @@ class StaticVertexBufferInterface : public VertexBufferInterface
explicit StaticVertexBufferInterface(rx::Renderer *renderer);
~StaticVertexBufferInterface();
- bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
- unsigned int *outStreamOffset);
+ gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+ GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset);
- bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamOffset);
+ bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamFffset);
protected:
- bool reserveSpace(unsigned int size);
+ gl::Error reserveSpace(unsigned int size);
private:
struct VertexElement
{
GLenum type;
- GLint size;
- GLsizei stride;
+ GLuint size;
+ GLuint stride;
bool normalized;
- int attributeOffset;
+ bool pureInteger;
+ size_t attributeOffset;
unsigned int streamOffset;
};
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp
new file mode 100644
index 0000000000..7034b78eab
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp
@@ -0,0 +1,348 @@
+//
+// 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 "libGLESv2/renderer/d3d/VertexDataManager.h"
+#include "libGLESv2/renderer/d3d/BufferD3D.h"
+#include "libGLESv2/renderer/d3d/VertexBuffer.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/VertexAttribute.h"
+
+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 };
+}
+
+namespace rx
+{
+
+static 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 = ComputeVertexAttributeStride(attrib);
+ return (size - attrib.offset % stride + (stride - ComputeVertexAttributeTypeSize(attrib))) / stride;
+}
+
+static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int vertexDrawCount, int instanceDrawCount)
+{
+ // 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 (instanceDrawCount > 0 && attrib.divisor > 0)
+ {
+ return instanceDrawCount / attrib.divisor;
+ }
+
+ return vertexDrawCount;
+}
+
+VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer)
+{
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mCurrentValue[i].FloatValues[0] = std::numeric_limits<float>::quiet_NaN();
+ mCurrentValue[i].FloatValues[1] = std::numeric_limits<float>::quiet_NaN();
+ mCurrentValue[i].FloatValues[2] = std::numeric_limits<float>::quiet_NaN();
+ mCurrentValue[i].FloatValues[3] = std::numeric_limits<float>::quiet_NaN();
+ mCurrentValue[i].Type = GL_FLOAT;
+ mCurrentValueBuffer[i] = NULL;
+ mCurrentValueOffsets[i] = 0;
+ }
+
+ mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE);
+
+ if (!mStreamingBuffer)
+ {
+ ERR("Failed to allocate the streaming vertex buffer.");
+ }
+}
+
+VertexDataManager::~VertexDataManager()
+{
+ delete mStreamingBuffer;
+
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ delete mCurrentValueBuffer[i];
+ }
+}
+
+gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[],
+ gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances)
+{
+ if (!mStreamingBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL.");
+ }
+
+ // Invalidate static buffers that don't contain matching attributes
+ for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1);
+
+ if (translated[attributeIndex].active && attribs[attributeIndex].enabled)
+ {
+ invalidateMatchingStaticData(attribs[attributeIndex], currentValues[attributeIndex]);
+ }
+ }
+
+ // Reserve the required space in the buffers
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (translated[i].active && attribs[i].enabled)
+ {
+ gl::Error error = reserveSpaceForAttrib(attribs[i], currentValues[i], count, instances);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+
+ // Perform the vertex data translations
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (translated[i].active)
+ {
+ if (attribs[i].enabled)
+ {
+ gl::Error error = storeAttribute(attribs[i], currentValues[i], &translated[i],
+ start, count, instances);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ else
+ {
+ if (!mCurrentValueBuffer[i])
+ {
+ mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE);
+ }
+
+ gl::Error error = storeCurrentValue(attribs[i], currentValues[i], &translated[i],
+ &mCurrentValue[i], &mCurrentValueOffsets[i],
+ mCurrentValueBuffer[i]);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (translated[i].active && attribs[i].enabled)
+ {
+ gl::Buffer *buffer = attribs[i].buffer.get();
+
+ if (buffer)
+ {
+ BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation());
+ bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(attribs[i]));
+ }
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &attrib,
+ const gl::VertexAttribCurrentValueData &currentValue) const
+{
+ gl::Buffer *buffer = attrib.buffer.get();
+
+ if (buffer)
+ {
+ BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation());
+ StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer();
+
+ if (staticBuffer &&
+ staticBuffer->getBufferSize() > 0 &&
+ !staticBuffer->lookupAttribute(attrib, NULL) &&
+ !staticBuffer->directStoragePossible(attrib, currentValue))
+ {
+ bufferImpl->invalidateStaticData();
+ }
+ }
+}
+
+gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &attrib,
+ const gl::VertexAttribCurrentValueData &currentValue,
+ GLsizei count,
+ GLsizei instances) const
+{
+ gl::Buffer *buffer = attrib.buffer.get();
+ BufferD3D *bufferImpl = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
+ StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL;
+ VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
+
+ if (!vertexBuffer->directStoragePossible(attrib, currentValue))
+ {
+ if (staticBuffer)
+ {
+ if (staticBuffer->getBufferSize() == 0)
+ {
+ int totalCount = ElementsInBuffer(attrib, bufferImpl->getSize());
+ gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+ else
+ {
+ int totalCount = StreamingBufferElementCount(attrib, count, instances);
+ ASSERT(!bufferImpl || ElementsInBuffer(attrib, bufferImpl->getSize()) >= totalCount);
+
+ gl::Error error = mStreamingBuffer->reserveVertexSpace(attrib, totalCount, instances);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexAttribCurrentValueData &currentValue,
+ TranslatedAttribute *translated,
+ GLint start,
+ GLsizei count,
+ GLsizei instances)
+{
+ gl::Buffer *buffer = attrib.buffer.get();
+ ASSERT(buffer || attrib.pointer);
+
+ BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
+ StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL;
+ VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
+ bool directStorage = vertexBuffer->directStoragePossible(attrib, currentValue);
+
+ unsigned int streamOffset = 0;
+ unsigned int outputElementSize = 0;
+
+ if (directStorage)
+ {
+ outputElementSize = ComputeVertexAttributeStride(attrib);
+ streamOffset = attrib.offset + outputElementSize * start;
+ }
+ else if (staticBuffer)
+ {
+ gl::Error error = staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!staticBuffer->lookupAttribute(attrib, &streamOffset))
+ {
+ // Convert the entire buffer
+ int totalCount = ElementsInBuffer(attrib, storage->getSize());
+ int startIndex = attrib.offset / ComputeVertexAttributeStride(attrib);
+
+ gl::Error error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount,
+ 0, &streamOffset);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ unsigned int firstElementOffset = (attrib.offset / ComputeVertexAttributeStride(attrib)) * outputElementSize;
+ unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? start * outputElementSize : 0;
+ if (streamOffset + firstElementOffset + startOffset < streamOffset)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY);
+ }
+
+ streamOffset += firstElementOffset + startOffset;
+ }
+ else
+ {
+ int totalCount = StreamingBufferElementCount(attrib, count, instances);
+ gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, start, totalCount, instances, &streamOffset);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ translated->storage = directStorage ? storage : NULL;
+ translated->vertexBuffer = vertexBuffer->getVertexBuffer();
+ translated->serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial();
+ translated->divisor = attrib.divisor;
+
+ translated->attribute = &attrib;
+ translated->currentValueType = currentValue.Type;
+ translated->stride = outputElementSize;
+ translated->offset = streamOffset;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribute &attrib,
+ const gl::VertexAttribCurrentValueData &currentValue,
+ TranslatedAttribute *translated,
+ gl::VertexAttribCurrentValueData *cachedValue,
+ size_t *cachedOffset,
+ StreamingVertexBufferInterface *buffer)
+{
+ if (*cachedValue != currentValue)
+ {
+ gl::Error error = buffer->reserveVertexSpace(attrib, 1, 0);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ unsigned int streamOffset;
+ error = buffer->storeVertexAttributes(attrib, currentValue, 0, 1, 0, &streamOffset);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *cachedValue = currentValue;
+ *cachedOffset = streamOffset;
+ }
+
+ translated->storage = NULL;
+ translated->vertexBuffer = buffer->getVertexBuffer();
+ translated->serial = buffer->getSerial();
+ translated->divisor = 0;
+
+ translated->attribute = &attrib;
+ translated->currentValueType = currentValue.Type;
+ translated->stride = 0;
+ translated->offset = *cachedOffset;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h
new file mode 100644
index 0000000000..7728722246
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h
@@ -0,0 +1,95 @@
+//
+// 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 LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_
+#define LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_
+
+#include "libGLESv2/Constants.h"
+#include "libGLESv2/VertexAttribute.h"
+#include "common/angleutils.h"
+
+namespace gl
+{
+struct VertexAttribute;
+class ProgramBinary;
+struct VertexAttribCurrentValueData;
+}
+
+namespace rx
+{
+class BufferD3D;
+class StreamingVertexBufferInterface;
+class VertexBuffer;
+class Renderer;
+
+struct TranslatedAttribute
+{
+ TranslatedAttribute() : active(false), attribute(NULL), currentValueType(GL_NONE),
+ offset(0), stride(0), vertexBuffer(NULL), storage(NULL),
+ serial(0), divisor(0) {};
+ bool active;
+
+ const gl::VertexAttribute *attribute;
+ GLenum currentValueType;
+ unsigned int offset;
+ unsigned int stride; // 0 means not to advance the read pointer at all
+
+ VertexBuffer *vertexBuffer;
+ BufferD3D *storage;
+ unsigned int serial;
+ unsigned int divisor;
+};
+
+class VertexDataManager
+{
+ public:
+ VertexDataManager(rx::Renderer *renderer);
+ virtual ~VertexDataManager();
+
+ gl::Error prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[],
+ gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VertexDataManager);
+
+ gl::Error reserveSpaceForAttrib(const gl::VertexAttribute &attrib,
+ const gl::VertexAttribCurrentValueData &currentValue,
+ GLsizei count,
+ GLsizei instances) const;
+
+ void invalidateMatchingStaticData(const gl::VertexAttribute &attrib,
+ const gl::VertexAttribCurrentValueData &currentValue) const;
+
+ gl::Error storeAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexAttribCurrentValueData &currentValue,
+ TranslatedAttribute *translated,
+ GLint start,
+ GLsizei count,
+ GLsizei instances);
+
+ gl::Error storeCurrentValue(const gl::VertexAttribute &attrib,
+ const gl::VertexAttribCurrentValueData &currentValue,
+ TranslatedAttribute *translated,
+ gl::VertexAttribCurrentValueData *cachedValue,
+ size_t *cachedOffset,
+ StreamingVertexBufferInterface *buffer);
+
+ rx::Renderer *const mRenderer;
+
+ StreamingVertexBufferInterface *mStreamingBuffer;
+
+ gl::VertexAttribCurrentValueData mCurrentValue[gl::MAX_VERTEX_ATTRIBS];
+
+ StreamingVertexBufferInterface *mCurrentValueBuffer[gl::MAX_VERTEX_ATTRIBS];
+ std::size_t mCurrentValueOffsets[gl::MAX_VERTEX_ATTRIBS];
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
new file mode 100644
index 0000000000..d43e65ea78
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
@@ -0,0 +1,1049 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d11/Blit11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/formatutils.h"
+
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2duips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2duips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2duips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2duips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2dps.h"
+
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dvs.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dgs.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3duips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3duips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3duips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3duips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3dps.h"
+
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h"
+
+namespace rx
+{
+
+static DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource)
+{
+ ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource);
+ if (!texture)
+ {
+ return DXGI_FORMAT_UNKNOWN;
+ }
+
+ D3D11_TEXTURE2D_DESC desc;
+ texture->GetDesc(&desc);
+
+ SafeRelease(texture);
+
+ return desc.Format;
+}
+
+static ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context,
+ ID3D11Resource *source, unsigned int subresource,
+ const gl::Extents &size, unsigned int cpuAccessFlags)
+{
+ D3D11_TEXTURE2D_DESC stagingDesc;
+ stagingDesc.Width = size.width;
+ stagingDesc.Height = size.height;
+ stagingDesc.MipLevels = 1;
+ stagingDesc.ArraySize = 1;
+ stagingDesc.Format = GetTextureFormat(source);
+ stagingDesc.SampleDesc.Count = 1;
+ stagingDesc.SampleDesc.Quality = 0;
+ stagingDesc.Usage = D3D11_USAGE_STAGING;
+ stagingDesc.CPUAccessFlags = cpuAccessFlags;
+ stagingDesc.MiscFlags = 0;
+ stagingDesc.BindFlags = 0;
+
+ ID3D11Texture2D *stagingTexture = NULL;
+ HRESULT result = device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture);
+ if (FAILED(result))
+ {
+ ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result);
+ return NULL;
+ }
+
+ context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, NULL);
+
+ return stagingTexture;
+}
+
+inline static 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);
+}
+
+static 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;
+}
+
+static 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;
+}
+
+Blit11::Blit11(rx::Renderer11 *renderer)
+ : mRenderer(renderer), mBlitShaderMap(compareBlitParameters), mSwizzleShaderMap(compareSwizzleParameters),
+ mVertexBuffer(NULL), mPointSampler(NULL), mLinearSampler(NULL), mScissorEnabledRasterizerState(NULL),
+ mScissorDisabledRasterizerState(NULL), mDepthStencilState(NULL),
+ mQuad2DIL(NULL), mQuad2DVS(NULL), mDepthPS(NULL),
+ mQuad3DIL(NULL), mQuad3DVS(NULL), mQuad3DGS(NULL),
+ mSwizzleCB(NULL)
+{
+ HRESULT result;
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_BUFFER_DESC vbDesc;
+ vbDesc.ByteWidth = std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), sizeof(d3d11::PositionTexCoordVertex)) *
+ 6 * renderer->getRendererCaps().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, NULL, &mVertexBuffer);
+ ASSERT(SUCCEEDED(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 = mRenderer->isLevel9() ? FLT_MAX : 0.0f;
+
+ result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler);
+ ASSERT(SUCCEEDED(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 = mRenderer->isLevel9() ? FLT_MAX : 0.0f;
+
+ result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler);
+ ASSERT(SUCCEEDED(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));
+ d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state");
+
+ rasterDesc.ScissorEnable = FALSE;
+ result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState);
+ ASSERT(SUCCEEDED(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));
+ d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state");
+
+ 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 },
+ };
+
+ result = device->CreateInputLayout(quad2DLayout, ArraySize(quad2DLayout), g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), &mQuad2DIL);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mQuad2DIL, "Blit11 2D input layout");
+
+ result = device->CreateVertexShader(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), NULL, &mQuad2DVS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader");
+
+ if (!renderer->isLevel9())
+ {
+ result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader");
+
+ 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 },
+ };
+
+ result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout");
+
+ result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader");
+
+ result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader");
+ }
+
+ buildShaderMap();
+
+ 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, NULL, &mSwizzleCB);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer");
+}
+
+Blit11::~Blit11()
+{
+ SafeRelease(mVertexBuffer);
+ SafeRelease(mPointSampler);
+ SafeRelease(mLinearSampler);
+ SafeRelease(mScissorEnabledRasterizerState);
+ SafeRelease(mScissorDisabledRasterizerState);
+ SafeRelease(mDepthStencilState);
+
+ SafeRelease(mQuad2DIL);
+ SafeRelease(mQuad2DVS);
+ SafeRelease(mDepthPS);
+
+ SafeRelease(mQuad3DIL);
+ SafeRelease(mQuad3DVS);
+ SafeRelease(mQuad3DGS);
+
+ SafeRelease(mSwizzleCB);
+
+ clearShaderMap();
+}
+
+static inline 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;
+}
+
+gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size,
+ GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
+{
+ HRESULT result;
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
+ source->GetDesc(&sourceSRVDesc);
+
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format);
+ const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat);
+
+ GLenum shaderType = GL_NONE;
+ switch (sourceFormatInfo.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;
+ }
+
+ SwizzleParameters parameters = { 0 };
+ parameters.mDestinationType = shaderType;
+ parameters.mViewDimension = sourceSRVDesc.ViewDimension;
+
+ SwizzleShaderMap::const_iterator i = mSwizzleShaderMap.find(parameters);
+ if (i == mSwizzleShaderMap.end())
+ {
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION, "Internal error, missing swizzle shader.");
+ }
+
+ const Shader &shader = i->second;
+
+ // 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);
+ }
+
+ 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);
+ shader.mVertexWriteFunction(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(swizzleRed);
+ swizzleIndices[1] = GetSwizzleIndex(swizzleGreen);
+ swizzleIndices[2] = GetSwizzleIndex(swizzleBlue);
+ swizzleIndices[3] = GetSwizzleIndex(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(NULL, NULL, 0xFFFFFFF);
+ deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
+ deviceContext->RSSetState(mScissorDisabledRasterizerState);
+
+ // Apply shaders
+ deviceContext->IASetInputLayout(shader.mInputLayout);
+ deviceContext->IASetPrimitiveTopology(topology);
+ deviceContext->VSSetShader(shader.mVertexShader, NULL, 0);
+
+ deviceContext->PSSetShader(shader.mPixelShader, NULL, 0);
+ deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0);
+
+ // Unset the currently bound shader resource to avoid conflicts
+ ID3D11ShaderResourceView *const nullSRV = NULL;
+ deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+
+ // Apply render target
+ mRenderer->setOneTimeRenderTarget(dest);
+
+ // Set the viewport
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = size.width;
+ viewport.Height = size.height;
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ deviceContext->RSSetViewports(1, &viewport);
+
+ // Apply textures
+ deviceContext->PSSetShaderResources(0, 1, &source);
+
+ // Apply samplers
+ deviceContext->PSSetSamplers(0, 1, &mPointSampler);
+
+ // Draw the quad
+ deviceContext->Draw(drawCount, 0);
+
+ // Unbind textures and render targets and vertex buffer
+ deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+
+ mRenderer->unapplyRenderTargets();
+
+ UINT zero = 0;
+ ID3D11Buffer *const nullBuffer = NULL;
+ deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
+
+ mRenderer->markAllStateDirty();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+bool 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)
+{
+ 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);
+
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format);
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat);
+
+ BlitParameters parameters = { 0 };
+ parameters.mDestinationFormat = destFormat;
+ parameters.mSignedInteger = (internalFormatInfo.componentType == GL_INT);
+ parameters.m3DBlit = sourceArea.depth > 1;
+
+ BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters);
+ if (i == mBlitShaderMap.end())
+ {
+ UNREACHABLE();
+ return false;
+ }
+
+ const Shader& shader = i->second;
+
+ // Set vertices
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
+ return false;
+ }
+
+ UINT stride = 0;
+ UINT startIdx = 0;
+ UINT drawCount = 0;
+ D3D11_PRIMITIVE_TOPOLOGY topology;
+
+ shader.mVertexWriteFunction(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(NULL, NULL, 0xFFFFFFF);
+ deviceContext->OMSetDepthStencilState(NULL, 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(shader.mInputLayout);
+ deviceContext->IASetPrimitiveTopology(topology);
+ deviceContext->VSSetShader(shader.mVertexShader, NULL, 0);
+
+ deviceContext->PSSetShader(shader.mPixelShader, NULL, 0);
+ deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0);
+
+ // Unset the currently bound shader resource to avoid conflicts
+ ID3D11ShaderResourceView *const nullSRV = NULL;
+ deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+
+ // Apply render target
+ mRenderer->setOneTimeRenderTarget(dest);
+
+ // Set the viewport
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = destSize.width;
+ viewport.Height = destSize.height;
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ deviceContext->RSSetViewports(1, &viewport);
+
+ // Apply textures
+ deviceContext->PSSetShaderResources(0, 1, &source);
+
+ // Apply samplers
+ ID3D11SamplerState *sampler = NULL;
+ switch (filter)
+ {
+ case GL_NEAREST: sampler = mPointSampler; break;
+ case GL_LINEAR: sampler = mLinearSampler; break;
+ default: UNREACHABLE(); return false;
+ }
+ deviceContext->PSSetSamplers(0, 1, &sampler);
+
+ // Draw the quad
+ deviceContext->Draw(drawCount, 0);
+
+ // Unbind textures and render targets and vertex buffer
+ deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+
+ mRenderer->unapplyRenderTargets();
+
+ UINT zero = 0;
+ ID3D11Buffer *const nullBuffer = NULL;
+ deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
+
+ mRenderer->markAllStateDirty();
+
+ return true;
+}
+
+bool Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+ ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+ const gl::Rectangle *scissor)
+{
+ return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize,
+ dest, destSubresource, destArea, destSize,
+ scissor, true);
+}
+
+bool 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)
+{
+ 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))
+ {
+ ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
+ return false;
+ }
+
+ 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(NULL, NULL, 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);
+ }
+
+ // Apply shaders
+ deviceContext->IASetInputLayout(mQuad2DIL);
+ deviceContext->IASetPrimitiveTopology(topology);
+ deviceContext->VSSetShader(mQuad2DVS, NULL, 0);
+
+ deviceContext->PSSetShader(mDepthPS, NULL, 0);
+ deviceContext->GSSetShader(NULL, NULL, 0);
+
+ // Unset the currently bound shader resource to avoid conflicts
+ ID3D11ShaderResourceView *const nullSRV = NULL;
+ deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+
+ // Apply render target
+ deviceContext->OMSetRenderTargets(0, NULL, dest);
+
+ // Set the viewport
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = destSize.width;
+ viewport.Height = destSize.height;
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ deviceContext->RSSetViewports(1, &viewport);
+
+ // Apply textures
+ deviceContext->PSSetShaderResources(0, 1, &source);
+
+ // Apply samplers
+ deviceContext->PSSetSamplers(0, 1, &mPointSampler);
+
+ // Draw the quad
+ deviceContext->Draw(drawCount, 0);
+
+ // Unbind textures and render targets and vertex buffer
+ deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+
+ mRenderer->unapplyRenderTargets();
+
+ UINT zero = 0;
+ ID3D11Buffer *const nullBuffer = NULL;
+ deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
+
+ mRenderer->markAllStateDirty();
+
+ return true;
+}
+
+bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+ ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+ const gl::Rectangle *scissor)
+{
+ return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize,
+ dest, destSubresource, destArea, destSize,
+ scissor, false);
+}
+
+bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+ ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+ const gl::Rectangle *scissor, bool stencilOnly)
+{
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ ID3D11Resource *sourceStaging = CreateStagingTexture(device, deviceContext, source, sourceSubresource, sourceSize, D3D11_CPU_ACCESS_READ);
+ // 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
+ ID3D11Resource *destStaging = CreateStagingTexture(device, deviceContext, dest, destSubresource, destSize, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE);
+
+ if (!sourceStaging || !destStaging)
+ {
+ SafeRelease(sourceStaging);
+ SafeRelease(destStaging);
+ return false;
+ }
+
+ DXGI_FORMAT format = GetTextureFormat(source);
+ ASSERT(format == GetTextureFormat(dest));
+
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format);
+ unsigned int pixelSize = dxgiFormatInfo.pixelBytes;
+ unsigned int copyOffset = 0;
+ unsigned int copySize = pixelSize;
+ if (stencilOnly)
+ {
+ copyOffset = dxgiFormatInfo.depthBits / 8;
+ copySize = dxgiFormatInfo.stencilBits / 8;
+
+ // It would be expensive to have non-byte sized stencil sizes since it would
+ // require reading from the destination, currently there aren't any though.
+ ASSERT(dxgiFormatInfo.stencilBits % 8 == 0 &&
+ dxgiFormatInfo.depthBits % 8 == 0);
+ }
+
+ D3D11_MAPPED_SUBRESOURCE sourceMapping, destMapping;
+ deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping);
+ deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping);
+
+ if (!sourceMapping.pData || !destMapping.pData)
+ {
+ if (!sourceMapping.pData)
+ {
+ deviceContext->Unmap(sourceStaging, 0);
+ }
+ if (!destMapping.pData)
+ {
+ deviceContext->Unmap(destStaging, 0);
+ }
+ SafeRelease(sourceStaging);
+ SafeRelease(destStaging);
+ return false;
+ }
+
+ gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
+
+ // Clip dest area to the destination size
+ gl::ClipRectangle(clippedDestArea, gl::Rectangle(0, 0, destSize.width, destSize.height), &clippedDestArea);
+
+ // Clip dest area to the scissor
+ if (scissor)
+ {
+ gl::ClipRectangle(clippedDestArea, *scissor, &clippedDestArea);
+ }
+
+ // Determine if entire rows can be copied at once instead of each individual pixel, requires that there is
+ // no out of bounds lookups required, the entire pixel is copied and no stretching
+ bool wholeRowCopy = sourceArea.width == clippedDestArea.width &&
+ sourceArea.x >= 0 && sourceArea.x + sourceArea.width <= sourceSize.width &&
+ copySize == 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 = gl::clamp(sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f), 0, sourceSize.height - 1);
+ unsigned int writeRow = y;
+
+ if (wholeRowCopy)
+ {
+ void *sourceRow = reinterpret_cast<char*>(sourceMapping.pData) +
+ readRow * sourceMapping.RowPitch +
+ sourceArea.x * pixelSize;
+
+ void *destRow = reinterpret_cast<char*>(destMapping.pData) +
+ writeRow * destMapping.RowPitch +
+ destArea.x * pixelSize;
+
+ memcpy(destRow, sourceRow, pixelSize * destArea.width);
+ }
+ else
+ {
+ for (int x = clippedDestArea.x; x < clippedDestArea.x + clippedDestArea.width; x++)
+ {
+ float xPerc = static_cast<float>(x - destArea.x) / (destArea.width - 1);
+
+ // Interpolate the original source rectangle to determine which column to sample from while clamping to the edges
+ unsigned int readColumn = gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1);
+ unsigned int writeColumn = x;
+
+ void *sourcePixel = reinterpret_cast<char*>(sourceMapping.pData) +
+ readRow * sourceMapping.RowPitch +
+ readColumn * pixelSize +
+ copyOffset;
+
+ void *destPixel = reinterpret_cast<char*>(destMapping.pData) +
+ writeRow * destMapping.RowPitch +
+ writeColumn * pixelSize +
+ copyOffset;
+
+ memcpy(destPixel, sourcePixel, copySize);
+ }
+ }
+ }
+
+ // HACK: Use ID3D11DevicContext::UpdateSubresource which causes an extra copy compared to ID3D11DevicContext::CopySubresourceRegion
+ // according to MSDN.
+ deviceContext->UpdateSubresource(dest, destSubresource, NULL, destMapping.pData, destMapping.RowPitch, destMapping.DepthPitch);
+
+ deviceContext->Unmap(sourceStaging, 0);
+ deviceContext->Unmap(destStaging, 0);
+
+ // TODO: Determine why this call to ID3D11DevicContext::CopySubresourceRegion causes a TDR timeout on some
+ // systems when called repeatedly.
+ // deviceContext->CopySubresourceRegion(dest, destSubresource, 0, 0, 0, destStaging, 0, NULL);
+
+ SafeRelease(sourceStaging);
+ SafeRelease(destStaging);
+
+ return true;
+}
+
+bool Blit11::compareBlitParameters(const Blit11::BlitParameters &a, const Blit11::BlitParameters &b)
+{
+ return memcmp(&a, &b, sizeof(Blit11::BlitParameters)) < 0;
+}
+
+bool Blit11::compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b)
+{
+ return memcmp(&a, &b, sizeof(Blit11::SwizzleParameters)) < 0;
+}
+
+void Blit11::add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps)
+{
+ BlitParameters params = { 0 };
+ params.mDestinationFormat = destFormat;
+ params.mSignedInteger = signedInteger;
+ params.m3DBlit = false;
+
+ ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end());
+ ASSERT(ps);
+
+ Shader shader;
+ shader.mVertexWriteFunction = Write2DVertices;
+ shader.mInputLayout = mQuad2DIL;
+ shader.mVertexShader = mQuad2DVS;
+ shader.mGeometryShader = NULL;
+ shader.mPixelShader = ps;
+
+ mBlitShaderMap[params] = shader;
+}
+
+void Blit11::add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps)
+{
+ BlitParameters params = { 0 };
+ params.mDestinationFormat = destFormat;
+ params.mSignedInteger = signedInteger;
+ params.m3DBlit = true;
+
+ ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end());
+ ASSERT(ps);
+
+ Shader shader;
+ shader.mVertexWriteFunction = Write3DVertices;
+ shader.mInputLayout = mQuad3DIL;
+ shader.mVertexShader = mQuad3DVS;
+ shader.mGeometryShader = mQuad3DGS;
+ shader.mPixelShader = ps;
+
+ mBlitShaderMap[params] = shader;
+}
+
+void Blit11::addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps)
+{
+ SwizzleParameters params = { 0 };
+ params.mDestinationType = destType;
+ params.mViewDimension = viewDimension;
+
+ ASSERT(mSwizzleShaderMap.find(params) == mSwizzleShaderMap.end());
+ ASSERT(ps);
+
+ Shader shader;
+ switch (viewDimension)
+ {
+ case D3D_SRV_DIMENSION_TEXTURE2D:
+ shader.mVertexWriteFunction = Write2DVertices;
+ shader.mInputLayout = mQuad2DIL;
+ shader.mVertexShader = mQuad2DVS;
+ shader.mGeometryShader = NULL;
+ break;
+
+ case D3D_SRV_DIMENSION_TEXTURE3D:
+ case D3D_SRV_DIMENSION_TEXTURE2DARRAY:
+ case D3D_SRV_DIMENSION_TEXTURECUBE:
+ shader.mVertexWriteFunction = Write3DVertices;
+ shader.mInputLayout = mQuad3DIL;
+ shader.mVertexShader = mQuad3DVS;
+ shader.mGeometryShader = mQuad3DGS;
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ shader.mPixelShader = ps;
+
+ mSwizzleShaderMap[params] = shader;
+}
+
+void Blit11::buildShaderMap()
+{
+ ID3D11Device *device = mRenderer->getDevice();
+
+ add2DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader" ));
+ add2DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader" ));
+ add2DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader" ));
+ add2DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader" ));
+ add2DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader" ));
+ add2DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader" ));
+ add2DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader" ));
+ add2DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader"));
+
+ addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" ));
+
+ if (mRenderer->isLevel9())
+ return;
+
+ add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" ));
+ add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" ));
+ add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" ));
+ add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" ));
+ add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" ));
+ add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" ));
+ add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" ));
+ add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" ));
+ add3DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader" ));
+ add3DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader" ));
+ add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" ));
+ add3DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader" ));
+ add3DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader" ));
+ add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" ));
+ add3DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader" ));
+ add3DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader" ));
+ add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" ));
+ add3DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader" ));
+ add3DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader" ));
+ add3DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader" ));
+ add3DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader" ));
+ add3DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader" ));
+ add3DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader" ));
+ add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader"));
+
+ addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader"));
+ addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader" ));
+
+ addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Cube F swizzle pixel shader" ));
+ addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader"));
+ addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Cube I swizzle pixel shader" ));
+
+ addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader" ));
+ addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader"));
+ addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader" ));
+
+ addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Array F swizzle pixel shader" ));
+ addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader"));
+ addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Array I swizzle pixel shader" ));
+}
+
+void Blit11::clearShaderMap()
+{
+ for (BlitShaderMap::iterator i = mBlitShaderMap.begin(); i != mBlitShaderMap.end(); ++i)
+ {
+ Shader &shader = i->second;
+ SafeRelease(shader.mPixelShader);
+ }
+ mBlitShaderMap.clear();
+
+ for (SwizzleShaderMap::iterator i = mSwizzleShaderMap.begin(); i != mSwizzleShaderMap.end(); ++i)
+ {
+ Shader &shader = i->second;
+ SafeRelease(shader.mPixelShader);
+ }
+ mSwizzleShaderMap.clear();
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h
new file mode 100644
index 0000000000..d6a0b795f4
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h
@@ -0,0 +1,129 @@
+//
+// 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 LIBGLESV2_BLIT11_H_
+#define LIBGLESV2_BLIT11_H_
+
+#include "common/angleutils.h"
+#include "libGLESv2/angletypes.h"
+#include "libGLESv2/Error.h"
+
+#include <map>
+
+namespace rx
+{
+class Renderer11;
+
+enum Filter
+{
+ Point,
+ Linear,
+};
+
+class Blit11
+{
+ public:
+ explicit Blit11(Renderer11 *renderer);
+ ~Blit11();
+
+ gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size,
+ GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
+
+ bool 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 copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+ ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+ const gl::Rectangle *scissor);
+
+ bool 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);
+
+ bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+ ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+ const gl::Rectangle *scissor);
+
+ private:
+ rx::Renderer11 *mRenderer;
+
+ struct BlitParameters
+ {
+ GLenum mDestinationFormat;
+ bool mSignedInteger;
+ bool m3DBlit;
+ };
+
+ bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+ ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+ const gl::Rectangle *scissor, bool stencilOnly);
+
+ static bool compareBlitParameters(const BlitParameters &a, const BlitParameters &b);
+
+ 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);
+
+ struct Shader
+ {
+ WriteVertexFunction mVertexWriteFunction;
+ ID3D11InputLayout *mInputLayout;
+ ID3D11VertexShader *mVertexShader;
+ ID3D11GeometryShader *mGeometryShader;
+ ID3D11PixelShader *mPixelShader;
+ };
+
+ typedef bool (*BlitParametersComparisonFunction)(const BlitParameters&, const BlitParameters &);
+ typedef std::map<BlitParameters, Shader, BlitParametersComparisonFunction> BlitShaderMap;
+ BlitShaderMap mBlitShaderMap;
+
+ void add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps);
+ void add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps);
+
+ struct SwizzleParameters
+ {
+ GLenum mDestinationType;
+ D3D11_SRV_DIMENSION mViewDimension;
+ };
+
+ static bool compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b);
+
+ typedef bool (*SwizzleParametersComparisonFunction)(const SwizzleParameters&, const SwizzleParameters &);
+ typedef std::map<SwizzleParameters, Shader, SwizzleParametersComparisonFunction> SwizzleShaderMap;
+ SwizzleShaderMap mSwizzleShaderMap;
+
+ void addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps);
+
+ void buildShaderMap();
+ void clearShaderMap();
+
+ ID3D11Buffer *mVertexBuffer;
+ ID3D11SamplerState *mPointSampler;
+ ID3D11SamplerState *mLinearSampler;
+ ID3D11RasterizerState *mScissorEnabledRasterizerState;
+ ID3D11RasterizerState *mScissorDisabledRasterizerState;
+ ID3D11DepthStencilState *mDepthStencilState;
+
+ ID3D11InputLayout *mQuad2DIL;
+ ID3D11VertexShader *mQuad2DVS;
+ ID3D11PixelShader *mDepthPS;
+
+ ID3D11InputLayout *mQuad3DIL;
+ ID3D11VertexShader *mQuad3DVS;
+ ID3D11GeometryShader *mQuad3DGS;
+
+ ID3D11Buffer *mSwizzleCB;
+
+ DISALLOW_COPY_AND_ASSIGN(Blit11);
+};
+
+}
+
+#endif // LIBGLESV2_BLIT11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
new file mode 100644
index 0000000000..ecd4d4672b
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
@@ -0,0 +1,961 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+PackPixelsParams::PackPixelsParams()
+ : format(GL_NONE),
+ type(GL_NONE),
+ outputPitch(0),
+ packBuffer(NULL),
+ 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)
+{}
+
+namespace gl_d3d11
+{
+
+D3D11_MAP GetD3DMapTypeFromBits(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)
+ {
+ return D3D11_MAP_WRITE;
+ }
+ else if (writeBit && readBit)
+ {
+ return D3D11_MAP_READ_WRITE;
+ }
+ else
+ {
+ UNREACHABLE();
+ return D3D11_MAP_READ;
+ }
+}
+
+}
+
+// Each instance of Buffer11::BufferStorage11 is specialized for a class of D3D binding points
+// - vertex/transform feedback buffers
+// - index buffers
+// - pixel unpack buffers
+// - uniform buffers
+class Buffer11::BufferStorage11
+{
+ public:
+ virtual ~BufferStorage11() {}
+
+ DataRevision getDataRevision() const { return mRevision; }
+ BufferUsage getUsage() const { return mUsage; }
+ size_t getSize() const { return mBufferSize; }
+ bool isMappable() const { return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_PIXEL_PACK); }
+
+ void setDataRevision(DataRevision rev) { mRevision = rev; }
+
+ virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset,
+ size_t size, size_t destOffset) = 0;
+ virtual bool resize(size_t size, bool preserveData) = 0;
+
+ virtual void *map(size_t offset, size_t length, GLbitfield access) = 0;
+ virtual void unmap() = 0;
+
+ protected:
+ BufferStorage11(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::NativeBuffer11 : public Buffer11::BufferStorage11
+{
+ public:
+ NativeBuffer11(Renderer11 *renderer, BufferUsage usage);
+ ~NativeBuffer11();
+
+ ID3D11Buffer *getNativeBuffer() const { return mNativeBuffer; }
+
+ virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset,
+ size_t size, size_t destOffset);
+ virtual bool resize(size_t size, bool preserveData);
+
+ virtual void *map(size_t offset, size_t length, GLbitfield access);
+ virtual void unmap();
+
+ bool setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset);
+
+ private:
+ ID3D11Buffer *mNativeBuffer;
+
+ static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize);
+};
+
+// 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::PackStorage11 : public Buffer11::BufferStorage11
+{
+ public:
+ PackStorage11(Renderer11 *renderer);
+ ~PackStorage11();
+
+ virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset,
+ size_t size, size_t destOffset);
+ virtual bool resize(size_t size, bool preserveData);
+
+ virtual void *map(size_t offset, size_t length, GLbitfield access);
+ virtual void unmap();
+
+ gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params);
+
+ private:
+
+ void flushQueuedPackCommand();
+
+ ID3D11Texture2D *mStagingTexture;
+ DXGI_FORMAT mTextureFormat;
+ gl::Extents mTextureSize;
+ MemoryBuffer mMemoryBuffer;
+ PackPixelsParams *mQueuedPackCommand;
+ PackPixelsParams mPackParams;
+ bool mDataModified;
+};
+
+
+Buffer11::Buffer11(Renderer11 *renderer)
+ : BufferD3D(),
+ mRenderer(renderer),
+ mSize(0),
+ mMappedStorage(NULL),
+ mResolvedDataRevision(0),
+ mReadUsageCount(0)
+{}
+
+Buffer11::~Buffer11()
+{
+ for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++)
+ {
+ SafeDelete(it->second);
+ }
+}
+
+Buffer11 *Buffer11::makeBuffer11(BufferImpl *buffer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(Buffer11*, buffer));
+ return static_cast<Buffer11*>(buffer);
+}
+
+gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage)
+{
+ gl::Error error = setSubData(data, size, 0);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (usage == GL_STATIC_DRAW)
+ {
+ initializeStaticData();
+ }
+
+ return error;
+}
+
+void *Buffer11::getData()
+{
+ NativeBuffer11 *stagingBuffer = getStagingBuffer();
+
+ if (!stagingBuffer)
+ {
+ // Out-of-memory
+ return NULL;
+ }
+
+ if (stagingBuffer->getDataRevision() > mResolvedDataRevision)
+ {
+ if (stagingBuffer->getSize() > mResolvedData.size())
+ {
+ if (!mResolvedData.resize(stagingBuffer->getSize()))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
+ }
+ }
+
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_READ, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
+ }
+
+ memcpy(mResolvedData.data(), mappedResource.pData, stagingBuffer->getSize());
+
+ context->Unmap(stagingBuffer->getNativeBuffer(), 0);
+
+ mResolvedDataRevision = stagingBuffer->getDataRevision();
+ }
+
+ mReadUsageCount = 0;
+
+ // Only happens if we initialized the buffer with no data (NULL)
+ if (mResolvedData.empty())
+ {
+ if (!mResolvedData.resize(mSize))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
+ }
+ }
+
+ ASSERT(mResolvedData.size() >= mSize);
+
+ return mResolvedData.data();
+}
+
+gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset)
+{
+ size_t requiredSize = size + offset;
+
+ if (data && size > 0)
+ {
+ NativeBuffer11 *stagingBuffer = getStagingBuffer();
+
+ if (!stagingBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer.");
+ }
+
+ // Explicitly resize the staging buffer, preserving data if the new data will not
+ // completely fill the buffer
+ if (stagingBuffer->getSize() < requiredSize)
+ {
+ bool preserveData = (offset > 0);
+ if (!stagingBuffer->resize(requiredSize, preserveData))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal staging buffer.");
+ }
+ }
+
+ if (!stagingBuffer->setData(D3D11_MAP_WRITE, reinterpret_cast<const uint8_t *>(data), size, offset))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to set data on internal staging buffer.");
+ }
+
+ stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1);
+ }
+
+ mSize = std::max(mSize, requiredSize);
+ invalidateStaticData();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
+{
+ Buffer11 *sourceBuffer = makeBuffer11(source);
+ ASSERT(sourceBuffer != NULL);
+
+ BufferStorage11 *copyDest = getLatestBufferStorage();
+ if (!copyDest)
+ {
+ copyDest = getStagingBuffer();
+ }
+
+ BufferStorage11 *copySource = sourceBuffer->getLatestBufferStorage();
+
+ 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())
+ {
+ copySource = sourceBuffer->getStagingBuffer();
+ }
+ else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copyDest->isMappable())
+ {
+ copyDest = getStagingBuffer();
+ }
+
+ // 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)
+ {
+ copySource = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
+ }
+ else
+ {
+ copySource = getStagingBuffer();
+ }
+ }
+
+ copyDest->copyFromStorage(copySource, sourceOffset, size, destOffset);
+ copyDest->setDataRevision(copyDest->getDataRevision() + 1);
+
+ mSize = std::max<size_t>(mSize, destOffset + size);
+ invalidateStaticData();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+{
+ ASSERT(!mMappedStorage);
+
+ BufferStorage11 *latestStorage = getLatestBufferStorage();
+ 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.
+ mMappedStorage = getStagingBuffer();
+ }
+
+ 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);
+ }
+
+ void *mappedBuffer = mMappedStorage->map(offset, length, access);
+ if (!mappedBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer.");
+ }
+
+ *mapPtr = mappedBuffer;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Buffer11::unmap()
+{
+ ASSERT(mMappedStorage);
+ mMappedStorage->unmap();
+ mMappedStorage = NULL;
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Buffer11::markTransformFeedbackUsage()
+{
+ BufferStorage11 *transformFeedbackStorage = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
+
+ if (transformFeedbackStorage)
+ {
+ transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1);
+ }
+
+ invalidateStaticData();
+}
+
+void Buffer11::markBufferUsage()
+{
+ mReadUsageCount++;
+
+ const unsigned int usageLimit = 5;
+
+ if (mReadUsageCount > usageLimit && mResolvedData.size() > 0)
+ {
+ mResolvedData.resize(0);
+ mResolvedDataRevision = 0;
+ }
+}
+
+Renderer* Buffer11::getRenderer()
+{
+ return mRenderer;
+}
+
+ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage)
+{
+ markBufferUsage();
+
+ BufferStorage11 *bufferStorage = getBufferStorage(usage);
+
+ if (!bufferStorage)
+ {
+ // Storage out-of-memory
+ return NULL;
+ }
+
+ ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, bufferStorage));
+
+ return static_cast<NativeBuffer11*>(bufferStorage)->getNativeBuffer();
+}
+
+ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat)
+{
+ BufferStorage11 *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK);
+
+ if (!storage)
+ {
+ // Storage out-of-memory
+ return NULL;
+ }
+
+ ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, storage));
+ ID3D11Buffer *buffer = static_cast<NativeBuffer11*>(storage)->getNativeBuffer();
+
+ auto bufferSRVIt = mBufferResourceViews.find(srvFormat);
+
+ if (bufferSRVIt != mBufferResourceViews.end())
+ {
+ if (bufferSRVIt->second.first == buffer)
+ {
+ return bufferSRVIt->second.second;
+ }
+ else
+ {
+ // The underlying buffer has changed since the SRV was created: recreate the SRV.
+ SafeRelease(bufferSRVIt->second.second);
+ }
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11ShaderResourceView *bufferSRV = NULL;
+
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(srvFormat);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc;
+ bufferSRVDesc.Buffer.ElementOffset = 0;
+ bufferSRVDesc.Buffer.ElementWidth = mSize / dxgiFormatInfo.pixelBytes;
+ bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+ bufferSRVDesc.Format = srvFormat;
+
+ HRESULT result = device->CreateShaderResourceView(buffer, &bufferSRVDesc, &bufferSRV);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(SUCCEEDED(result));
+
+ mBufferResourceViews[srvFormat] = BufferSRVPair(buffer, bufferSRV);
+
+ return bufferSRV;
+}
+
+gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams &params)
+{
+ PackStorage11 *packStorage = getPackStorage();
+
+ BufferStorage11 *latestStorage = getLatestBufferStorage();
+
+ if (packStorage)
+ {
+ gl::Error error = packStorage->packPixels(srcTexture, srcSubresource, params);
+ if (error.isError())
+ {
+ return error;
+ }
+ packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+Buffer11::BufferStorage11 *Buffer11::getBufferStorage(BufferUsage usage)
+{
+ BufferStorage11 *directBuffer = NULL;
+ auto directBufferIt = mBufferStorages.find(usage);
+ if (directBufferIt != mBufferStorages.end())
+ {
+ directBuffer = directBufferIt->second;
+ }
+
+ if (!directBuffer)
+ {
+ if (usage == BUFFER_USAGE_PIXEL_PACK)
+ {
+ directBuffer = new PackStorage11(mRenderer);
+ }
+ else
+ {
+ // buffer is not allocated, create it
+ directBuffer = new NativeBuffer11(mRenderer, usage);
+ }
+
+ mBufferStorages.insert(std::make_pair(usage, directBuffer));
+ }
+
+ // resize buffer
+ if (directBuffer->getSize() < mSize)
+ {
+ if (!directBuffer->resize(mSize, true))
+ {
+ // Out of memory error
+ return NULL;
+ }
+ }
+
+ BufferStorage11 *latestBuffer = getLatestBufferStorage();
+ if (latestBuffer && latestBuffer->getDataRevision() > directBuffer->getDataRevision())
+ {
+ // if copying from a pack buffer to a non-staging native buffer, we must first
+ // copy through the staging buffer, because other native buffers can't be mapped
+ if (latestBuffer->getUsage() == BUFFER_USAGE_PIXEL_PACK && !directBuffer->isMappable())
+ {
+ NativeBuffer11 *stagingBuffer = getStagingBuffer();
+
+ stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0);
+ directBuffer->setDataRevision(latestBuffer->getDataRevision());
+
+ latestBuffer = stagingBuffer;
+ }
+
+ // if copyFromStorage returns true, the D3D buffer has been recreated
+ // and we should update our serial
+ if (directBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0))
+ {
+ updateSerial();
+ }
+ directBuffer->setDataRevision(latestBuffer->getDataRevision());
+ }
+
+ return directBuffer;
+}
+
+Buffer11::BufferStorage11 *Buffer11::getLatestBufferStorage() const
+{
+ // Even though we iterate over all the direct buffers, it is expected that only
+ // 1 or 2 will be present.
+ BufferStorage11 *latestStorage = NULL;
+ DataRevision latestRevision = 0;
+ for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++)
+ {
+ BufferStorage11 *storage = it->second;
+ if (!latestStorage || storage->getDataRevision() > latestRevision)
+ {
+ latestStorage = storage;
+ latestRevision = storage->getDataRevision();
+ }
+ }
+
+ return latestStorage;
+}
+
+Buffer11::NativeBuffer11 *Buffer11::getStagingBuffer()
+{
+ BufferStorage11 *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING);
+
+ if (!stagingStorage)
+ {
+ // Out-of-memory
+ return NULL;
+ }
+
+ ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, stagingStorage));
+ return static_cast<NativeBuffer11*>(stagingStorage);
+}
+
+Buffer11::PackStorage11 *Buffer11::getPackStorage()
+{
+ BufferStorage11 *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK);
+
+ if (!packStorage)
+ {
+ // Out-of-memory
+ return NULL;
+ }
+
+ ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, packStorage));
+ return static_cast<PackStorage11*>(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.
+ // Check for absence of static buffer interfaces to detect dynamic data.
+ return (mStaticVertexBuffer && mStaticIndexBuffer);
+}
+
+Buffer11::BufferStorage11::BufferStorage11(Renderer11 *renderer, BufferUsage usage)
+ : mRenderer(renderer),
+ mUsage(usage),
+ mRevision(0),
+ mBufferSize(0)
+{
+}
+
+Buffer11::NativeBuffer11::NativeBuffer11(Renderer11 *renderer, BufferUsage usage)
+ : BufferStorage11(renderer, usage),
+ mNativeBuffer(NULL)
+{
+}
+
+Buffer11::NativeBuffer11::~NativeBuffer11()
+{
+ SafeRelease(mNativeBuffer);
+}
+
+// Returns true if it recreates the direct buffer
+bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset,
+ size_t size, size_t destOffset)
+{
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ size_t requiredSize = sourceOffset + size;
+ bool createBuffer = !mNativeBuffer || mBufferSize < requiredSize;
+
+ // (Re)initialize D3D buffer if needed
+ if (createBuffer)
+ {
+ bool preserveData = (destOffset > 0);
+ resize(source->getSize(), preserveData);
+ }
+
+ if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK)
+ {
+ ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, source));
+
+ void *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT);
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT hr = context->Map(mNativeBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
+ UNUSED_ASSERTION_VARIABLE(hr);
+ ASSERT(SUCCEEDED(hr));
+
+ unsigned char *destPointer = static_cast<unsigned char *>(mappedResource.pData) + destOffset;
+
+ // Offset bounds are validated at the API layer
+ ASSERT(sourceOffset + size <= destOffset + mBufferSize);
+ memcpy(destPointer, sourcePointer, size);
+ }
+ else
+ {
+ ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source));
+
+ D3D11_BOX srcBox;
+ srcBox.left = sourceOffset;
+ srcBox.right = sourceOffset + size;
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source));
+ ID3D11Buffer *sourceBuffer = static_cast<NativeBuffer11*>(source)->getNativeBuffer();
+
+ context->CopySubresourceRegion(mNativeBuffer, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox);
+ }
+
+ return createBuffer;
+}
+
+bool Buffer11::NativeBuffer11::resize(size_t size, bool preserveData)
+{
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ D3D11_BUFFER_DESC bufferDesc;
+ fillBufferDesc(&bufferDesc, mRenderer, mUsage, size);
+
+ ID3D11Buffer *newBuffer;
+ HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);
+
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ if (mNativeBuffer && preserveData)
+ {
+ // We don't call resize if the buffer is big enough already.
+ ASSERT(mBufferSize <= size);
+
+ D3D11_BOX srcBox;
+ srcBox.left = 0;
+ srcBox.right = mBufferSize;
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeBuffer, 0, &srcBox);
+ }
+
+ // No longer need the old buffer
+ SafeRelease(mNativeBuffer);
+ mNativeBuffer = newBuffer;
+
+ mBufferSize = bufferDesc.ByteWidth;
+
+ return true;
+}
+
+void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *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 (!static_cast<Renderer11 *>(renderer)->isLevel9())
+ 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);
+ bufferDesc->ByteWidth = std::min<UINT>(bufferDesc->ByteWidth, renderer->getRendererCaps().maxUniformBlockSize);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield access)
+{
+ ASSERT(mUsage == BUFFER_USAGE_STAGING);
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access);
+ UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0);
+
+ HRESULT result = context->Map(mNativeBuffer, 0, d3dMapType, d3dMapFlag, &mappedResource);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(SUCCEEDED(result));
+
+ return static_cast<GLubyte*>(mappedResource.pData) + offset;
+}
+
+bool Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset)
+{
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = context->Map(mNativeBuffer, 0, mapMode, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ uint8_t *offsetBufferPointer = reinterpret_cast<uint8_t *>(mappedResource.pData) + offset;
+ memcpy(offsetBufferPointer, data, size);
+
+ context->Unmap(mNativeBuffer, 0);
+
+ return true;
+}
+
+void Buffer11::NativeBuffer11::unmap()
+{
+ ASSERT(mUsage == BUFFER_USAGE_STAGING);
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ context->Unmap(mNativeBuffer, 0);
+}
+
+Buffer11::PackStorage11::PackStorage11(Renderer11 *renderer)
+ : BufferStorage11(renderer, BUFFER_USAGE_PIXEL_PACK),
+ mStagingTexture(NULL),
+ mTextureFormat(DXGI_FORMAT_UNKNOWN),
+ mQueuedPackCommand(NULL),
+ mDataModified(false)
+{
+}
+
+Buffer11::PackStorage11::~PackStorage11()
+{
+ SafeRelease(mStagingTexture);
+ SafeDelete(mQueuedPackCommand);
+}
+
+bool Buffer11::PackStorage11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset,
+ size_t size, size_t destOffset)
+{
+ // We copy through a staging buffer when drawing with a pack buffer,
+ // or for other cases where we access the pack buffer
+ UNREACHABLE();
+ return false;
+}
+
+bool Buffer11::PackStorage11::resize(size_t size, bool preserveData)
+{
+ if (size != mBufferSize)
+ {
+ if (!mMemoryBuffer.resize(size))
+ {
+ return false;
+ }
+ mBufferSize = size;
+ }
+
+ return true;
+}
+
+void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield access)
+{
+ 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.
+
+ flushQueuedPackCommand();
+ mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0);
+
+ return mMemoryBuffer.data() + offset;
+}
+
+void Buffer11::PackStorage11::unmap()
+{
+ // No-op
+}
+
+gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params)
+{
+ flushQueuedPackCommand();
+ mQueuedPackCommand = new PackPixelsParams(params);
+
+ D3D11_TEXTURE2D_DESC textureDesc;
+ srcTexure->GetDesc(&textureDesc);
+
+ if (mStagingTexture != NULL &&
+ (mTextureFormat != textureDesc.Format ||
+ mTextureSize.width != params.area.width ||
+ mTextureSize.height != params.area.height))
+ {
+ SafeRelease(mStagingTexture);
+ mTextureSize.width = 0;
+ mTextureSize.height = 0;
+ mTextureFormat = DXGI_FORMAT_UNKNOWN;
+ }
+
+ if (mStagingTexture == NULL)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT hr;
+
+ mTextureSize.width = params.area.width;
+ mTextureSize.height = params.area.height;
+ mTextureFormat = textureDesc.Format;
+
+ D3D11_TEXTURE2D_DESC stagingDesc;
+ stagingDesc.Width = params.area.width;
+ stagingDesc.Height = params.area.height;
+ stagingDesc.MipLevels = 1;
+ stagingDesc.ArraySize = 1;
+ stagingDesc.Format = mTextureFormat;
+ 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;
+
+ hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture);
+ if (FAILED(hr))
+ {
+ ASSERT(hr == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging texture.");
+ }
+ }
+
+ // ReadPixels from multisampled FBOs isn't supported in current GL
+ ASSERT(textureDesc.SampleDesc.Count <= 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;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ // Asynchronous copy
+ immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Buffer11::PackStorage11::flushQueuedPackCommand()
+{
+ ASSERT(mMemoryBuffer.size() > 0);
+
+ if (mQueuedPackCommand)
+ {
+ mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data());
+ SafeDelete(mQueuedPackCommand);
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h
new file mode 100644
index 0000000000..5f24fb4e2d
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h
@@ -0,0 +1,105 @@
+//
+// 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 LIBGLESV2_RENDERER_BUFFER11_H_
+#define LIBGLESV2_RENDERER_BUFFER11_H_
+
+#include "libGLESv2/renderer/d3d/BufferD3D.h"
+#include "libGLESv2/renderer/d3d/MemoryBuffer.h"
+#include "libGLESv2/angletypes.h"
+
+namespace rx
+{
+class Renderer11;
+
+enum BufferUsage
+{
+ BUFFER_USAGE_STAGING,
+ BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK,
+ BUFFER_USAGE_INDEX,
+ BUFFER_USAGE_PIXEL_UNPACK,
+ BUFFER_USAGE_PIXEL_PACK,
+ BUFFER_USAGE_UNIFORM,
+};
+
+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;
+};
+
+typedef size_t DataRevision;
+
+class Buffer11 : public BufferD3D
+{
+ public:
+ Buffer11(rx::Renderer11 *renderer);
+ virtual ~Buffer11();
+
+ static Buffer11 *makeBuffer11(BufferImpl *buffer);
+
+ ID3D11Buffer *getBuffer(BufferUsage usage);
+ ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat);
+ bool isMapped() const { return mMappedStorage != NULL; }
+ gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params);
+
+ // BufferD3D implementation
+ virtual size_t getSize() const { return mSize; }
+ virtual bool supportsDirectBinding() const;
+ virtual Renderer* getRenderer();
+
+ // BufferImpl implementation
+ virtual gl::Error setData(const void* data, size_t size, GLenum usage);
+ virtual void *getData();
+ virtual gl::Error setSubData(const void* data, size_t size, size_t offset);
+ virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
+ virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr);
+ virtual gl::Error unmap();
+ virtual void markTransformFeedbackUsage();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Buffer11);
+
+ class BufferStorage11;
+ class NativeBuffer11;
+ class PackStorage11;
+
+ rx::Renderer11 *mRenderer;
+ size_t mSize;
+
+ BufferStorage11 *mMappedStorage;
+
+ std::map<BufferUsage, BufferStorage11*> mBufferStorages;
+
+ typedef std::pair<ID3D11Buffer *, ID3D11ShaderResourceView *> BufferSRVPair;
+ std::map<DXGI_FORMAT, BufferSRVPair> mBufferResourceViews;
+
+ MemoryBuffer mResolvedData;
+ DataRevision mResolvedDataRevision;
+ unsigned int mReadUsageCount;
+
+ void markBufferUsage();
+ NativeBuffer11 *getStagingBuffer();
+ PackStorage11 *getPackStorage();
+
+ BufferStorage11 *getBufferStorage(BufferUsage usage);
+ BufferStorage11 *getLatestBufferStorage() const;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_BUFFER11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
new file mode 100644
index 0000000000..765d34fd3f
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
@@ -0,0 +1,555 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d11/Clear11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libGLESv2/formatutils.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
+
+// Precompiled shaders
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatvs.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatps.h"
+
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintvs.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintps.h"
+
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintvs.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintps.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 != NULL)
+ {
+ 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);
+}
+
+template <unsigned int vsSize, unsigned int psSize>
+Clear11::ClearShader Clear11::CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize])
+{
+ HRESULT result;
+
+ ClearShader shader = { 0 };
+
+ 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 },
+ };
+
+ result = device->CreateInputLayout(quadLayout, ArraySize(quadLayout), vsByteCode, vsSize, &shader.inputLayout);
+ ASSERT(SUCCEEDED(result));
+
+ result = device->CreateVertexShader(vsByteCode, vsSize, NULL, &shader.vertexShader);
+ ASSERT(SUCCEEDED(result));
+
+ result = device->CreatePixelShader(psByteCode, psSize, NULL, &shader.pixelShader);
+ ASSERT(SUCCEEDED(result));
+
+ return shader;
+}
+
+Clear11::Clear11(Renderer11 *renderer)
+ : mRenderer(renderer), mClearBlendStates(StructLessThan<ClearBlendInfo>), mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>),
+ mVertexBuffer(NULL), mRasterizerState(NULL)
+{
+ 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, NULL, &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 = mRenderer->isLevel9();
+ 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");
+
+ mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat);
+ if (mRenderer->isLevel9()) {
+ memset(&mUintClearShader, 0, sizeof(ClearShader));
+ memset(&mIntClearShader, 0, sizeof(ClearShader));
+ return;
+ }
+
+ mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint );
+ mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint );
+}
+
+Clear11::~Clear11()
+{
+ for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end(); i++)
+ {
+ SafeRelease(i->second);
+ }
+ mClearBlendStates.clear();
+
+ SafeRelease(mFloatClearShader.inputLayout);
+ SafeRelease(mFloatClearShader.vertexShader);
+ SafeRelease(mFloatClearShader.pixelShader);
+
+ SafeRelease(mUintClearShader.inputLayout);
+ SafeRelease(mUintClearShader.vertexShader);
+ SafeRelease(mUintClearShader.pixelShader);
+
+ SafeRelease(mIntClearShader.inputLayout);
+ SafeRelease(mIntClearShader.vertexShader);
+ SafeRelease(mIntClearShader.pixelShader);
+
+ for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++)
+ {
+ SafeRelease(i->second);
+ }
+ mClearDepthStencilStates.clear();
+
+ SafeRelease(mVertexBuffer);
+ SafeRelease(mRasterizerState);
+}
+
+gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
+{
+ // First determine if a scissored clear is needed, this will always require drawing a quad.
+ //
+ // Otherwise, iterate over the color buffers which require clearing and determine if they can be
+ // cleared with ID3D11DeviceContext::ClearRenderTargetView... 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.
+ //
+ // 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;
+ if (frameBuffer->getFirstColorbuffer() != NULL)
+ {
+ gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer();
+ framebufferSize.width = attachment->getWidth();
+ framebufferSize.height = attachment->getHeight();
+ framebufferSize.depth = 1;
+ }
+ else if (frameBuffer->getDepthOrStencilbuffer() != NULL)
+ {
+ gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer();
+ framebufferSize.width = attachment->getWidth();
+ framebufferSize.height = attachment->getHeight();
+ framebufferSize.depth = 1;
+ }
+ 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 = NULL;
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ {
+ if (clearParams.clearColor[colorAttachment] && frameBuffer->isEnabledColorAttachment(colorAttachment))
+ {
+ gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment);
+ if (attachment)
+ {
+ RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment);
+ if (!renderTarget)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
+ }
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat());
+
+ 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).", colorAttachment,
+ attachment->getInternalFormat());
+ }
+
+ 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 (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 scissored or masked clear is required
+ MaskedRenderTarget maskAndRt;
+ bool clearColor = clearParams.clearColor[colorAttachment];
+ 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 is possible
+
+ ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
+ if (!framebufferRTV)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
+ }
+
+ const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
+
+ // Check if the actual format has a channel that the internal format does not and set them to the
+ // default values
+ const float clearValues[4] =
+ {
+ ((formatInfo.redBits == 0 && actualFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red),
+ ((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
+ ((formatInfo.blueBits == 0 && actualFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue),
+ ((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
+ };
+
+ deviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
+ }
+ }
+ }
+ }
+
+ if (clearParams.clearDepth || clearParams.clearStencil)
+ {
+ gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer();
+ if (attachment)
+ {
+ RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment);
+ if (!renderTarget)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null.");
+ }
+
+ const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
+
+ unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << actualFormatInfo.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.size() > 0 || maskedClearDepthStencil)
+ {
+ // 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->getRendererCaps().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() : NULL;
+
+ 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;
+ const ClearShader* shader = NULL;
+ 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 : NULL;
+ 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 = framebufferSize.width;
+ viewport.Height = 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);
+ deviceContext->VSSetShader(shader->vertexShader, NULL, 0);
+ deviceContext->PSSetShader(shader->pixelShader, NULL, 0);
+ deviceContext->GSSetShader(NULL, NULL, 0);
+
+ // Apply vertex buffer
+ deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx);
+ deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+
+ // Apply render targets
+ deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv);
+
+ // Draw the clear quad
+ deviceContext->Draw(4, 0);
+
+ // Clean up
+ mRenderer->markAllStateDirty();
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>& rts)
+{
+ ClearBlendInfo blendKey = { 0 };
+ 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 i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ {
+ blendDesc.RenderTarget[i].BlendEnable = FALSE;
+ blendDesc.RenderTarget[i].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendKey.maskChannels[i][0],
+ blendKey.maskChannels[i][1],
+ blendKey.maskChannels[i][2],
+ blendKey.maskChannels[i][3]);
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11BlendState* blendState = NULL;
+ HRESULT result = device->CreateBlendState(&blendDesc, &blendState);
+ if (FAILED(result) || !blendState)
+ {
+ ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
+ return NULL;
+ }
+
+ mClearBlendStates[blendKey] = blendState;
+
+ return blendState;
+ }
+}
+
+ID3D11DepthStencilState *Clear11::getDepthStencilState(const gl::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 = NULL;
+ HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState);
+ if (FAILED(result) || !dsState)
+ {
+ ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
+ return NULL;
+ }
+
+ mClearDepthStencilStates[dsKey] = dsState;
+
+ return dsState;
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h
new file mode 100644
index 0000000000..be8e187c40
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h
@@ -0,0 +1,87 @@
+//
+// 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 LIBGLESV2_RENDERER_CLEAR11_H_
+#define LIBGLESV2_RENDERER_CLEAR11_H_
+
+#include "libGLESv2/angletypes.h"
+#include "libGLESv2/Error.h"
+
+#include <map>
+#include <vector>
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Renderer11;
+class RenderTarget11;
+
+class Clear11
+{
+ 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 gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
+
+ private:
+ Renderer11 *mRenderer;
+
+ struct ClearBlendInfo
+ {
+ bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4];
+ };
+ typedef bool (*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &);
+ typedef std::map<ClearBlendInfo, ID3D11BlendState*, ClearBlendInfoComparisonFunction> ClearBlendStateMap;
+ ClearBlendStateMap mClearBlendStates;
+
+ struct MaskedRenderTarget
+ {
+ bool colorMask[4];
+ RenderTarget11 *renderTarget;
+ };
+
+ ID3D11BlendState *getBlendState(const std::vector<MaskedRenderTarget> &rts);
+
+ struct ClearShader
+ {
+ ID3D11InputLayout *inputLayout;
+ ID3D11VertexShader *vertexShader;
+ ID3D11PixelShader *pixelShader;
+ };
+ ClearShader mFloatClearShader;
+ ClearShader mUintClearShader;
+ ClearShader mIntClearShader;
+
+ template <unsigned int vsSize, unsigned int psSize>
+ static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize]);
+
+ struct ClearDepthStencilInfo
+ {
+ bool clearDepth;
+ bool clearStencil;
+ UINT8 stencilWriteMask;
+ };
+ typedef bool (*ClearDepthStencilInfoComparisonFunction)(const ClearDepthStencilInfo&, const ClearDepthStencilInfo &);
+ typedef std::map<ClearDepthStencilInfo, ID3D11DepthStencilState*, ClearDepthStencilInfoComparisonFunction> ClearDepthStencilStateMap;
+ ClearDepthStencilStateMap mClearDepthStencilStates;
+
+ ID3D11DepthStencilState *getDepthStencilState(const gl::ClearParameters &clearParams);
+
+ ID3D11Buffer *mVertexBuffer;
+ ID3D11RasterizerState *mRasterizerState;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_CLEAR11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp
new file mode 100644
index 0000000000..a841b52862
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp
@@ -0,0 +1,70 @@
+//
+// 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::Fence11 class which implements rx::FenceImpl.
+
+#include "libGLESv2/renderer/d3d/d3d11/Fence11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+Fence11::Fence11(rx::Renderer11 *renderer)
+{
+ mRenderer = renderer;
+ mQuery = NULL;
+}
+
+Fence11::~Fence11()
+{
+ SafeRelease(mQuery);
+}
+
+bool Fence11::isSet() const
+{
+ return mQuery != NULL;
+}
+
+void Fence11::set()
+{
+ if (!mQuery)
+ {
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = D3D11_QUERY_EVENT;
+ queryDesc.MiscFlags = 0;
+
+ if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ mRenderer->getDeviceContext()->End(mQuery);
+}
+
+bool Fence11::test(bool flushCommandBuffer)
+{
+ ASSERT(mQuery);
+
+ UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH);
+ HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, getDataFlags);
+
+ if (mRenderer->isDeviceLost())
+ {
+ return gl::error(GL_OUT_OF_MEMORY, true);
+ }
+
+ ASSERT(result == S_OK || result == S_FALSE);
+ return (result == S_OK);
+}
+
+bool Fence11::hasError() const
+{
+ return mRenderer->isDeviceLost();
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h
index a5398bca14..50c7621776 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h
@@ -21,11 +21,10 @@ class Fence11 : public FenceImpl
explicit Fence11(rx::Renderer11 *renderer);
virtual ~Fence11();
- GLboolean isFence();
- void setFence(GLenum condition);
- GLboolean testFence();
- void finishFence();
- void getFenceiv(GLenum pname, GLint *params);
+ bool isSet() const;
+ void set();
+ bool test(bool flushCommandBuffer);
+ bool hasError() const;
private:
DISALLOW_COPY_AND_ASSIGN(Fence11);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
new file mode 100644
index 0000000000..7536713af4
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
@@ -0,0 +1,569 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Image11.h"
+#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
+#include "libGLESv2/main.h"
+
+#include "common/utilities.h"
+
+namespace rx
+{
+
+Image11::Image11()
+{
+ mStagingTexture = NULL;
+ mRenderer = NULL;
+ mDXGIFormat = DXGI_FORMAT_UNKNOWN;
+ mRecoverFromStorage = false;
+ mAssociatedStorage = NULL;
+ mAssociatedStorageLevel = 0;
+ mAssociatedStorageLayerTarget = 0;
+ mRecoveredFromStorageCount = 0;
+}
+
+Image11::~Image11()
+{
+ disassociateStorage();
+ releaseStagingTexture();
+}
+
+Image11 *Image11::makeImage11(Image *img)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img));
+ return static_cast<rx::Image11*>(img);
+}
+
+void Image11::generateMipmap(Image11 *dest, Image11 *src)
+{
+ ASSERT(src->getDXGIFormat() == dest->getDXGIFormat());
+ ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth());
+ ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight());
+
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(src->getDXGIFormat());
+ ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL);
+
+ D3D11_MAPPED_SUBRESOURCE destMapped;
+ HRESULT destMapResult = dest->map(D3D11_MAP_WRITE, &destMapped);
+ if (FAILED(destMapResult))
+ {
+ ERR("Failed to map destination image for mip map generation. HRESULT:0x%X", destMapResult);
+ return;
+ }
+
+ D3D11_MAPPED_SUBRESOURCE srcMapped;
+ HRESULT srcMapResult = src->map(D3D11_MAP_READ, &srcMapped);
+ if (FAILED(srcMapResult))
+ {
+ ERR("Failed to map source image for mip map generation. HRESULT:0x%X", srcMapResult);
+
+ dest->unmap();
+ return;
+ }
+
+ const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(srcMapped.pData);
+ uint8_t *destData = reinterpret_cast<uint8_t*>(destMapped.pData);
+
+ dxgiFormatInfo.mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(),
+ sourceData, srcMapped.RowPitch, srcMapped.DepthPitch,
+ destData, destMapped.RowPitch, destMapped.DepthPitch);
+
+ dest->unmap();
+ src->unmap();
+
+ dest->markDirty();
+}
+
+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 && !(d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL))
+ {
+ return false;
+ }
+
+ return mDirty;
+}
+
+bool Image11::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage);
+ return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height);
+}
+
+bool Image11::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage);
+ return copyToStorageImpl(storage11, level, face, xoffset, yoffset, width, height);
+}
+
+bool Image11::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
+{
+ TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage);
+ return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height);
+}
+
+bool Image11::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height)
+{
+ TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage);
+ return copyToStorageImpl(storage11, level, arrayLayer, xoffset, yoffset, width, height);
+}
+
+bool Image11::copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ // 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.
+ storage11->releaseAssociatedImage(level, layerTarget, this);
+ }
+
+ bool updateSubresourceSuccess = storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, layerTarget, xoffset, yoffset, 0, width, height, 1);
+
+ // Once the image data has been copied into the Storage, we can release it locally.
+ if (attemptToReleaseStagingTexture && updateSubresourceSuccess)
+ {
+ storage11->associateImage(this, level, layerTarget);
+ releaseStagingTexture();
+ mRecoverFromStorage = true;
+ mAssociatedStorage = storage11;
+ mAssociatedStorageLevel = level;
+ mAssociatedStorageLayerTarget = layerTarget;
+ }
+
+ return updateSubresourceSuccess;
+}
+
+bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const
+{
+ return (mAssociatedStorage == textureStorage);
+}
+
+bool Image11::recoverFromAssociatedStorage()
+{
+ if (mRecoverFromStorage)
+ {
+ createStagingTexture();
+
+ bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, 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
+ mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedStorageLevel, mAssociatedStorageLayerTarget, 0, 0, 0, mWidth, mHeight, mDepth);
+ mRecoveredFromStorageCount += 1;
+ }
+
+ // Reset all the recovery parameters, even if the texture storage association is broken.
+ disassociateStorage();
+
+ return textureStorageCorrect;
+ }
+
+ return false;
+}
+
+void Image11::disassociateStorage()
+{
+ if (mRecoverFromStorage)
+ {
+ // Make the texturestorage release the Image11 too
+ mAssociatedStorage->disassociateImage(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this);
+
+ mRecoverFromStorage = false;
+ mAssociatedStorage = NULL;
+ mAssociatedStorageLevel = 0;
+ mAssociatedStorageLayerTarget = 0;
+ }
+}
+
+bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease)
+{
+ if (mWidth != width ||
+ mHeight != 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;
+
+ mRenderer = Renderer11::makeRenderer11(renderer);
+
+ mWidth = width;
+ mHeight = height;
+ mDepth = depth;
+ mInternalFormat = internalformat;
+ mTarget = target;
+
+ // compute the d3d format that will be used
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat);
+ mDXGIFormat = formatInfo.texFormat;
+ mActualFormat = dxgiFormatInfo.internalFormat;
+ mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
+
+ SafeRelease(mStagingTexture);
+ 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.
+void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+ GLint unpackAlignment, GLenum type, const void *input)
+{
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+ GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpackAlignment);
+
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
+ GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
+
+ const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat);
+ LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type);
+
+ D3D11_MAPPED_SUBRESOURCE mappedImage;
+ HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
+ if (FAILED(result))
+ {
+ ERR("Could not map image for loading.");
+ return;
+ }
+
+ uint8_t* offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch));
+ loadFunction(width, height, depth,
+ reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
+ offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
+
+ unmap();
+}
+
+void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+ const void *input)
+{
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+ GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
+
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
+ GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
+ GLuint outputBlockWidth = dxgiFormatInfo.blockWidth;
+ GLuint outputBlockHeight = dxgiFormatInfo.blockHeight;
+
+ ASSERT(xoffset % outputBlockWidth == 0);
+ ASSERT(yoffset % outputBlockHeight == 0);
+
+ const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat);
+ LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE);
+
+ D3D11_MAPPED_SUBRESOURCE mappedImage;
+ HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
+ if (FAILED(result))
+ {
+ ERR("Could not map image for loading.");
+ return;
+ }
+
+ uint8_t* offsetMappedData = reinterpret_cast<uint8_t*>(mappedImage.pData) + ((yoffset / outputBlockHeight) * mappedImage.RowPitch +
+ (xoffset / outputBlockWidth) * outputPixelSize +
+ zoffset * mappedImage.DepthPitch);
+
+ loadFunction(width, height, depth,
+ reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
+ offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
+
+ unmap();
+}
+
+void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+{
+ gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer();
+
+ if (colorbuffer && colorbuffer->getActualFormat() == mActualFormat)
+ {
+ // No conversion needed-- use copyback fastpath
+ ID3D11Texture2D *colorBufferTexture = NULL;
+ unsigned int subresourceIndex = 0;
+
+ if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
+ {
+ D3D11_TEXTURE2D_DESC textureDesc;
+ colorBufferTexture->GetDesc(&textureDesc);
+
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ ID3D11Texture2D* srcTex = NULL;
+ if (textureDesc.SampleDesc.Count > 1)
+ {
+ D3D11_TEXTURE2D_DESC resolveDesc;
+ resolveDesc.Width = textureDesc.Width;
+ resolveDesc.Height = textureDesc.Height;
+ resolveDesc.MipLevels = 1;
+ resolveDesc.ArraySize = 1;
+ resolveDesc.Format = textureDesc.Format;
+ resolveDesc.SampleDesc.Count = 1;
+ resolveDesc.SampleDesc.Quality = 0;
+ resolveDesc.Usage = D3D11_USAGE_DEFAULT;
+ resolveDesc.BindFlags = 0;
+ resolveDesc.CPUAccessFlags = 0;
+ resolveDesc.MiscFlags = 0;
+
+ HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex);
+ if (FAILED(result))
+ {
+ ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
+ return;
+ }
+
+ deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format);
+ subresourceIndex = 0;
+ }
+ else
+ {
+ srcTex = colorBufferTexture;
+ srcTex->AddRef();
+ }
+
+ D3D11_BOX srcBox;
+ srcBox.left = x;
+ srcBox.right = x + width;
+ srcBox.top = y;
+ srcBox.bottom = y + height;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, zoffset, srcTex, subresourceIndex, &srcBox);
+
+ SafeRelease(srcTex);
+ SafeRelease(colorBufferTexture);
+ }
+ }
+ else
+ {
+ // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
+ D3D11_MAPPED_SUBRESOURCE mappedImage;
+ HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
+ if (FAILED(result))
+ {
+ ERR("Failed to map texture for Image11::copy, HRESULT: 0x%X.", result);
+ return;
+ }
+
+ // determine the offset coordinate into the destination buffer
+ GLsizei rowOffset = gl::GetInternalFormatInfo(mActualFormat).pixelBytes * xoffset;
+ uint8_t *dataOffset = static_cast<uint8_t*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch;
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+
+ mRenderer->readPixels(source, x, y, width, height, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
+
+ unmap();
+ }
+}
+
+ID3D11Resource *Image11::getStagingTexture()
+{
+ createStagingTexture();
+
+ return mStagingTexture;
+}
+
+void Image11::releaseStagingTexture()
+{
+ SafeRelease(mStagingTexture);
+}
+
+unsigned int Image11::getStagingSubresource()
+{
+ createStagingTexture();
+
+ return mStagingSubresource;
+}
+
+void Image11::createStagingTexture()
+{
+ if (mStagingTexture)
+ {
+ return;
+ }
+
+ const DXGI_FORMAT dxgiFormat = getDXGIFormat();
+
+ if (mWidth > 0 && mHeight > 0 && mDepth > 0)
+ {
+ 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::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
+ {
+ std::vector<D3D11_SUBRESOURCE_DATA> initialData;
+ std::vector< std::vector<BYTE> > textureData;
+ d3d11::GenerateInitialTextureData(mInternalFormat, 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);
+ ERR("Creating image failed.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ 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::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
+ {
+ std::vector<D3D11_SUBRESOURCE_DATA> initialData;
+ std::vector< std::vector<BYTE> > textureData;
+ d3d11::GenerateInitialTextureData(mInternalFormat, 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);
+ ERR("Creating image failed.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ mStagingTexture = newTexture;
+ mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+
+ mDirty = false;
+}
+
+HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
+{
+ createStagingTexture();
+
+ // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE.
+ recoverFromAssociatedStorage();
+
+ HRESULT result = E_FAIL;
+
+ if (mStagingTexture)
+ {
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map);
+
+ // this can fail if the device is removed (from TDR)
+ if (d3d11::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ }
+ else if (SUCCEEDED(result))
+ {
+ mDirty = true;
+ }
+ }
+
+ return result;
+}
+
+void Image11::unmap()
+{
+ if (mStagingTexture)
+ {
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->Unmap(mStagingTexture, mStagingSubresource);
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h
new file mode 100644
index 0000000000..a76a61f036
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h
@@ -0,0 +1,89 @@
+//
+// 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 LIBGLESV2_RENDERER_IMAGE11_H_
+#define LIBGLESV2_RENDERER_IMAGE11_H_
+
+#include "libGLESv2/renderer/d3d/ImageD3D.h"
+
+#include "common/debug.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Renderer;
+class Renderer11;
+class TextureStorage11;
+
+class Image11 : public ImageD3D
+{
+ public:
+ Image11();
+ virtual ~Image11();
+
+ static Image11 *makeImage11(Image *img);
+
+ static void generateMipmap(Image11 *dest, Image11 *src);
+
+ virtual bool isDirty() const;
+
+ virtual bool copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+ virtual bool copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+ virtual bool copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+ virtual bool copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height);
+
+ virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease);
+
+ DXGI_FORMAT getDXGIFormat() const;
+
+ virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+ GLint unpackAlignment, GLenum type, const void *input);
+ virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+ const void *input);
+
+ virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+
+ bool recoverFromAssociatedStorage();
+ bool isAssociatedStorageValid(TextureStorage11* textureStorage) const;
+ void disassociateStorage();
+
+ protected:
+ HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
+ void unmap();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Image11);
+
+ bool copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+ ID3D11Resource *getStagingTexture();
+ unsigned int getStagingSubresource();
+ void createStagingTexture();
+ void releaseStagingTexture();
+
+ Renderer11 *mRenderer;
+
+ DXGI_FORMAT mDXGIFormat;
+ ID3D11Resource *mStagingTexture;
+ unsigned int mStagingSubresource;
+
+ bool mRecoverFromStorage;
+ TextureStorage11 *mAssociatedStorage;
+ int mAssociatedStorageLevel;
+ int mAssociatedStorageLayerTarget;
+ unsigned int mRecoveredFromStorageCount;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_IMAGE11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp
new file mode 100644
index 0000000000..9a61182ee9
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp
@@ -0,0 +1,162 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.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);
+ }
+ }
+
+ mBufferSize = bufferSize;
+ mIndexType = indexType;
+ mDynamicUsage = dynamic;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer));
+ return static_cast<IndexBuffer11*>(indexBuffer);
+}
+
+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/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h
index 39a61946ad..f7c2b38e7e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h
@@ -9,7 +9,7 @@
#ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_
#define LIBGLESV2_RENDERER_INDEXBUFFER11_H_
-#include "libGLESv2/renderer/IndexBuffer.h"
+#include "libGLESv2/renderer/d3d/IndexBuffer.h"
namespace rx
{
@@ -21,18 +21,18 @@ class IndexBuffer11 : public IndexBuffer
explicit IndexBuffer11(Renderer11 *const renderer);
virtual ~IndexBuffer11();
- virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
+ virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
static IndexBuffer11 *makeIndexBuffer11(IndexBuffer *indexBuffer);
- virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory);
- virtual bool unmapBuffer();
+ 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 bool setSize(unsigned int bufferSize, GLenum indexType);
+ virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType);
- virtual bool discard();
+ virtual gl::Error discard();
DXGI_FORMAT getIndexFormat() const;
ID3D11Buffer *getBuffer() const;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
index 4940b8c638..d835e4fa68 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -8,19 +7,35 @@
// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches
// D3D11 input layouts.
-#include "libGLESv2/renderer/d3d11/InputLayoutCache.h"
-#include "libGLESv2/renderer/d3d11/VertexBuffer11.h"
-#include "libGLESv2/renderer/d3d11/BufferStorage11.h"
-#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h"
+#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h"
+#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/renderer/d3d/VertexDataManager.h"
#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/renderer/VertexDataManager.h"
+#include "libGLESv2/VertexAttribute.h"
#include "third_party/murmurhash/MurmurHash3.h"
namespace rx
{
+static void GetInputLayout(const TranslatedAttribute translatedAttributes[gl::MAX_VERTEX_ATTRIBS],
+ gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS])
+{
+ for (unsigned int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ const TranslatedAttribute &translatedAttribute = translatedAttributes[attributeIndex];
+
+ if (translatedAttributes[attributeIndex].active)
+ {
+ inputLayout[attributeIndex] = gl::VertexFormat(*translatedAttribute.attribute,
+ translatedAttribute.currentValueType);
+ }
+ }
+}
+
const unsigned int InputLayoutCache::kMaxInputLayouts = 1024;
InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts)
@@ -31,7 +46,7 @@ InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInp
mCurrentIL = NULL;
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
- mCurrentBuffers[i] = -1;
+ mCurrentBuffers[i] = NULL;
mCurrentVertexStrides[i] = -1;
mCurrentVertexOffsets[i] = -1;
}
@@ -53,7 +68,7 @@ void InputLayoutCache::clear()
{
for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++)
{
- i->second.inputLayout->Release();
+ SafeRelease(i->second.inputLayout);
}
mInputLayoutMap.clear();
markDirty();
@@ -64,42 +79,36 @@ void InputLayoutCache::markDirty()
mCurrentIL = NULL;
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
- mCurrentBuffers[i] = -1;
+ mCurrentBuffers[i] = NULL;
mCurrentVertexStrides[i] = -1;
mCurrentVertexOffsets[i] = -1;
}
}
-GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
- gl::ProgramBinary *programBinary)
+gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
+ gl::ProgramBinary *programBinary)
{
int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS];
programBinary->sortAttributesByLayout(attributes, sortedSemanticIndices);
if (!mDevice || !mDeviceContext)
{
- ERR("InputLayoutCache is not initialized.");
- return GL_INVALID_OPERATION;
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal input layout cache is not initialized.");
}
InputLayoutKey ilKey = { 0 };
- ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL };
- unsigned int vertexBufferSerials[gl::MAX_VERTEX_ATTRIBS] = { 0 };
- UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 };
- UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 };
-
static const char* semanticName = "TEXCOORD";
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
if (attributes[i].active)
{
- VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer);
- BufferStorage11 *bufferStorage = attributes[i].storage ? BufferStorage11::makeBufferStorage11(attributes[i].storage) : NULL;
-
D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
+ gl::VertexFormat vertexFormat(*attributes[i].attribute, attributes[i].currentValueType);
+ const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat);
+
// Record the type of the associated vertex shader vector in our key
// This will prevent mismatched vertex shaders from using the same input layout
GLint attributeSize;
@@ -107,31 +116,28 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName;
ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i;
- ilKey.elements[ilKey.elementCount].desc.Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT;
+ ilKey.elements[ilKey.elementCount].desc.Format = vertexFormatInfo.nativeFormat;
ilKey.elements[ilKey.elementCount].desc.InputSlot = i;
ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0;
ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass;
ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor;
ilKey.elementCount++;
-
- vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX) : vertexBuffer->getBuffer();
- vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial();
- vertexStrides[i] = attributes[i].stride;
- vertexOffsets[i] = attributes[i].offset;
}
}
ID3D11InputLayout *inputLayout = NULL;
- InputLayoutMap::iterator i = mInputLayoutMap.find(ilKey);
- if (i != mInputLayoutMap.end())
+ InputLayoutMap::iterator keyIter = mInputLayoutMap.find(ilKey);
+ if (keyIter != mInputLayoutMap.end())
{
- inputLayout = i->second.inputLayout;
- i->second.lastUsedTime = mCounter++;
+ inputLayout = keyIter->second.inputLayout;
+ keyIter->second.lastUsedTime = mCounter++;
}
else
{
- ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
+ gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS];
+ GetInputLayout(attributes, shaderInputLayout);
+ ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutableForInputLayout(shaderInputLayout));
D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS];
for (unsigned int j = 0; j < ilKey.elementCount; ++j)
@@ -142,8 +148,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout);
if (FAILED(result))
{
- ERR("Failed to crate input layout, result: 0x%08x", result);
- return GL_INVALID_OPERATION;
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result);
}
if (mInputLayoutMap.size() >= kMaxInputLayouts)
@@ -159,7 +164,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
leastRecentlyUsed = i;
}
}
- leastRecentlyUsed->second.inputLayout->Release();
+ SafeRelease(leastRecentlyUsed->second.inputLayout);
mInputLayoutMap.erase(leastRecentlyUsed);
}
@@ -176,19 +181,46 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
mCurrentIL = inputLayout;
}
+ bool dirtyBuffers = false;
+ size_t minDiff = gl::MAX_VERTEX_ATTRIBS;
+ size_t maxDiff = 0;
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
- if (vertexBufferSerials[i] != mCurrentBuffers[i] || vertexStrides[i] != mCurrentVertexStrides[i] ||
- vertexOffsets[i] != mCurrentVertexOffsets[i])
+ ID3D11Buffer *buffer = NULL;
+
+ if (attributes[i].active)
+ {
+ VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer);
+ Buffer11 *bufferStorage = attributes[i].storage ? Buffer11::makeBuffer11(attributes[i].storage) : NULL;
+
+ buffer = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK)
+ : vertexBuffer->getBuffer();
+ }
+
+ UINT vertexStride = attributes[i].stride;
+ UINT vertexOffset = attributes[i].offset;
+
+ if (buffer != mCurrentBuffers[i] || vertexStride != mCurrentVertexStrides[i] ||
+ vertexOffset != mCurrentVertexOffsets[i])
{
- mDeviceContext->IASetVertexBuffers(i, 1, &vertexBuffers[i], &vertexStrides[i], &vertexOffsets[i]);
- mCurrentBuffers[i] = vertexBufferSerials[i];
- mCurrentVertexStrides[i] = vertexStrides[i];
- mCurrentVertexOffsets[i] = vertexOffsets[i];
+ dirtyBuffers = true;
+ minDiff = std::min(minDiff, static_cast<size_t>(i));
+ maxDiff = std::max(maxDiff, static_cast<size_t>(i));
+
+ mCurrentBuffers[i] = buffer;
+ mCurrentVertexStrides[i] = vertexStride;
+ mCurrentVertexOffsets[i] = vertexOffset;
}
}
- return GL_NO_ERROR;
+ if (dirtyBuffers)
+ {
+ ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS);
+ mDeviceContext->IASetVertexBuffers(minDiff, maxDiff - minDiff + 1, mCurrentBuffers + minDiff,
+ mCurrentVertexStrides + minDiff, mCurrentVertexOffsets + minDiff);
+ }
+
+ return gl::Error(GL_NO_ERROR);
}
std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout)
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h
index bb1a8eebcf..cc71ac3f6f 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h
@@ -11,8 +11,14 @@
#define LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_
#include "libGLESv2/Constants.h"
+#include "libGLESv2/Error.h"
#include "common/angleutils.h"
+#include <GLES2/gl2.h>
+
+#include <cstddef>
+#include <unordered_map>
+
namespace gl
{
class ProgramBinary;
@@ -32,8 +38,8 @@ class InputLayoutCache
void clear();
void markDirty();
- GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
- gl::ProgramBinary *programBinary);
+ gl::Error applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
+ gl::ProgramBinary *programBinary);
private:
DISALLOW_COPY_AND_ASSIGN(InputLayoutCache);
@@ -67,7 +73,7 @@ class InputLayoutCache
};
ID3D11InputLayout *mCurrentIL;
- unsigned int mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS];
+ ID3D11Buffer *mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS];
UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS];
UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS];
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
new file mode 100644
index 0000000000..a4e84f91c2
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
@@ -0,0 +1,252 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libGLESv2/formatutils.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/Context.h"
+
+// Precompiled shaders
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturevs.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturegs.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4fps.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4ips.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4uips.h"
+
+namespace rx
+{
+
+PixelTransfer11::PixelTransfer11(Renderer11 *renderer)
+ : mRenderer(renderer),
+ mBufferToTextureVS(NULL),
+ mBufferToTextureGS(NULL),
+ mParamsConstantBuffer(NULL),
+ mCopyRasterizerState(NULL),
+ mCopyDepthStencilState(NULL)
+{
+ 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));
+
+ 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));
+
+ D3D11_BUFFER_DESC constantBufferDesc = { 0 };
+ constantBufferDesc.ByteWidth = rx::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));
+ d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer");
+
+ StructZero(&mParamsData);
+
+ // init shaders
+ if (mRenderer->isLevel9())
+ return;
+
+ mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS");
+ mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
+
+ buildShaderMap();
+}
+
+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);
+}
+
+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;
+ parametersOut->PixelsPerRow = static_cast<unsigned int>(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);
+}
+
+bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+ GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
+{
+ gl::Extents destSize = destRenderTarget->getExtents();
+
+ if (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 )
+ {
+ return false;
+ }
+
+ 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::GetFormatTypeInfo(unsizedFormat, sourcePixelsType).internalFormat;
+
+ const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat);
+ DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat;
+ ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN);
+ Buffer11 *bufferStorage11 = Buffer11::makeBuffer11(sourceBuffer.getImplementation());
+ ID3D11ShaderResourceView *bufferSRV = bufferStorage11->getSRV(srvFormat);
+ ASSERT(bufferSRV != NULL);
+
+ ID3D11RenderTargetView *textureRTV = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView();
+ ASSERT(textureRTV != NULL);
+
+ CopyShaderParams shaderParams;
+ setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams);
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ ID3D11ShaderResourceView *nullSRV = NULL;
+ ID3D11Buffer *nullBuffer = NULL;
+ UINT zero = 0;
+
+ // Are we doing a 2D or 3D copy?
+ ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL);
+
+ deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0);
+ deviceContext->GSSetShader(geometryShader, NULL, 0);
+ deviceContext->PSSetShader(pixelShader, NULL, 0);
+ deviceContext->PSSetShaderResources(0, 1, &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);
+
+ mRenderer->setOneTimeRenderTarget(textureRTV);
+
+ 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 = destSize.width;
+ viewport.Height = 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
+ deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+ deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer);
+
+ mRenderer->markAllStateDirty();
+
+ return true;
+}
+
+void 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");
+}
+
+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);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h
new file mode 100644
index 0000000000..ed1a3ae1d0
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h
@@ -0,0 +1,86 @@
+//
+// 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 LIBGLESV2_PIXELTRANSFER11_H_
+#define LIBGLESV2_PIXELTRANSFER11_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 RenderTarget;
+
+class PixelTransfer11
+{
+ public:
+ explicit PixelTransfer11(Renderer11 *renderer);
+ ~PixelTransfer11();
+
+ static bool supportsBufferToTextureCopy(GLenum internalFormat);
+
+ // 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
+ bool copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *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];
+ };
+
+ static void setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat,
+ const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut);
+
+ void buildShaderMap();
+ ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const;
+
+ Renderer11 *mRenderer;
+
+ std::map<GLenum, ID3D11PixelShader *> mBufferToTexturePSMap;
+ ID3D11VertexShader *mBufferToTextureVS;
+ ID3D11GeometryShader *mBufferToTextureGS;
+ ID3D11Buffer *mParamsConstantBuffer;
+ CopyShaderParams mParamsData;
+
+ ID3D11RasterizerState *mCopyRasterizerState;
+ ID3D11DepthStencilState *mCopyDepthStencilState;
+
+};
+
+}
+
+#endif // LIBGLESV2_PIXELTRANSFER11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp
new file mode 100644
index 0000000000..7109be3e28
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp
@@ -0,0 +1,156 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d11/Query11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libGLESv2/main.h"
+
+#include <GLES2/gl2ext.h>
+
+namespace rx
+{
+
+Query11::Query11(rx::Renderer11 *renderer, GLenum type)
+ : QueryImpl(type),
+ mResult(0),
+ mQueryFinished(false),
+ mRenderer(renderer),
+ mQuery(NULL)
+{
+}
+
+Query11::~Query11()
+{
+ SafeRelease(mQuery);
+}
+
+gl::Error Query11::begin()
+{
+ if (mQuery == NULL)
+ {
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = gl_d3d11::ConvertQueryType(getType());
+ queryDesc.MiscFlags = 0;
+
+ HRESULT result = mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result);
+ }
+ }
+
+ mRenderer->getDeviceContext()->Begin(mQuery);
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Query11::end()
+{
+ ASSERT(mQuery);
+ mRenderer->getDeviceContext()->End(mQuery);
+
+ mQueryFinished = false;
+ mResult = GL_FALSE;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Query11::getResult(GLuint *params)
+{
+ while (!mQueryFinished)
+ {
+ gl::Error error = testQuery();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!mQueryFinished)
+ {
+ Sleep(0);
+ }
+ }
+
+ ASSERT(mQueryFinished);
+ *params = mResult;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Query11::isResultAvailable(GLuint *available)
+{
+ gl::Error error = testQuery();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *available = (mQueryFinished ? GL_TRUE : GL_FALSE);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Query11::testQuery()
+{
+ if (!mQueryFinished)
+ {
+ ASSERT(mQuery);
+
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ switch (getType())
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ {
+ UINT64 numPixels = 0;
+ HRESULT result = context->GetData(mQuery, &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)
+ {
+ mQueryFinished = true;
+ mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ break;
+
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ {
+ D3D11_QUERY_DATA_SO_STATISTICS soStats = { 0 };
+ HRESULT result = context->GetData(mQuery, &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)
+ {
+ mQueryFinished = true;
+ mResult = static_cast<GLuint>(soStats.NumPrimitivesWritten);
+ }
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ if (!mQueryFinished && mRenderer->testDeviceLost(true))
+ {
+ 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/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h
index 0a03de77ca..822f2542ee 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h
@@ -21,15 +21,19 @@ class Query11 : public QueryImpl
Query11(rx::Renderer11 *renderer, GLenum type);
virtual ~Query11();
- void begin();
- void end();
- GLuint getResult();
- GLboolean isResultAvailable();
+ virtual gl::Error begin();
+ virtual gl::Error end();
+ virtual gl::Error getResult(GLuint *params);
+ virtual gl::Error isResultAvailable(GLuint *available);
private:
DISALLOW_COPY_AND_ASSIGN(Query11);
- GLboolean testQuery();
+ gl::Error testQuery();
+
+ GLuint mResult;
+
+ bool mQueryFinished;
rx::Renderer11 *mRenderer;
ID3D11Query *mQuery;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp
index a1c324cd80..71b931f27e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp
@@ -1,6 +1,5 @@
-#include "precompiled.h"
//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -8,18 +7,29 @@
// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render
// state objects.
-#include "libGLESv2/renderer/d3d11/RenderStateCache.h"
-#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
-
+#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h"
+#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/utilities.h"
+#include "libGLESv2/FramebufferAttachment.h"
+
#include "common/debug.h"
+
#include "third_party/murmurhash/MurmurHash3.h"
namespace rx
{
+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
@@ -49,29 +59,10 @@ void RenderStateCache::initialize(ID3D11Device *device)
void RenderStateCache::clear()
{
- for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++)
- {
- i->second.first->Release();
- }
- mBlendStateCache.clear();
-
- for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++)
- {
- i->second.first->Release();
- }
- mRasterizerStateCache.clear();
-
- for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
- {
- i->second.first->Release();
- }
- mDepthStencilStateCache.clear();
-
- for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++)
- {
- i->second.first->Release();
- }
- mSamplerStateCache.clear();
+ ClearStateMap(mBlendStateCache);
+ ClearStateMap(mRasterizerStateCache);
+ ClearStateMap(mDepthStencilStateCache);
+ ClearStateMap(mSamplerStateCache);
}
std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState)
@@ -79,58 +70,56 @@ std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState)
static const unsigned int seed = 0xABCDEF98;
std::size_t hash = 0;
- MurmurHash3_x86_32(&blendState, sizeof(BlendStateKey), seed, &hash);
+ 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(gl::BlendState)) == 0;
+ return memcmp(&a, &b, sizeof(BlendStateKey)) == 0;
}
-ID3D11BlendState *RenderStateCache::getBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState)
+gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState,
+ ID3D11BlendState **outBlendState)
{
if (!mDevice)
{
- ERR("RenderStateCache is not initialized.");
- return NULL;
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
}
bool mrt = false;
+ const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender();
+
BlendStateKey key = { 0 };
key.blendState = blendState;
- for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
{
- gl::Renderbuffer *renderBuffer = framebuffer->getColorbuffer(i);
- if (renderBuffer)
+ const gl::FramebufferAttachment *attachment = colorbuffers[colorAttachment];
+
+ auto rtChannels = key.rtChannels[colorAttachment];
+
+ if (attachment)
{
- if (i > 0)
+ if (colorAttachment > 0)
{
mrt = true;
}
- GLenum internalFormat = renderBuffer->getInternalFormat();
- key.rtChannels[i][0] = gl::GetRedSize(internalFormat) > 0;
- key.rtChannels[i][1] = gl::GetGreenSize(internalFormat) > 0;
- key.rtChannels[i][2] = gl::GetBlueSize(internalFormat) > 0;;
- key.rtChannels[i][3] = gl::GetAlphaSize(internalFormat) > 0;
- }
- else
- {
- key.rtChannels[i][0] = false;
- key.rtChannels[i][1] = false;
- key.rtChannels[i][2] = false;
- key.rtChannels[i][3] = false;
+ rtChannels[0] = attachment->getRedSize() > 0;
+ rtChannels[1] = attachment->getGreenSize() > 0;
+ rtChannels[2] = attachment->getBlueSize() > 0;
+ rtChannels[3] = attachment->getAlphaSize() > 0;
}
}
- BlendStateMap::iterator i = mBlendStateCache.find(key);
- if (i != mBlendStateCache.end())
+ BlendStateMap::iterator keyIter = mBlendStateCache.find(key);
+ if (keyIter != mBlendStateCache.end())
{
- BlendStateCounterPair &state = i->second;
+ BlendStateCounterPair &state = keyIter->second;
state.second = mCounter++;
- return state.first;
+ *outBlendState = state.first;
+ return gl::Error(GL_NO_ERROR);
}
else
{
@@ -147,7 +136,7 @@ ID3D11BlendState *RenderStateCache::getBlendState(gl::Framebuffer *framebuffer,
leastRecentlyUsed = i;
}
}
- leastRecentlyUsed->second.first->Release();
+ SafeRelease(leastRecentlyUsed->second.first);
mBlendStateCache.erase(leastRecentlyUsed);
}
@@ -182,13 +171,13 @@ ID3D11BlendState *RenderStateCache::getBlendState(gl::Framebuffer *framebuffer,
HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState);
if (FAILED(result) || !dx11BlendState)
{
- ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
- return NULL;
+ 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++)));
- return dx11BlendState;
+ *outBlendState = dx11BlendState;
+ return gl::Error(GL_NO_ERROR);
}
}
@@ -206,26 +195,25 @@ bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, cons
return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
}
-ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState,
- bool scissorEnabled, unsigned int depthSize)
+gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled,
+ ID3D11RasterizerState **outRasterizerState)
{
if (!mDevice)
{
- ERR("RenderStateCache is not initialized.");
- return NULL;
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
}
- RasterizerStateKey key;
+ RasterizerStateKey key = { 0 };
key.rasterizerState = rasterState;
key.scissorEnabled = scissorEnabled;
- key.depthSize = depthSize;
- RasterizerStateMap::iterator i = mRasterizerStateCache.find(key);
- if (i != mRasterizerStateCache.end())
+ RasterizerStateMap::iterator keyIter = mRasterizerStateCache.find(key);
+ if (keyIter != mRasterizerStateCache.end())
{
- RasterizerStateCounterPair &state = i->second;
+ RasterizerStateCounterPair &state = keyIter->second;
state.second = mCounter++;
- return state.first;
+ *outRasterizerState = state.first;
+ return gl::Error(GL_NO_ERROR);
}
else
{
@@ -242,7 +230,7 @@ ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::Rasterizer
leastRecentlyUsed = i;
}
}
- leastRecentlyUsed->second.first->Release();
+ SafeRelease(leastRecentlyUsed->second.first);
mRasterizerStateCache.erase(leastRecentlyUsed);
}
@@ -258,25 +246,34 @@ ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::Rasterizer
rasterDesc.FillMode = D3D11_FILL_SOLID;
rasterDesc.CullMode = cullMode;
rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE;
- rasterDesc.DepthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(depthSize));
rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though.
- rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor;
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)
{
- ERR("Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result);
- return NULL;
+ 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++)));
- return dx11RasterizerState;
+ *outRasterizerState = dx11RasterizerState;
+ return gl::Error(GL_NO_ERROR);
}
}
@@ -294,20 +291,20 @@ bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a,
return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0;
}
-ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState)
+gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState, ID3D11DepthStencilState **outDSState)
{
if (!mDevice)
{
- ERR("RenderStateCache is not initialized.");
- return NULL;
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
}
- DepthStencilStateMap::iterator i = mDepthStencilStateCache.find(dsState);
- if (i != mDepthStencilStateCache.end())
+ DepthStencilStateMap::iterator keyIter = mDepthStencilStateCache.find(dsState);
+ if (keyIter != mDepthStencilStateCache.end())
{
- DepthStencilStateCounterPair &state = i->second;
+ DepthStencilStateCounterPair &state = keyIter->second;
state.second = mCounter++;
- return state.first;
+ *outDSState = state.first;
+ return gl::Error(GL_NO_ERROR);
}
else
{
@@ -324,7 +321,7 @@ ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthS
leastRecentlyUsed = i;
}
}
- leastRecentlyUsed->second.first->Release();
+ SafeRelease(leastRecentlyUsed->second.first);
mDepthStencilStateCache.erase(leastRecentlyUsed);
}
@@ -348,13 +345,13 @@ ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthS
HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState);
if (FAILED(result) || !dx11DepthStencilState)
{
- ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
- return NULL;
+ return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
}
mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++)));
- return dx11DepthStencilState;
+ *outDSState = dx11DepthStencilState;
+ return gl::Error(GL_NO_ERROR);
}
}
@@ -372,20 +369,20 @@ bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl:
return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0;
}
-ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &samplerState)
+gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState)
{
if (!mDevice)
{
- ERR("RenderStateCache is not initialized.");
- return NULL;
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
}
- SamplerStateMap::iterator i = mSamplerStateCache.find(samplerState);
- if (i != mSamplerStateCache.end())
+ SamplerStateMap::iterator keyIter = mSamplerStateCache.find(samplerState);
+ if (keyIter != mSamplerStateCache.end())
{
- SamplerStateCounterPair &state = i->second;
+ SamplerStateCounterPair &state = keyIter->second;
state.second = mCounter++;
- return state.first;
+ *outSamplerState = state.first;
+ return gl::Error(GL_NO_ERROR);
}
else
{
@@ -402,37 +399,37 @@ ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &sa
leastRecentlyUsed = i;
}
}
- leastRecentlyUsed->second.first->Release();
+ SafeRelease(leastRecentlyUsed->second.first);
mSamplerStateCache.erase(leastRecentlyUsed);
}
D3D11_SAMPLER_DESC samplerDesc;
- samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, samplerState.maxAnisotropy);
+ 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 = D3D11_TEXTURE_ADDRESS_CLAMP;
- samplerDesc.MipLODBias = static_cast<float>(samplerState.lodOffset);
+ samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR);
+ samplerDesc.MipLODBias = 0;
samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy;
- samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+ 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 = gl_d3d11::ConvertMinLOD(samplerState.minFilter, samplerState.lodOffset);
- samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0
- ? gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset) : FLT_MAX;
+ samplerDesc.MinLOD = samplerState.minLod;
+ samplerDesc.MaxLOD = samplerState.maxLod;
ID3D11SamplerState *dx11SamplerState = NULL;
HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState);
if (FAILED(result) || !dx11SamplerState)
{
- ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
- return NULL;
+ 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++)));
- return dx11SamplerState;
+ *outSamplerState = dx11SamplerState;
+ return gl::Error(GL_NO_ERROR);
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h
index b4b871a4bd..d5471a3061 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -11,8 +11,11 @@
#define LIBGLESV2_RENDERER_RENDERSTATECACHE_H_
#include "libGLESv2/angletypes.h"
+#include "libGLESv2/Error.h"
#include "common/angleutils.h"
+#include <unordered_map>
+
namespace gl
{
class Framebuffer;
@@ -20,6 +23,7 @@ class Framebuffer;
namespace rx
{
+class Renderer11;
class RenderStateCache
{
@@ -30,12 +34,10 @@ class RenderStateCache
void initialize(ID3D11Device *device);
void clear();
- // Increments refcount on the returned blend state, Release() must be called.
- ID3D11BlendState *getBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState);
- ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState,
- bool scissorEnabled, unsigned int depthSize);
- ID3D11DepthStencilState *getDepthStencilState(const gl::DepthStencilState &dsState);
- ID3D11SamplerState *getSamplerState(const gl::SamplerState &samplerState);
+ 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, ID3D11DepthStencilState **outDSState);
+ gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState);
private:
DISALLOW_COPY_AND_ASSIGN(RenderStateCache);
@@ -63,7 +65,6 @@ class RenderStateCache
{
gl::RasterizerState rasterizerState;
bool scissorEnabled;
- unsigned int depthSize;
};
static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState);
static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp
index 3707097aa4..3041f21faa 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -8,26 +7,66 @@
// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers
// retained by Renderbuffers.
-#include "libGLESv2/renderer/d3d11/RenderTarget11.h"
-#include "libGLESv2/renderer/d3d11/Renderer11.h"
-
-#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
#include "libGLESv2/main.h"
namespace rx
{
-static unsigned int getRTVSubresourceIndex(ID3D11Texture2D *texture, ID3D11RenderTargetView *view)
+static 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;
+}
+
+static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view)
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
view->GetDesc(&rtvDesc);
- D3D11_TEXTURE2D_DESC texDesc;
- texture->GetDesc(&texDesc);
-
unsigned int mipSlice = 0;
unsigned int arraySlice = 0;
- unsigned int mipLevels = texDesc.MipLevels;
switch (rtvDesc.ViewDimension)
{
@@ -76,20 +115,19 @@ static unsigned int getRTVSubresourceIndex(ID3D11Texture2D *texture, ID3D11Rende
break;
}
+ unsigned int mipLevels, samples;
+ getTextureProperties(resource, &mipLevels, &samples);
+
return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
}
-static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11DepthStencilView *view)
+static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view)
{
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
view->GetDesc(&dsvDesc);
- D3D11_TEXTURE2D_DESC texDesc;
- texture->GetDesc(&texDesc);
-
unsigned int mipSlice = 0;
unsigned int arraySlice = 0;
- unsigned int mipLevels = texDesc.MipLevels;
switch (dsvDesc.ViewDimension)
{
@@ -123,7 +161,7 @@ static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11Depth
arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice;
break;
- case D3D11_RTV_DIMENSION_UNKNOWN:
+ case D3D11_DSV_DIMENSION_UNKNOWN:
UNIMPLEMENTED();
break;
@@ -132,16 +170,37 @@ static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11Depth
break;
}
+ unsigned int mipLevels, samples;
+ getTextureProperties(resource, &mipLevels, &samples);
+
return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
}
-RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height)
+RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource,
+ ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth)
{
mRenderer = Renderer11::makeRenderer11(renderer);
- mTexture = tex;
+
+ mTexture = resource;
+ if (mTexture)
+ {
+ mTexture->AddRef();
+ }
+
mRenderTarget = rtv;
+ if (mRenderTarget)
+ {
+ mRenderTarget->AddRef();
+ }
+
mDepthStencil = NULL;
+
mShaderResource = srv;
+ if (mShaderResource)
+ {
+ mShaderResource->AddRef();
+ }
+
mSubresourceIndex = 0;
if (mRenderTarget && mTexture)
@@ -149,26 +208,46 @@ RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv,
D3D11_RENDER_TARGET_VIEW_DESC desc;
mRenderTarget->GetDesc(&desc);
- D3D11_TEXTURE2D_DESC texDesc;
- mTexture->GetDesc(&texDesc);
+ unsigned int mipLevels, samples;
+ getTextureProperties(mTexture, &mipLevels, &samples);
mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget);
mWidth = width;
mHeight = height;
- mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0;
+ mDepth = depth;
+ mSamples = samples;
- mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
- mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format);
+ mInternalFormat = dxgiFormatInfo.internalFormat;
+ mActualFormat = dxgiFormatInfo.internalFormat;
}
}
-RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height)
+RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource,
+ ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth)
{
mRenderer = Renderer11::makeRenderer11(renderer);
- mTexture = tex;
+
+ mTexture = resource;
+ if (mTexture)
+ {
+ mTexture->AddRef();
+ }
+
mRenderTarget = NULL;
+
mDepthStencil = dsv;
+ if (mDepthStencil)
+ {
+ mDepthStencil->AddRef();
+ }
+
mShaderResource = srv;
+ if (mShaderResource)
+ {
+ mShaderResource->AddRef();
+ }
+
mSubresourceIndex = 0;
if (mDepthStencil && mTexture)
@@ -176,20 +255,22 @@ RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv,
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
mDepthStencil->GetDesc(&desc);
- D3D11_TEXTURE2D_DESC texDesc;
- mTexture->GetDesc(&texDesc);
+ unsigned int mipLevels, samples;
+ getTextureProperties(mTexture, &mipLevels, &samples);
mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil);
mWidth = width;
mHeight = height;
- mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0;
+ mDepth = depth;
+ mSamples = samples;
- mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
- mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format);
+ mInternalFormat = dxgiFormatInfo.internalFormat;
+ mActualFormat = dxgiFormatInfo.internalFormat;
}
}
-RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth)
+RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples)
{
mRenderer = Renderer11::makeRenderer11(renderer);
mTexture = NULL;
@@ -197,14 +278,11 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height
mDepthStencil = NULL;
mShaderResource = NULL;
- DXGI_FORMAT requestedFormat = gl_d3d11::ConvertRenderbufferFormat(format);
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat);
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat);
- int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples);
- if (supportedSamples < 0)
- {
- gl::error(GL_OUT_OF_MEMORY);
- return;
- }
+ const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat);
+ GLuint supportedSamples = textureCaps.getNearestSamples(samples);
if (width > 0 && height > 0)
{
@@ -214,16 +292,35 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
- desc.Format = requestedFormat;
+ 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;
- desc.BindFlags = (depth ? D3D11_BIND_DEPTH_STENCIL : (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE));
+
+ // 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);
+ if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ // Multisample targets flagged for binding as depth stencil cannot also be
+ // flagged for binding as SRV, so make certain not to add the SRV flag for
+ // these targets.
+ bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1);
+ }
+
+ desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) |
+ (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) |
+ (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0);
ID3D11Device *device = mRenderer->getDevice();
- HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
+ ID3D11Texture2D *texture = NULL;
+ HRESULT result = device->CreateTexture2D(&desc, NULL, &texture);
+ mTexture = texture;
if (result == E_OUTOFMEMORY)
{
@@ -232,10 +329,28 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height
}
ASSERT(SUCCEEDED(result));
- if (depth)
+ 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 = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ SafeRelease(mTexture);
+ gl::error(GL_OUT_OF_MEMORY);
+ return;
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+
+ if (bindDSV)
{
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
- dsvDesc.Format = requestedFormat;
+ dsvDesc.Format = formatInfo.dsvFormat;
dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS;
dsvDesc.Texture2D.MipSlice = 0;
dsvDesc.Flags = 0;
@@ -243,82 +358,58 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height
if (result == E_OUTOFMEMORY)
{
- mTexture->Release();
- mTexture = NULL;
+ SafeRelease(mTexture);
+ SafeRelease(mShaderResource);
gl::error(GL_OUT_OF_MEMORY);
+ return;
}
ASSERT(SUCCEEDED(result));
}
- else
+
+ if (bindRTV)
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = requestedFormat;
+ rtvDesc.Format = formatInfo.rtvFormat;
rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
rtvDesc.Texture2D.MipSlice = 0;
result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget);
if (result == E_OUTOFMEMORY)
{
- mTexture->Release();
- mTexture = NULL;
+ SafeRelease(mTexture);
+ SafeRelease(mShaderResource);
+ SafeRelease(mDepthStencil);
gl::error(GL_OUT_OF_MEMORY);
return;
}
ASSERT(SUCCEEDED(result));
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srvDesc.Format = requestedFormat;
- srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
- srvDesc.Texture2D.MostDetailedMip = 0;
- srvDesc.Texture2D.MipLevels = 1;
- result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource);
-
- if (result == E_OUTOFMEMORY)
+ if (formatInfo.dataInitializerFunction != NULL)
{
- mTexture->Release();
- mTexture = NULL;
- mRenderTarget->Release();
- mRenderTarget = NULL;
- gl::error(GL_OUT_OF_MEMORY);
- return;
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
+ context->ClearRenderTargetView(mRenderTarget, clearValues);
}
- ASSERT(SUCCEEDED(result));
}
}
+
mWidth = width;
mHeight = height;
- mInternalFormat = format;
+ mDepth = 1;
+ mInternalFormat = internalFormat;
mSamples = supportedSamples;
- mActualFormat = d3d11_gl::ConvertTextureInternalFormat(requestedFormat);
+ mActualFormat = dxgiFormatInfo.internalFormat;
mSubresourceIndex = D3D11CalcSubresource(0, 0, 1);
}
RenderTarget11::~RenderTarget11()
{
- if (mTexture)
- {
- mTexture->Release();
- mTexture = NULL;
- }
-
- if (mRenderTarget)
- {
- mRenderTarget->Release();
- mRenderTarget = NULL;
- }
-
- if (mDepthStencil)
- {
- mDepthStencil->Release();
- mDepthStencil = NULL;
- }
-
- if (mShaderResource)
- {
- mShaderResource->Release();
- mShaderResource = NULL;
- }
+ SafeRelease(mTexture);
+ SafeRelease(mRenderTarget);
+ SafeRelease(mDepthStencil);
+ SafeRelease(mShaderResource);
}
RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target)
@@ -327,7 +418,12 @@ RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target)
return static_cast<rx::RenderTarget11*>(target);
}
-ID3D11Texture2D *RenderTarget11::getTexture() const
+void RenderTarget11::invalidate(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ // Currently a no-op
+}
+
+ID3D11Resource *RenderTarget11::getTexture() const
{
return mTexture;
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h
index 97827f2639..82182957af 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h
@@ -20,14 +20,17 @@ class Renderer11;
class RenderTarget11 : public RenderTarget
{
public:
- RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height);
- RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height);
- RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth);
+ // RenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them
+ RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth);
+ RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth);
+ RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples);
virtual ~RenderTarget11();
static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget);
- ID3D11Texture2D *getTexture() const;
+ virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height);
+
+ ID3D11Resource *getTexture() const;
ID3D11RenderTargetView *getRenderTargetView() const;
ID3D11DepthStencilView *getDepthStencilView() const;
ID3D11ShaderResourceView *getShaderResourceView() const;
@@ -38,7 +41,7 @@ class RenderTarget11 : public RenderTarget
DISALLOW_COPY_AND_ASSIGN(RenderTarget11);
unsigned int mSubresourceIndex;
- ID3D11Texture2D *mTexture;
+ ID3D11Resource *mTexture;
ID3D11RenderTargetView *mRenderTarget;
ID3D11DepthStencilView *mDepthStencil;
ID3D11ShaderResourceView *mShaderResource;
@@ -48,4 +51,4 @@ class RenderTarget11 : public RenderTarget
}
-#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_ \ No newline at end of file
+#endif // LIBGLESV2_RENDERER_RENDERTARGET11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
new file mode 100644
index 0000000000..b29b2ef910
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
@@ -0,0 +1,3266 @@
+//
+// 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 "common/platform.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/renderer/d3d/ProgramD3D.h"
+#include "libGLESv2/renderer/d3d/ShaderD3D.h"
+#include "libGLESv2/renderer/d3d/TextureD3D.h"
+#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Image11.h"
+#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
+#include "libGLESv2/renderer/d3d/VertexDataManager.h"
+#include "libGLESv2/renderer/d3d/IndexDataManager.h"
+#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Query11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Fence11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Blit11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Clear11.h"
+#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/VertexArray11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
+
+#include "libEGL/Display.h"
+
+#include "common/utilities.h"
+
+#include <EGL/eglext.h>
+
+#include <sstream>
+
+// 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
+{
+static const DXGI_FORMAT RenderTargetFormats[] =
+ {
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM
+ };
+
+static const DXGI_FORMAT DepthStencilFormats[] =
+ {
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D16_UNORM
+ };
+
+enum
+{
+ MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
+};
+
+Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay)
+ : Renderer(display),
+ mDc(hDc),
+ mRequestedDisplay(requestedDisplay)
+{
+ mVertexDataManager = NULL;
+ mIndexDataManager = NULL;
+
+ mLineLoopIB = NULL;
+ mTriangleFanIB = NULL;
+
+ mBlit = NULL;
+ mPixelTransfer = NULL;
+
+ mClear = NULL;
+
+ mSyncQuery = NULL;
+
+ mD3d11Module = NULL;
+ mDxgiModule = NULL;
+
+ mDeviceLost = false;
+
+ mDevice = NULL;
+ mDeviceContext = NULL;
+ mDxgiAdapter = NULL;
+ mDxgiFactory = NULL;
+
+ mDriverConstantBufferVS = NULL;
+ mDriverConstantBufferPS = NULL;
+
+ mAppliedVertexShader = NULL;
+ mAppliedGeometryShader = NULL;
+ mCurPointGeometryShader = NULL;
+ mAppliedPixelShader = NULL;
+}
+
+Renderer11::~Renderer11()
+{
+ release();
+}
+
+Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer));
+ return static_cast<rx::Renderer11*>(renderer);
+}
+
+#ifndef __d3d11_1_h__
+#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
+#endif
+
+EGLint Renderer11::initialize()
+{
+ if (!mCompiler.initialize())
+ {
+ return EGL_NOT_INITIALIZED;
+ }
+
+#if !defined(ANGLE_PLATFORM_WINRT)
+ mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
+ mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+
+ if (mD3d11Module == NULL || mDxgiModule == NULL)
+ {
+ ERR("Could not load D3D11 or DXGI library - aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ // create the D3D11 device
+ ASSERT(mDevice == NULL);
+ PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
+
+ if (D3D11CreateDevice == NULL)
+ {
+ ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+#endif
+
+ D3D_FEATURE_LEVEL featureLevels[] =
+ {
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+#if !defined(ANGLE_ENABLE_D3D9)
+ D3D_FEATURE_LEVEL_9_3,
+ D3D_FEATURE_LEVEL_9_2,
+ D3D_FEATURE_LEVEL_9_1,
+#endif
+ };
+
+ D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE;
+ if (mRequestedDisplay == EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE)
+ {
+ driverType = D3D_DRIVER_TYPE_WARP;
+ }
+
+ HRESULT result = S_OK;
+
+#ifdef _DEBUG
+ result = D3D11CreateDevice(NULL,
+ driverType,
+ NULL,
+ D3D11_CREATE_DEVICE_DEBUG,
+ featureLevels,
+ ArraySize(featureLevels),
+ D3D11_SDK_VERSION,
+ &mDevice,
+ &mFeatureLevel,
+ &mDeviceContext);
+
+ if (!mDevice || FAILED(result))
+ {
+ ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
+ }
+
+ if (!mDevice || FAILED(result))
+#endif
+ {
+ result = D3D11CreateDevice(NULL,
+ driverType,
+ NULL,
+ 0,
+ featureLevels,
+ ArraySize(featureLevels),
+ D3D11_SDK_VERSION,
+ &mDevice,
+ &mFeatureLevel,
+ &mDeviceContext);
+
+ if (!mDevice || FAILED(result))
+ {
+ ERR("Could not create D3D11 device - aborting!\n");
+ return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer
+ }
+ }
+
+#if !ANGLE_SKIP_DXGI_1_2_CHECK && !defined(ANGLE_PLATFORM_WINRT)
+ // 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(mDc);
+ 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))
+ {
+ ERR("DXGI 1.2 required to present to HWNDs owned by another process.\n");
+ return EGL_NOT_INITIALIZED;
+ }
+ SafeRelease(dxgiDevice2);
+ }
+#endif
+
+#if !defined(ANGLE_PLATFORM_WINRT)
+ IDXGIDevice *dxgiDevice = NULL;
+#else
+ IDXGIDevice1 *dxgiDevice = NULL;
+#endif
+ result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice));
+
+ if (FAILED(result))
+ {
+ ERR("Could not query DXGI device - aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter);
+
+ if (FAILED(result))
+ {
+ ERR("Could not retrieve DXGI adapter - aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ SafeRelease(dxgiDevice);
+
+ mDxgiAdapter->GetDesc(&mAdapterDescription);
+ memset(mDescription, 0, sizeof(mDescription));
+ wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
+
+ result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory);
+
+ if (!mDxgiFactory || FAILED(result))
+ {
+ ERR("Could not create DXGI factory - aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
+#if !defined(__MINGW32__) && defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
+ 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 = {0};
+ filter.DenyList.NumIDs = ArraySize(hideMessages);
+ filter.DenyList.pIDList = hideMessages;
+
+ infoQueue->AddStorageFilterEntries(&filter);
+ SafeRelease(infoQueue);
+ }
+#endif
+
+#if !defined(ANGLE_PLATFORM_WINRT)
+ static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
+ if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
+ {
+ ID3D10Multithread *multithread;
+ result = mDevice->QueryInterface(IID_PPV_ARGS(&multithread));
+ ASSERT(SUCCEEDED(result));
+ result = multithread->SetMultithreadProtected(true);
+ ASSERT(SUCCEEDED(result));
+ multithread->Release();
+ }
+#endif
+
+ initializeDevice();
+
+ return 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()
+{
+ mStateCache.initialize(mDevice);
+ mInputLayoutCache.initialize(mDevice, mDeviceContext);
+
+ ASSERT(!mVertexDataManager && !mIndexDataManager);
+ mVertexDataManager = new VertexDataManager(this);
+ mIndexDataManager = new IndexDataManager(this);
+
+ ASSERT(!mBlit);
+ mBlit = new Blit11(this);
+
+ ASSERT(!mClear);
+ mClear = new Clear11(this);
+
+ ASSERT(!mPixelTransfer);
+ mPixelTransfer = new PixelTransfer11(this);
+
+ const gl::Caps &rendererCaps = getRendererCaps();
+
+ mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
+ mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
+
+ mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
+ mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
+
+ mCurVertexSRVs.resize(rendererCaps.maxVertexTextureImageUnits);
+ mCurPixelSRVs.resize(rendererCaps.maxTextureImageUnits);
+
+ markAllStateDirty();
+}
+
+int Renderer11::generateConfigs(ConfigDesc **configDescList)
+{
+ unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
+ unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
+ (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
+ int numConfigs = 0;
+
+ for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
+ {
+ const d3d11::DXGIFormat &renderTargetFormatInfo = d3d11::GetDXGIFormatInfo(RenderTargetFormats[formatIndex]);
+ const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat);
+ if (renderTargetFormatCaps.renderable)
+ {
+ for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
+ {
+ const d3d11::DXGIFormat &depthStencilFormatInfo = d3d11::GetDXGIFormatInfo(DepthStencilFormats[depthStencilIndex]);
+ const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat);
+ if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == DXGI_FORMAT_UNKNOWN)
+ {
+ ConfigDesc newConfig;
+ newConfig.renderTargetFormat = renderTargetFormatInfo.internalFormat;
+ newConfig.depthStencilFormat = depthStencilFormatInfo.internalFormat;
+ newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
+ newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast
+ newConfig.es3Capable = true;
+
+ (*configDescList)[numConfigs++] = newConfig;
+ }
+ }
+ }
+ }
+
+ return numConfigs;
+}
+
+void Renderer11::deleteConfigs(ConfigDesc *configDescList)
+{
+ delete [] (configDescList);
+}
+
+void Renderer11::sync(bool block)
+{
+ if (block)
+ {
+ HRESULT result;
+
+ if (!mSyncQuery)
+ {
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = D3D11_QUERY_EVENT;
+ queryDesc.MiscFlags = 0;
+
+ result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
+ ASSERT(SUCCEEDED(result));
+ }
+
+ mDeviceContext->End(mSyncQuery);
+ mDeviceContext->Flush();
+
+ do
+ {
+ result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
+
+ // Keep polling, but allow other threads to do something useful first
+ Sleep(0);
+
+ if (testDeviceLost(true))
+ {
+ return;
+ }
+ }
+ while (result == S_FALSE);
+ }
+ else
+ {
+ mDeviceContext->Flush();
+ }
+}
+
+SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+{
+ return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat);
+}
+
+gl::Error Renderer11::generateSwizzle(gl::Texture *texture)
+{
+ if (texture)
+ {
+ TextureStorage *texStorage = texture->getNativeTexture();
+ if (texStorage)
+ {
+ TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage);
+
+ gl::Error error = storage11->generateSwizzles(texture->getSamplerState().swizzleRed,
+ texture->getSamplerState().swizzleGreen,
+ texture->getSamplerState().swizzleBlue,
+ texture->getSamplerState().swizzleAlpha);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
+{
+ if (type == gl::SAMPLER_PIXEL)
+ {
+ ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits);
+
+ if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+ {
+ ID3D11SamplerState *dxSamplerState = NULL;
+ gl::Error error = mStateCache.getSamplerState(samplerState, &dxSamplerState);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(dxSamplerState != NULL);
+ mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
+
+ mCurPixelSamplerStates[index] = samplerState;
+ }
+
+ mForceSetPixelSamplerStates[index] = false;
+ }
+ else if (type == gl::SAMPLER_VERTEX)
+ {
+ ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits);
+
+ if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+ {
+ ID3D11SamplerState *dxSamplerState = NULL;
+ gl::Error error = mStateCache.getSamplerState(samplerState, &dxSamplerState);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(dxSamplerState != NULL);
+ mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
+
+ mCurVertexSamplerStates[index] = samplerState;
+ }
+
+ mForceSetVertexSamplerStates[index] = false;
+ }
+ else UNREACHABLE();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
+{
+ ID3D11ShaderResourceView *textureSRV = NULL;
+ bool forceSetTexture = false;
+
+ if (texture)
+ {
+ TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation());
+ TextureStorage *texStorage = textureImpl->getNativeTexture();
+ ASSERT(texStorage != NULL);
+
+ TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage);
+ gl::SamplerState samplerState;
+ texture->getSamplerStateWithNativeOffset(&samplerState);
+ textureSRV = storage11->getSRV(samplerState);
+
+ // 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);
+
+ forceSetTexture = textureImpl->hasDirtyImages();
+ textureImpl->resetDirty();
+ }
+
+ if (type == gl::SAMPLER_PIXEL)
+ {
+ ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits);
+
+ if (forceSetTexture || mCurPixelSRVs[index] != textureSRV)
+ {
+ mDeviceContext->PSSetShaderResources(index, 1, &textureSRV);
+ }
+
+ mCurPixelSRVs[index] = textureSRV;
+ }
+ else if (type == gl::SAMPLER_VERTEX)
+ {
+ ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits);
+
+ if (forceSetTexture || mCurVertexSRVs[index] != textureSRV)
+ {
+ mDeviceContext->VSSetShaderResources(index, 1, &textureSRV);
+ }
+
+ mCurVertexSRVs[index] = textureSRV;
+ }
+ else UNREACHABLE();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[])
+{
+ for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++)
+ {
+ const gl::Buffer *uniformBuffer = vertexUniformBuffers[uniformBufferIndex];
+ if (uniformBuffer)
+ {
+ Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation());
+ ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM);
+
+ if (!constantBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY);
+ }
+
+ if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial())
+ {
+ mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex,
+ 1, &constantBuffer);
+ mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial();
+ }
+ }
+ }
+
+ for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++)
+ {
+ const gl::Buffer *uniformBuffer = fragmentUniformBuffers[uniformBufferIndex];
+ if (uniformBuffer)
+ {
+ Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation());
+ ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM);
+
+ if (!constantBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY);
+ }
+
+ if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial())
+ {
+ mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex,
+ 1, &constantBuffer);
+ mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial();
+ }
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
+{
+ if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
+ {
+ ID3D11RasterizerState *dxRasterState = NULL;
+ gl::Error error = mStateCache.getRasterizerState(rasterState, mScissorEnabled, &dxRasterState);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mDeviceContext->RSSetState(dxRasterState);
+
+ mCurRasterState = rasterState;
+ }
+
+ mForceSetRasterState = false;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
+ unsigned int sampleMask)
+{
+ if (mForceSetBlendState ||
+ memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 ||
+ memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0 ||
+ sampleMask != mCurSampleMask)
+ {
+ ID3D11BlendState *dxBlendState = NULL;
+ gl::Error error = mStateCache.getBlendState(framebuffer, blendState, &dxBlendState);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(dxBlendState != NULL);
+
+ 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;
+ }
+
+ mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
+
+ mCurBlendState = blendState;
+ mCurBlendColor = blendColor;
+ mCurSampleMask = sampleMask;
+ }
+
+ mForceSetBlendState = false;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
+ int stencilBackRef, bool frontFaceCCW)
+{
+ if (mForceSetDepthStencilState ||
+ memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
+ stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
+ {
+ ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask);
+ ASSERT(stencilRef == stencilBackRef);
+ ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask);
+
+ ID3D11DepthStencilState *dxDepthStencilState = NULL;
+ gl::Error error = mStateCache.getDepthStencilState(depthStencilState, &dxDepthStencilState);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ 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
+ META_ASSERT(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF);
+ META_ASSERT(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF);
+ UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu);
+
+ mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
+
+ mCurDepthStencilState = depthStencilState;
+ mCurStencilRef = stencilRef;
+ mCurStencilBackRef = stencilBackRef;
+ }
+
+ mForceSetDepthStencilState = false;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
+{
+ if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
+ enabled != mScissorEnabled)
+ {
+ if (enabled)
+ {
+ D3D11_RECT rect;
+ rect.left = std::max(0, scissor.x);
+ rect.top = std::max(0, scissor.y);
+ rect.right = scissor.x + std::max(0, scissor.width);
+ rect.bottom = scissor.y + std::max(0, scissor.height);
+
+ mDeviceContext->RSSetScissorRects(1, &rect);
+ }
+
+ if (enabled != mScissorEnabled)
+ {
+ mForceSetRasterState = true;
+ }
+
+ mCurScissor = scissor;
+ mScissorEnabled = enabled;
+ }
+
+ mForceSetScissor = false;
+}
+
+void Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
+ bool ignoreViewport)
+{
+ gl::Rectangle actualViewport = viewport;
+ float actualZNear = gl::clamp01(zNear);
+ float actualZFar = gl::clamp01(zFar);
+ if (ignoreViewport)
+ {
+ actualViewport.x = 0;
+ actualViewport.y = 0;
+ actualViewport.width = mRenderTargetDesc.width;
+ actualViewport.height = mRenderTargetDesc.height;
+ actualZNear = 0.0f;
+ actualZFar = 1.0f;
+ }
+
+ const gl::Caps& caps = getRendererCaps();
+
+ // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds
+ D3D11_VIEWPORT dxViewport;
+ dxViewport.TopLeftX = gl::clamp(actualViewport.x, -static_cast<int>(caps.maxViewportWidth), static_cast<int>(caps.maxViewportWidth));
+ dxViewport.TopLeftY = gl::clamp(actualViewport.y, -static_cast<int>(caps.maxViewportHeight), static_cast<int>(caps.maxViewportHeight));
+ dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(caps.maxViewportWidth - dxViewport.TopLeftX));
+ dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(caps.maxViewportHeight - dxViewport.TopLeftY));
+ dxViewport.MinDepth = actualZNear;
+ dxViewport.MaxDepth = actualZFar;
+
+ bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
+ actualZNear != mCurNear || actualZFar != mCurFar;
+
+ if (viewportChanged)
+ {
+ mDeviceContext->RSSetViewports(1, &dxViewport);
+
+ mCurViewport = actualViewport;
+ mCurNear = actualZNear;
+ mCurFar = actualZFar;
+
+ mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f;
+ mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f;
+ mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
+ mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
+
+ 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;
+ }
+
+ mForceSetViewport = false;
+}
+
+bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
+{
+ 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 (primitiveTopology != mCurrentPrimitiveTopology)
+ {
+ mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
+ mCurrentPrimitiveTopology = primitiveTopology;
+ }
+
+ return count >= minCount;
+}
+
+gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
+{
+ // Get the color render buffer and serial
+ // Also extract the render target dimensions and view
+ unsigned int renderTargetWidth = 0;
+ unsigned int renderTargetHeight = 0;
+ GLenum renderTargetFormat = 0;
+ unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0};
+ ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
+ bool missingColorRenderTarget = true;
+
+ const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender();
+
+ for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
+ {
+ gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
+
+ if (colorbuffer)
+ {
+ // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order)
+
+ // 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 (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ renderTargetSerials[colorAttachment] = GetAttachmentSerial(colorbuffer);
+
+ // Extract the render target dimensions and view
+ RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
+ if (!renderTarget)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal render target pointer unexpectedly null.");
+ }
+
+ framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
+ if (!framebufferRTVs[colorAttachment])
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
+ }
+
+ if (missingColorRenderTarget)
+ {
+ renderTargetWidth = colorbuffer->getWidth();
+ renderTargetHeight = colorbuffer->getHeight();
+ renderTargetFormat = colorbuffer->getActualFormat();
+ missingColorRenderTarget = false;
+ }
+
+ // TODO: Detect if this color buffer is already bound as a texture and unbind it first to prevent
+ // D3D11 warnings.
+ }
+ }
+
+ // Get the depth stencil render buffter and serials
+ gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer();
+ unsigned int depthbufferSerial = 0;
+ unsigned int stencilbufferSerial = 0;
+ if (depthStencil)
+ {
+ depthbufferSerial = GetAttachmentSerial(depthStencil);
+ }
+ else if (framebuffer->getStencilbuffer())
+ {
+ depthStencil = framebuffer->getStencilbuffer();
+ stencilbufferSerial = GetAttachmentSerial(depthStencil);
+ }
+
+ ID3D11DepthStencilView* framebufferDSV = NULL;
+ if (depthStencil)
+ {
+ RenderTarget11 *depthStencilRenderTarget = d3d11::GetAttachmentRenderTarget(depthStencil);
+ if (!depthStencilRenderTarget)
+ {
+ SafeRelease(framebufferRTVs);
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal render target pointer unexpectedly null.");
+ }
+
+ framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
+ if (!framebufferDSV)
+ {
+ SafeRelease(framebufferRTVs);
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null.");
+ }
+
+ // If there is no render buffer, the width, height and format values come from
+ // the depth stencil
+ if (missingColorRenderTarget)
+ {
+ renderTargetWidth = depthStencil->getWidth();
+ renderTargetHeight = depthStencil->getHeight();
+ renderTargetFormat = depthStencil->getActualFormat();
+ }
+ }
+
+ // Apply the render target and depth stencil
+ if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
+ memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 ||
+ depthbufferSerial != mAppliedDepthbufferSerial ||
+ stencilbufferSerial != mAppliedStencilbufferSerial)
+ {
+ mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV);
+
+ mRenderTargetDesc.width = renderTargetWidth;
+ mRenderTargetDesc.height = renderTargetHeight;
+ mRenderTargetDesc.format = renderTargetFormat;
+ mForceSetViewport = true;
+ mForceSetScissor = true;
+ mForceSetBlendState = true;
+
+ if (!mDepthStencilInitialized)
+ {
+ mForceSetRasterState = true;
+ }
+
+ for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
+ {
+ mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex];
+ }
+ mAppliedDepthbufferSerial = depthbufferSerial;
+ mAppliedStencilbufferSerial = stencilbufferSerial;
+ mRenderTargetDescInitialized = true;
+ mDepthStencilInitialized = true;
+ }
+
+ invalidateFramebufferSwizzles(framebuffer);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[],
+ GLint first, GLsizei count, GLsizei instances)
+{
+ TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
+ gl::Error error = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return mInputLayoutCache.applyVertexBuffers(attributes, programBinary);
+}
+
+gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
+{
+ gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ID3D11Buffer *buffer = NULL;
+ DXGI_FORMAT bufferFormat = (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;
+
+ if (indexInfo->storage)
+ {
+ Buffer11 *storage = Buffer11::makeBuffer11(indexInfo->storage);
+ buffer = storage->getBuffer(BUFFER_USAGE_INDEX);
+ }
+ else
+ {
+ IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
+ buffer = indexBuffer->getBuffer();
+ }
+
+ if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat || indexInfo->startOffset != mAppliedIBOffset)
+ {
+ mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset);
+
+ mAppliedIB = buffer;
+ mAppliedIBFormat = bufferFormat;
+ mAppliedIBOffset = indexInfo->startOffset;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[])
+{
+ ID3D11Buffer* d3dBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
+ UINT d3dOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
+ bool requiresUpdate = false;
+ for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
+ {
+ if (transformFeedbackBuffers[i])
+ {
+ Buffer11 *storage = Buffer11::makeBuffer11(transformFeedbackBuffers[i]->getImplementation());
+ ID3D11Buffer *buffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
+
+ d3dBuffers[i] = buffer;
+ d3dOffsets[i] = (mAppliedTFBuffers[i] != buffer) ? static_cast<UINT>(offsets[i]) : -1;
+ }
+ else
+ {
+ d3dBuffers[i] = NULL;
+ d3dOffsets[i] = 0;
+ }
+
+ if (d3dBuffers[i] != mAppliedTFBuffers[i] || offsets[i] != mAppliedTFOffsets[i])
+ {
+ requiresUpdate = true;
+ }
+ }
+
+ if (requiresUpdate)
+ {
+ mDeviceContext->SOSetTargets(ArraySize(d3dBuffers), d3dBuffers, d3dOffsets);
+ for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
+ {
+ mAppliedTFBuffers[i] = d3dBuffers[i];
+ mAppliedTFOffsets[i] = offsets[i];
+ }
+ }
+}
+
+gl::Error Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive)
+{
+ if (mode == GL_POINTS && transformFeedbackActive)
+ {
+ // Since point sprites are generated with a geometry shader, too many vertices will
+ // be written if transform feedback is active. To work around this, draw only the points
+ // with the stream out shader and no pixel shader to feed the stream out buffers and then
+ // draw again with the point sprite geometry shader to rasterize the point sprites.
+
+ mDeviceContext->PSSetShader(NULL, NULL, 0);
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ }
+ else
+ {
+ mDeviceContext->Draw(count, 0);
+ }
+
+ mDeviceContext->GSSetShader(mCurPointGeometryShader, NULL, 0);
+ mDeviceContext->PSSetShader(mAppliedPixelShader, NULL, 0);
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ }
+ else
+ {
+ mDeviceContext->Draw(count, 0);
+ }
+
+ mDeviceContext->GSSetShader(mAppliedGeometryShader, NULL, 0);
+
+ return gl::Error(GL_NO_ERROR);
+ }
+ else if (mode == GL_LINE_LOOP)
+ {
+ return drawLineLoop(count, GL_NONE, NULL, 0, NULL);
+ }
+ else if (mode == GL_TRIANGLE_FAN)
+ {
+ return drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances);
+ }
+ else if (instances > 0)
+ {
+ mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ mDeviceContext->Draw(count, 0);
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
+ gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances)
+{
+ int minIndex = static_cast<int>(indexInfo.indexRange.start);
+
+ if (mode == GL_LINE_LOOP)
+ {
+ return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer);
+ }
+ else if (mode == GL_TRIANGLE_FAN)
+ {
+ return drawTriangleFan(count, type, indices, minIndex, elementArrayBuffer, instances);
+ }
+ else if (instances > 0)
+ {
+ mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0);
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ mDeviceContext->DrawIndexed(count, 0, -minIndex);
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+template<typename T>
+static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data)
+{
+ 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();
+ }
+}
+
+template<typename T>
+static void fillTriangleFanIndices(GLenum type, unsigned int numTris, const GLvoid *indices, T *data)
+{
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = 0;
+ data[i*3 + 1] = i + 1;
+ data[i*3 + 2] = i + 2;
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
+ }
+ break;
+ default: UNREACHABLE();
+ }
+}
+
+gl::Error Renderer11::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)
+ {
+ gl::Buffer *indexBuffer = elementArrayBuffer;
+ BufferImpl *storage = indexBuffer->getImplementation();
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+ }
+
+ // TODO: some level 9 hardware supports 32-bit indices; test and store support instead
+ const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+
+ if (!mLineLoopIB)
+ {
+ mLineLoopIB = new StreamingIndexBufferInterface(this);
+ gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType);
+ if (error.isError())
+ {
+ SafeDelete(mLineLoopIB);
+ return error;
+ }
+ }
+
+ // Checked by Renderer11::applyPrimitiveType
+ ASSERT(count >= 0);
+
+ int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
+ if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / indexTypeSize))
+ {
+ 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;
+ error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (indexType == GL_UNSIGNED_SHORT)
+ fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned short*>(mappedMemory));
+ else
+ fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned int*>(mappedMemory));
+ unsigned int indexBufferOffset = offset;
+
+ error = mLineLoopIB->unmapBuffer();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer());
+ ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer();
+ DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
+
+ if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset)
+ {
+ mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset);
+ mAppliedIB = d3dIndexBuffer;
+ mAppliedIBFormat = indexFormat;
+ mAppliedIBOffset = indexBufferOffset;
+ }
+
+ mDeviceContext->DrawIndexed(count + 1, 0, -minIndex);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances)
+{
+ // Get the raw indices for an indexed draw
+ if (type != GL_NONE && elementArrayBuffer)
+ {
+ gl::Buffer *indexBuffer = elementArrayBuffer;
+ BufferImpl *storage = indexBuffer->getImplementation();
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+ }
+
+ const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+
+ if (!mTriangleFanIB)
+ {
+ mTriangleFanIB = new StreamingIndexBufferInterface(this);
+ gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType);
+ if (error.isError())
+ {
+ SafeDelete(mTriangleFanIB);
+ return error;
+ }
+ }
+
+ // Checked by Renderer11::applyPrimitiveType
+ ASSERT(count >= 3);
+
+ const unsigned int numTris = count - 2;
+
+ int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
+ if (numTris > (std::numeric_limits<unsigned int>::max() / (indexTypeSize * 3)))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
+ }
+
+ const unsigned int spaceNeeded = (numTris * 3) * indexTypeSize;
+ gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ void* mappedMemory = NULL;
+ unsigned int offset;
+ error = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (indexType == GL_UNSIGNED_SHORT)
+ fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned short*>(mappedMemory));
+ else
+ fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned int*>(mappedMemory));
+
+ unsigned int indexBufferOffset = offset;
+
+ error = mTriangleFanIB->unmapBuffer();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer());
+ ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer();
+ DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
+
+ if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset)
+ {
+ mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset);
+ mAppliedIB = d3dIndexBuffer;
+ mAppliedIBFormat = indexFormat;
+ mAppliedIBOffset = indexBufferOffset;
+ }
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0);
+ }
+ else
+ {
+ mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
+ bool rasterizerDiscard, bool transformFeedbackActive)
+{
+ ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout);
+ ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer);
+ ShaderExecutable *geometryExe = programBinary->getGeometryExecutable();
+
+ ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL);
+
+ ID3D11PixelShader *pixelShader = NULL;
+ // Skip pixel shader if we're doing rasterizer discard.
+ if (!rasterizerDiscard)
+ {
+ pixelShader = (pixelExe ? ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader() : NULL);
+ }
+
+ ID3D11GeometryShader *geometryShader = NULL;
+ if (transformFeedbackActive)
+ {
+ geometryShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getStreamOutShader() : NULL);
+ }
+ else if (mCurRasterState.pointDrawMode)
+ {
+ geometryShader = (geometryExe ? ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader() : NULL);
+ }
+
+ bool dirtyUniforms = false;
+
+ if (vertexShader != mAppliedVertexShader)
+ {
+ mDeviceContext->VSSetShader(vertexShader, NULL, 0);
+ mAppliedVertexShader = vertexShader;
+ dirtyUniforms = true;
+ }
+
+ if (geometryShader != mAppliedGeometryShader)
+ {
+ mDeviceContext->GSSetShader(geometryShader, NULL, 0);
+ mAppliedGeometryShader = geometryShader;
+ dirtyUniforms = true;
+ }
+
+ if (geometryExe && mCurRasterState.pointDrawMode)
+ {
+ mCurPointGeometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader();
+ }
+ else
+ {
+ mCurPointGeometryShader = NULL;
+ }
+
+ if (pixelShader != mAppliedPixelShader)
+ {
+ mDeviceContext->PSSetShader(pixelShader, NULL, 0);
+ mAppliedPixelShader = pixelShader;
+ dirtyUniforms = true;
+ }
+
+ if (dirtyUniforms)
+ {
+ programBinary->dirtyAllUniforms();
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::applyUniforms(const gl::ProgramBinary &programBinary)
+{
+ const std::vector<gl::LinkedUniform*> &uniformArray = programBinary.getUniforms();
+
+ unsigned int totalRegisterCountVS = 0;
+ unsigned int totalRegisterCountPS = 0;
+
+ bool vertexUniformsDirty = false;
+ bool pixelUniformsDirty = false;
+
+ for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++)
+ {
+ const gl::LinkedUniform &uniform = *uniformArray[uniformIndex];
+
+ 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 ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary.getImplementation());
+ const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getVertexUniformStorage());
+ const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&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);
+ UNUSED_ASSERTION_VARIABLE(result);
+ 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);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(SUCCEEDED(result));
+ mapPS = (float(*)[4])map.pData;
+ }
+
+ for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++)
+ {
+ gl::LinkedUniform *uniform = uniformArray[uniformIndex];
+
+ if (!uniform->isSampler())
+ {
+ 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(0, 1, &vertexConstantBuffer);
+ mCurrentVertexConstantBuffer = vertexConstantBuffer;
+ }
+
+ if (mCurrentPixelConstantBuffer != pixelConstantBuffer)
+ {
+ mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer);
+ mCurrentPixelConstantBuffer = pixelConstantBuffer;
+ }
+
+ // Driver uniforms
+ if (!mDriverConstantBufferVS)
+ {
+ D3D11_BUFFER_DESC constantBufferDescription = {0};
+ constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants);
+ constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
+ constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ constantBufferDescription.CPUAccessFlags = 0;
+ constantBufferDescription.MiscFlags = 0;
+ constantBufferDescription.StructureByteStride = 0;
+
+ HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(SUCCEEDED(result));
+
+ mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS);
+ }
+
+ if (!mDriverConstantBufferPS)
+ {
+ D3D11_BUFFER_DESC constantBufferDescription = {0};
+ constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants);
+ constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
+ constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ constantBufferDescription.CPUAccessFlags = 0;
+ constantBufferDescription.MiscFlags = 0;
+ constantBufferDescription.StructureByteStride = 0;
+
+ HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(SUCCEEDED(result));
+
+ mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS);
+ }
+
+ if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0)
+ {
+ mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0);
+ memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants));
+ }
+
+ if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0)
+ {
+ mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0);
+ memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants));
+ }
+
+ // needed for the point sprite geometry shader
+ if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
+ {
+ mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
+ mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
+{
+ gl::Error error = mClear->clearFramebuffer(clearParams, frameBuffer);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ invalidateFramebufferSwizzles(frameBuffer);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Renderer11::markAllStateDirty()
+{
+ for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
+ {
+ mAppliedRenderTargetSerials[rtIndex] = 0;
+ }
+ mAppliedDepthbufferSerial = 0;
+ mAppliedStencilbufferSerial = 0;
+ mDepthStencilInitialized = false;
+ mRenderTargetDescInitialized = false;
+
+ ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexSRVs.size());
+ for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId)
+ {
+ mForceSetVertexSamplerStates[vsamplerId] = true;
+ mCurVertexSRVs[vsamplerId] = NULL;
+ }
+
+ ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelSRVs.size());
+ for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId)
+ {
+ mForceSetPixelSamplerStates[fsamplerId] = true;
+ mCurPixelSRVs[fsamplerId] = NULL;
+ }
+
+ mForceSetBlendState = true;
+ mForceSetRasterState = true;
+ mForceSetDepthStencilState = true;
+ mForceSetScissor = true;
+ mForceSetViewport = true;
+
+ mAppliedIB = NULL;
+ mAppliedIBFormat = DXGI_FORMAT_UNKNOWN;
+ mAppliedIBOffset = 0;
+
+ mAppliedVertexShader = NULL;
+ mAppliedGeometryShader = NULL;
+ mCurPointGeometryShader = NULL;
+ mAppliedPixelShader = NULL;
+
+ for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
+ {
+ mAppliedTFBuffers[i] = NULL;
+ mAppliedTFOffsets[i] = 0;
+ }
+
+ memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants));
+ memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants));
+
+ mInputLayoutCache.markDirty();
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++)
+ {
+ mCurrentConstantBufferVS[i] = -1;
+ mCurrentConstantBufferPS[i] = -1;
+ }
+
+ mCurrentVertexConstantBuffer = NULL;
+ mCurrentPixelConstantBuffer = NULL;
+ mCurrentGeometryConstantBuffer = NULL;
+
+ mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+}
+
+void Renderer11::releaseDeviceResources()
+{
+ mStateCache.clear();
+ mInputLayoutCache.clear();
+
+ SafeDelete(mVertexDataManager);
+ SafeDelete(mIndexDataManager);
+ SafeDelete(mLineLoopIB);
+ SafeDelete(mTriangleFanIB);
+ SafeDelete(mBlit);
+ SafeDelete(mClear);
+ SafeDelete(mPixelTransfer);
+
+ SafeRelease(mDriverConstantBufferVS);
+ SafeRelease(mDriverConstantBufferPS);
+ SafeRelease(mSyncQuery);
+}
+
+void Renderer11::notifyDeviceLost()
+{
+ mDeviceLost = true;
+ mDisplay->notifyDeviceLost();
+}
+
+bool Renderer11::isDeviceLost()
+{
+ return mDeviceLost;
+}
+
+// set notify to true to broadcast a message to all contexts of the device loss
+bool Renderer11::testDeviceLost(bool notify)
+{
+ bool isLost = false;
+
+ // GetRemovedReason is used to test if the device is removed
+ HRESULT result = mDevice->GetDeviceRemovedReason();
+ isLost = d3d11::isDeviceLostError(result);
+
+ if (isLost)
+ {
+ // Log error if this is a new device lost event
+ if (mDeviceLost == false)
+ {
+ ERR("The D3D11 device was removed: 0x%08X", result);
+ }
+
+ // ensure we note the device loss --
+ // we'll probably get this done again by notifyDeviceLost
+ // but best to remember it!
+ // Note that we don't want to clear the device loss status here
+ // -- this needs to be done by resetDevice
+ mDeviceLost = true;
+ if (notify)
+ {
+ notifyDeviceLost();
+ }
+ }
+
+ 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;
+ }
+
+ D3D_FEATURE_LEVEL featureLevels[] =
+ {
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+#if !defined(ANGLE_ENABLE_D3D9)
+ D3D_FEATURE_LEVEL_9_3,
+ D3D_FEATURE_LEVEL_9_2,
+ D3D_FEATURE_LEVEL_9_1,
+#endif
+ };
+
+ ID3D11Device* dummyDevice;
+ D3D_FEATURE_LEVEL dummyFeatureLevel;
+ ID3D11DeviceContext* dummyContext;
+
+ HRESULT result = D3D11CreateDevice(NULL,
+ D3D_DRIVER_TYPE_HARDWARE,
+ NULL,
+ #if defined(_DEBUG)
+ D3D11_CREATE_DEVICE_DEBUG,
+ #else
+ 0,
+ #endif
+ featureLevels,
+ ArraySize(featureLevels),
+ D3D11_SDK_VERSION,
+ &dummyDevice,
+ &dummyFeatureLevel,
+ &dummyContext);
+
+ if (!mDevice || FAILED(result))
+ {
+ return false;
+ }
+
+ SafeRelease(dummyContext);
+ SafeRelease(dummyDevice);
+
+ return true;
+}
+
+void Renderer11::release()
+{
+ releaseShaderCompiler();
+ releaseDeviceResources();
+
+ SafeRelease(mDxgiFactory);
+ SafeRelease(mDxgiAdapter);
+
+ if (mDeviceContext)
+ {
+ mDeviceContext->ClearState();
+ mDeviceContext->Flush();
+ SafeRelease(mDeviceContext);
+ }
+
+ SafeRelease(mDevice);
+
+ if (mD3d11Module)
+ {
+ FreeLibrary(mD3d11Module);
+ mD3d11Module = NULL;
+ }
+
+ if (mDxgiModule)
+ {
+ FreeLibrary(mDxgiModule);
+ mDxgiModule = NULL;
+ }
+
+ mCompiler.release();
+}
+
+bool Renderer11::resetDevice()
+{
+ // recreate everything
+ release();
+ EGLint result = initialize();
+
+ if (result != EGL_SUCCESS)
+ {
+ ERR("Could not reinitialize D3D11 device: %08X", result);
+ return false;
+ }
+
+ mDeviceLost = false;
+
+ return true;
+}
+
+DWORD Renderer11::getAdapterVendor() const
+{
+ return mAdapterDescription.VendorId;
+}
+
+std::string Renderer11::getRendererDescription() const
+{
+ std::ostringstream rendererString;
+
+ rendererString << mDescription;
+ rendererString << " Direct3D11";
+
+ rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel();
+ rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel();
+
+ return rendererString.str();
+}
+
+GUID Renderer11::getAdapterIdentifier() const
+{
+ // Use the adapter LUID as our adapter ID
+ // This number is local to a machine is only guaranteed to be unique between restarts
+ META_ASSERT(sizeof(LUID) <= sizeof(GUID));
+ GUID adapterId = {0};
+ memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID));
+ return adapterId;
+}
+
+unsigned int Renderer11::getReservedVertexUniformVectors() const
+{
+ return 0; // Driver uniforms are stored in a separate constant buffer
+}
+
+unsigned int Renderer11::getReservedFragmentUniformVectors() const
+{
+ return 0; // Driver uniforms are stored in a separate constant buffer
+}
+
+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;
+}
+
+bool Renderer11::getShareHandleSupport() const
+{
+ // We only currently support share handles with BGRA surfaces, because
+ // chrome needs BGRA. Once chrome fixes this, we should always support them.
+ // PIX doesn't seem to support using share handles, so disable them.
+ return getRendererExtensions().textureFormatBGRA8888 && !gl::perfActive();
+}
+
+bool Renderer11::getPostSubBufferSupport() const
+{
+ // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2.
+ return false;
+}
+
+int Renderer11::getMajorShaderModel() const
+{
+ switch (mFeatureLevel)
+ {
+ 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:
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MAJOR_VERSION; // 4
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+int Renderer11::getMinorShaderModel() const
+{
+ switch (mFeatureLevel)
+ {
+ 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:
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+int Renderer11::getMinSwapInterval() const
+{
+ return 0;
+}
+
+int Renderer11::getMaxSwapInterval() const
+{
+ return 4;
+}
+
+bool Renderer11::copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source)
+{
+ if (source && dest)
+ {
+ TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source);
+ TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest);
+
+ mDeviceContext->CopyResource(dest11->getResource(), source11->getResource());
+
+ dest11->invalidateSwizzleCache();
+
+ return true;
+ }
+
+ return false;
+}
+
+bool Renderer11::copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source)
+{
+ if (source && dest)
+ {
+ TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source);
+ TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest);
+
+ mDeviceContext->CopyResource(dest11->getResource(), source11->getResource());
+
+ dest11->invalidateSwizzleCache();
+
+ return true;
+ }
+
+ return false;
+}
+
+bool Renderer11::copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source)
+{
+ if (source && dest)
+ {
+ TextureStorage11_3D *source11 = TextureStorage11_3D::makeTextureStorage11_3D(source);
+ TextureStorage11_3D *dest11 = TextureStorage11_3D::makeTextureStorage11_3D(dest);
+
+ mDeviceContext->CopyResource(dest11->getResource(), source11->getResource());
+
+ dest11->invalidateSwizzleCache();
+
+ return true;
+ }
+
+ return false;
+}
+
+bool Renderer11::copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source)
+{
+ if (source && dest)
+ {
+ TextureStorage11_2DArray *source11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(source);
+ TextureStorage11_2DArray *dest11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(dest);
+
+ mDeviceContext->CopyResource(dest11->getResource(), source11->getResource());
+
+ dest11->invalidateSwizzleCache();
+
+ return true;
+ }
+
+ return false;
+}
+
+bool Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
+{
+ gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
+ if (!colorbuffer)
+ {
+ ERR("Failed to retrieve the color buffer from the frame buffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
+ if (!sourceRenderTarget)
+ {
+ ERR("Failed to retrieve the render target from the frame buffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
+ if (!source)
+ {
+ ERR("Failed to retrieve the render target view from the render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage);
+ if (!storage11)
+ {
+ ERR("Failed to retrieve the texture storage from the destination.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+ RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index));
+ if (!destRenderTarget)
+ {
+ ERR("Failed to retrieve the render target from the destination storage.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
+ if (!dest)
+ {
+ ERR("Failed to retrieve the render target view from the destination render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
+ gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
+
+ gl::Box destArea(xoffset, yoffset, 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
+ bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
+ destFormat, GL_NEAREST);
+
+ storage11->invalidateSwizzleCacheLevel(level);
+
+ return ret;
+}
+
+bool Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
+{
+ gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
+ if (!colorbuffer)
+ {
+ ERR("Failed to retrieve the color buffer from the frame buffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
+ if (!sourceRenderTarget)
+ {
+ ERR("Failed to retrieve the render target from the frame buffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
+ if (!source)
+ {
+ ERR("Failed to retrieve the render target view from the render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage);
+ if (!storage11)
+ {
+ ERR("Failed to retrieve the texture storage from the destination.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
+ RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index));
+ if (!destRenderTarget)
+ {
+ ERR("Failed to retrieve the render target from the destination storage.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
+ if (!dest)
+ {
+ ERR("Failed to retrieve the render target view from the destination render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
+ gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
+
+ gl::Box destArea(xoffset, yoffset, 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
+ bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
+ destFormat, GL_NEAREST);
+
+ storage11->invalidateSwizzleCacheLevel(level);
+
+ return ret;
+}
+
+bool Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+{
+ gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
+ if (!colorbuffer)
+ {
+ ERR("Failed to retrieve the color buffer from the frame buffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
+ if (!sourceRenderTarget)
+ {
+ ERR("Failed to retrieve the render target from the frame buffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
+ if (!source)
+ {
+ ERR("Failed to retrieve the render target view from the render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage);
+ if (!storage11)
+ {
+ ERR("Failed to retrieve the texture storage from the destination.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level, zOffset);
+ RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index));
+ if (!destRenderTarget)
+ {
+ ERR("Failed to retrieve the render target from the destination storage.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
+ if (!dest)
+ {
+ ERR("Failed to retrieve the render target view from the destination render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
+ gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
+
+ gl::Box destArea(xoffset, yoffset, 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
+ bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
+ destFormat, GL_NEAREST);
+
+ storage11->invalidateSwizzleCacheLevel(level);
+
+ return ret;
+}
+
+bool Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+{
+ gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
+ if (!colorbuffer)
+ {
+ ERR("Failed to retrieve the color buffer from the frame buffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
+ if (!sourceRenderTarget)
+ {
+ ERR("Failed to retrieve the render target from the frame buffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
+ if (!source)
+ {
+ ERR("Failed to retrieve the render target view from the render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage);
+ if (!storage11)
+ {
+ SafeRelease(source);
+ ERR("Failed to retrieve the texture storage from the destination.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zOffset);
+ RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index));
+ if (!destRenderTarget)
+ {
+ SafeRelease(source);
+ ERR("Failed to retrieve the render target from the destination storage.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
+ if (!dest)
+ {
+ ERR("Failed to retrieve the render target view from the destination render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
+ gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
+
+ gl::Box destArea(xoffset, yoffset, 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
+ bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
+ destFormat, GL_NEAREST);
+
+ storage11->invalidateSwizzleCacheLevel(level);
+
+ return ret;
+}
+
+void Renderer11::unapplyRenderTargets()
+{
+ setOneTimeRenderTarget(NULL);
+}
+
+void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView)
+{
+ ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
+
+ rtvArray[0] = renderTargetView;
+
+ mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, rtvArray, NULL);
+
+ // Do not preserve the serial for this one-time-use render target
+ for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
+ {
+ mAppliedRenderTargetSerials[rtIndex] = 0;
+ }
+}
+
+RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
+{
+ SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
+ RenderTarget11 *renderTarget = NULL;
+
+ if (depth)
+ {
+ // Note: depth stencil may be NULL for 0 sized surfaces
+ renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(),
+ swapChain11->getDepthStencilTexture(),
+ swapChain11->getDepthStencilShaderResource(),
+ swapChain11->getWidth(), swapChain11->getHeight(), 1);
+ }
+ else
+ {
+ // Note: render target may be NULL for 0 sized surfaces
+ renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(),
+ swapChain11->getOffscreenTexture(),
+ swapChain11->getRenderTargetShaderResource(),
+ swapChain11->getWidth(), swapChain11->getHeight(), 1);
+ }
+ return renderTarget;
+}
+
+RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples)
+{
+ RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples);
+ return renderTarget;
+}
+
+ShaderImpl *Renderer11::createShader(GLenum type)
+{
+ return new ShaderD3D(type, this);
+}
+
+ProgramImpl *Renderer11::createProgram()
+{
+ return new ProgramD3D(this);
+}
+
+void Renderer11::releaseShaderCompiler()
+{
+ ShaderD3D::releaseCompiler();
+}
+
+ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type,
+ const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+ bool separatedOutputBuffers)
+{
+ ShaderExecutable11 *executable = NULL;
+ HRESULT result;
+
+ switch (type)
+ {
+ case rx::SHADER_VERTEX:
+ {
+ ID3D11VertexShader *vertexShader = NULL;
+ ID3D11GeometryShader *streamOutShader = NULL;
+
+ result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader);
+ ASSERT(SUCCEEDED(result));
+
+ if (transformFeedbackVaryings.size() > 0)
+ {
+ std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration;
+ for (size_t i = 0; i < transformFeedbackVaryings.size(); i++)
+ {
+ const gl::LinkedVarying &varying = transformFeedbackVaryings[i];
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+
+ for (size_t j = 0; j < varying.semanticIndexCount; j++)
+ {
+ D3D11_SO_DECLARATION_ENTRY entry = { 0 };
+ entry.Stream = 0;
+ entry.SemanticName = varying.semanticName.c_str();
+ entry.SemanticIndex = varying.semanticIndex + j;
+ entry.StartComponent = 0;
+ entry.ComponentCount = gl::VariableColumnCount(transposedType);
+ entry.OutputSlot = (separatedOutputBuffers ? i : 0);
+ soDeclaration.push_back(entry);
+ }
+ }
+
+ result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(),
+ NULL, 0, 0, NULL, &streamOutShader);
+ ASSERT(SUCCEEDED(result));
+ }
+
+ if (vertexShader)
+ {
+ executable = new ShaderExecutable11(function, length, vertexShader, streamOutShader);
+ }
+ }
+ break;
+ case rx::SHADER_PIXEL:
+ {
+ ID3D11PixelShader *pixelShader = NULL;
+
+ result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader);
+ ASSERT(SUCCEEDED(result));
+
+ if (pixelShader)
+ {
+ executable = new ShaderExecutable11(function, length, pixelShader);
+ }
+ }
+ break;
+ case rx::SHADER_GEOMETRY:
+ {
+ ID3D11GeometryShader *geometryShader = NULL;
+
+ result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader);
+ ASSERT(SUCCEEDED(result));
+
+ if (geometryShader)
+ {
+ executable = new ShaderExecutable11(function, length, geometryShader);
+ }
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return executable;
+}
+
+ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
+ const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+ bool separatedOutputBuffers, D3DWorkaroundType workaround)
+{
+ const char *profileType = NULL;
+ switch (type)
+ {
+ case rx::SHADER_VERTEX:
+ profileType = "vs";
+ break;
+ case rx::SHADER_PIXEL:
+ profileType = "ps";
+ break;
+ case rx::SHADER_GEOMETRY:
+ profileType = "gs";
+ break;
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+
+ const char *profileVersion = NULL;
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ profileVersion = "5_0";
+ break;
+ case D3D_FEATURE_LEVEL_10_1:
+ profileVersion = "4_1";
+ break;
+ case D3D_FEATURE_LEVEL_10_0:
+ profileVersion = "4_0";
+ break;
+ case D3D_FEATURE_LEVEL_9_3:
+ profileVersion = "4_0_level_9_3";
+ break;
+ case D3D_FEATURE_LEVEL_9_2:
+ profileVersion = "4_0_level_9_2";
+ break;
+ case D3D_FEATURE_LEVEL_9_1:
+ profileVersion = "4_0_level_9_1";
+ break;
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+
+ char profile[32];
+ snprintf(profile, ArraySize(profile), "%s_%s", profileType, profileVersion);
+
+ UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL0;
+
+ if (gl::perfActive())
+ {
+#ifndef NDEBUG
+ flags = D3DCOMPILE_SKIP_OPTIMIZATION;
+#endif
+
+ flags |= D3DCOMPILE_DEBUG;
+
+ std::string sourcePath = getTempPath();
+ std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL);
+ writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
+ }
+
+ // 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.
+ const UINT extraFlags[] =
+ {
+ flags,
+ flags | D3DCOMPILE_SKIP_VALIDATION,
+ flags | D3DCOMPILE_SKIP_OPTIMIZATION
+ };
+
+ const static char *extraFlagNames[] =
+ {
+ "default",
+ "skip validation",
+ "skip optimization"
+ };
+
+ int attempts = ArraySize(extraFlags);
+
+ ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts);
+ if (!binary)
+ {
+ return NULL;
+ }
+
+ ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type,
+ transformFeedbackVaryings, separatedOutputBuffers);
+ SafeRelease(binary);
+
+ return executable;
+}
+
+rx::UniformStorage *Renderer11::createUniformStorage(size_t storageSize)
+{
+ return new UniformStorage11(this, storageSize);
+}
+
+VertexBuffer *Renderer11::createVertexBuffer()
+{
+ return new VertexBuffer11(this);
+}
+
+IndexBuffer *Renderer11::createIndexBuffer()
+{
+ return new IndexBuffer11(this);
+}
+
+BufferImpl *Renderer11::createBuffer()
+{
+ return new Buffer11(this);
+}
+
+VertexArrayImpl *Renderer11::createVertexArray()
+{
+ return new VertexArray11(this);
+}
+
+QueryImpl *Renderer11::createQuery(GLenum type)
+{
+ return new Query11(this, type);
+}
+
+FenceImpl *Renderer11::createFence()
+{
+ return new Fence11(this);
+}
+
+TransformFeedbackImpl* Renderer11::createTransformFeedback()
+{
+ return new TransformFeedbackD3D();
+}
+
+bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
+{
+ ASSERT(getRendererExtensions().pixelBufferObject);
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
+ const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat);
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11FormatInfo.texFormat);
+
+ // 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 (dxgiFormatInfo.internalFormat != internalFormat)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+ GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
+{
+ ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
+ return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea);
+}
+
+bool Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource)
+{
+ ASSERT(colorbuffer != NULL);
+
+ RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
+ if (renderTarget)
+ {
+ *subresourceIndex = renderTarget->getSubresourceIndex();
+
+ ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView();
+ if (colorBufferRTV)
+ {
+ ID3D11Resource *textureResource = NULL;
+ colorBufferRTV->GetResource(&textureResource);
+
+ if (textureResource)
+ {
+ HRESULT result = textureResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)resource);
+ SafeRelease(textureResource);
+
+ if (SUCCEEDED(result))
+ {
+ return true;
+ }
+ else
+ {
+ ERR("Failed to extract the ID3D11Texture2D from the render target resource, "
+ "HRESULT: 0x%X.", result);
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
+ const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter)
+{
+ if (blitRenderTarget)
+ {
+ gl::FramebufferAttachment *readBuffer = readTarget->getReadColorbuffer();
+
+ if (!readBuffer)
+ {
+ ERR("Failed to retrieve the read buffer from the read framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget *readRenderTarget = GetAttachmentRenderTarget(readBuffer);
+
+ for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ {
+ if (drawTarget->isEnabledColorAttachment(colorAttachment))
+ {
+ gl::FramebufferAttachment *drawBuffer = drawTarget->getColorbuffer(colorAttachment);
+
+ if (!drawBuffer)
+ {
+ ERR("Failed to retrieve the draw buffer from the draw framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget *drawRenderTarget = GetAttachmentRenderTarget(drawBuffer);
+
+ if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor,
+ blitRenderTarget, false, false))
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ if (blitDepth || blitStencil)
+ {
+ gl::FramebufferAttachment *readBuffer = readTarget->getDepthOrStencilbuffer();
+ gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer();
+
+ if (!readBuffer)
+ {
+ ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ if (!drawBuffer)
+ {
+ ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget *readRenderTarget = GetAttachmentRenderTarget(readBuffer);
+ RenderTarget *drawRenderTarget = GetAttachmentRenderTarget(drawBuffer);
+ ASSERT(readRenderTarget && drawRenderTarget);
+
+ if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor,
+ false, blitDepth, blitStencil))
+ {
+ return false;
+ }
+ }
+
+ invalidateFramebufferSwizzles(drawTarget);
+
+ return true;
+}
+
+gl::Error Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+ GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels)
+{
+ ID3D11Texture2D *colorBufferTexture = NULL;
+ unsigned int subresourceIndex = 0;
+
+ gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
+
+ if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
+ {
+ gl::Rectangle area;
+ area.x = x;
+ area.y = y;
+ area.width = width;
+ area.height = height;
+
+ gl::Buffer *packBuffer = pack.pixelBuffer.get();
+ if (packBuffer != NULL)
+ {
+ rx::Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation());
+ PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast<ptrdiff_t>(pixels));
+
+ gl::Error error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ packBuffer->getIndexRangeCache()->clear();
+ }
+ else
+ {
+ gl::Error error = readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ SafeRelease(colorBufferTexture);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+Image *Renderer11::createImage()
+{
+ return new Image11();
+}
+
+void Renderer11::generateMipmap(Image *dest, Image *src)
+{
+ Image11 *dest11 = Image11::makeImage11(dest);
+ Image11 *src11 = Image11::makeImage11(src);
+ Image11::generateMipmap(dest11, src11);
+}
+
+TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain)
+{
+ SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
+ return new TextureStorage11_2D(this, swapChain11);
+}
+
+TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
+{
+ return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels);
+}
+
+TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels)
+{
+ return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels);
+}
+
+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);
+}
+
+TextureImpl *Renderer11::createTexture(GLenum target)
+{
+ switch(target)
+ {
+ case GL_TEXTURE_2D: return new TextureD3D_2D(this);
+ case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this);
+ case GL_TEXTURE_3D: return new TextureD3D_3D(this);
+ case GL_TEXTURE_2D_ARRAY: return new TextureD3D_2DArray(this);
+ default:
+ UNREACHABLE();
+ }
+
+ return NULL;
+}
+
+gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format,
+ GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels)
+{
+ ASSERT(area.width >= 0);
+ ASSERT(area.height >= 0);
+
+ D3D11_TEXTURE2D_DESC textureDesc;
+ texture->GetDesc(&textureDesc);
+
+ // 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(area.x, 0, static_cast<int>(textureDesc.Width));
+ safeArea.y = gl::clamp(area.y, 0, static_cast<int>(textureDesc.Height));
+ safeArea.width = gl::clamp(area.width + std::min(area.x, 0), 0,
+ static_cast<int>(textureDesc.Width) - safeArea.x);
+ safeArea.height = gl::clamp(area.height + std::min(area.y, 0), 0,
+ static_cast<int>(textureDesc.Height) - safeArea.y);
+
+ ASSERT(safeArea.x >= 0 && safeArea.y >= 0);
+ ASSERT(safeArea.x + safeArea.width <= static_cast<int>(textureDesc.Width));
+ ASSERT(safeArea.y + safeArea.height <= static_cast<int>(textureDesc.Height));
+
+ if (safeArea.width == 0 || safeArea.height == 0)
+ {
+ // no work to do
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ D3D11_TEXTURE2D_DESC stagingDesc;
+ stagingDesc.Width = safeArea.width;
+ stagingDesc.Height = safeArea.height;
+ stagingDesc.MipLevels = 1;
+ stagingDesc.ArraySize = 1;
+ stagingDesc.Format = textureDesc.Format;
+ 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;
+
+ ID3D11Texture2D* stagingTex = NULL;
+ HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal staging texture for ReadPixels, HRESULT: 0x%X.", result);
+ }
+
+ ID3D11Texture2D* srcTex = NULL;
+ if (textureDesc.SampleDesc.Count > 1)
+ {
+ D3D11_TEXTURE2D_DESC resolveDesc;
+ resolveDesc.Width = textureDesc.Width;
+ resolveDesc.Height = textureDesc.Height;
+ resolveDesc.MipLevels = 1;
+ resolveDesc.ArraySize = 1;
+ resolveDesc.Format = textureDesc.Format;
+ resolveDesc.SampleDesc.Count = 1;
+ resolveDesc.SampleDesc.Quality = 0;
+ resolveDesc.Usage = D3D11_USAGE_DEFAULT;
+ resolveDesc.BindFlags = 0;
+ resolveDesc.CPUAccessFlags = 0;
+ resolveDesc.MiscFlags = 0;
+
+ result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex);
+ if (FAILED(result))
+ {
+ SafeRelease(stagingTex);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal resolve texture for ReadPixels, HRESULT: 0x%X.", result);
+ }
+
+ mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format);
+ subResource = 0;
+ }
+ else
+ {
+ srcTex = texture;
+ srcTex->AddRef();
+ }
+
+ 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);
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox);
+
+ SafeRelease(srcTex);
+
+ PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0);
+ packPixels(stagingTex, packParams, pixels);
+
+ SafeRelease(stagingTex);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams &params, uint8_t *pixelsOut)
+{
+ D3D11_TEXTURE2D_DESC textureDesc;
+ readTexture->GetDesc(&textureDesc);
+
+ D3D11_MAPPED_SUBRESOURCE mapping;
+ HRESULT hr = mDeviceContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &mapping);
+ UNUSED_ASSERTION_VARIABLE(hr);
+ ASSERT(SUCCEEDED(hr));
+
+ uint8_t *source;
+ int inputPitch;
+ if (params.pack.reverseRowOrder)
+ {
+ source = static_cast<uint8_t*>(mapping.pData) + mapping.RowPitch * (params.area.height - 1);
+ inputPitch = -static_cast<int>(mapping.RowPitch);
+ }
+ else
+ {
+ source = static_cast<uint8_t*>(mapping.pData);
+ inputPitch = static_cast<int>(mapping.RowPitch);
+ }
+
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(textureDesc.Format);
+ const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat);
+ if (sourceFormatInfo.format == params.format && sourceFormatInfo.type == params.type)
+ {
+ uint8_t *dest = pixelsOut + params.offset;
+ for (int y = 0; y < params.area.height; y++)
+ {
+ memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourceFormatInfo.pixelBytes);
+ }
+ }
+ else
+ {
+ const d3d11::DXGIFormat &sourceDXGIFormatInfo = d3d11::GetDXGIFormatInfo(textureDesc.Format);
+ ColorCopyFunction fastCopyFunc = sourceDXGIFormatInfo.getFastCopyFunction(params.format, params.type);
+
+ const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(params.format, params.type);
+ const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat);
+
+ 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 = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes;
+ const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
+
+ fastCopyFunc(src, dest);
+ }
+ }
+ }
+ else
+ {
+ uint8_t temp[16]; // Maximum size of any Color<T> type used.
+ META_ASSERT(sizeof(temp) >= sizeof(gl::ColorF) &&
+ sizeof(temp) >= sizeof(gl::ColorUI) &&
+ sizeof(temp) >= sizeof(gl::ColorI));
+
+ for (int y = 0; y < params.area.height; y++)
+ {
+ for (int x = 0; x < params.area.width; x++)
+ {
+ uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes;
+ const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
+
+ // readFunc and writeFunc will be using the same type of color, CopyTexImage
+ // will not allow the copy otherwise.
+ sourceDXGIFormatInfo.colorReadFunction(src, temp);
+ destFormatTypeInfo.colorWriteFunction(temp, dest);
+ }
+ }
+ }
+ }
+
+ mDeviceContext->Unmap(readTexture, 0);
+}
+
+bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
+ RenderTarget *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));
+
+ bool result = true;
+
+ RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget);
+ if (!drawRenderTarget)
+ {
+ ERR("Failed to retrieve the draw render target from the draw framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11Resource *drawTexture = drawRenderTarget11->getTexture();
+ unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
+ ID3D11RenderTargetView *drawRTV = drawRenderTarget11->getRenderTargetView();
+ ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView();
+
+ RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget);
+ if (!readRenderTarget)
+ {
+ ERR("Failed to retrieve the read render target from the read framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11Resource *readTexture = NULL;
+ ID3D11ShaderResourceView *readSRV = NULL;
+ unsigned int readSubresource = 0;
+ if (readRenderTarget->getSamples() > 0)
+ {
+ ID3D11Resource *unresolvedResource = readRenderTarget11->getTexture();
+ ID3D11Texture2D *unresolvedTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(unresolvedResource);
+
+ if (unresolvedTexture)
+ {
+ readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex());
+ readSubresource = 0;
+
+ SafeRelease(unresolvedTexture);
+
+ HRESULT hresult = mDevice->CreateShaderResourceView(readTexture, NULL, &readSRV);
+ if (FAILED(hresult))
+ {
+ SafeRelease(readTexture);
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+ }
+ }
+ else
+ {
+ readTexture = readRenderTarget11->getTexture();
+ readTexture->AddRef();
+ readSubresource = readRenderTarget11->getSubresourceIndex();
+ readSRV = readRenderTarget11->getShaderResourceView();
+ readSRV->AddRef();
+ }
+
+ if (!readTexture || !readSRV)
+ {
+ SafeRelease(readTexture);
+ SafeRelease(readSRV);
+ ERR("Failed to retrieve the read render target view from the read render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
+ gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
+
+ bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL);
+
+ bool wholeBufferCopy = !scissorNeeded &&
+ 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;
+
+ const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getActualFormat());
+ bool partialDSBlit = (actualFormatInfo.depthBits > 0 && depthBlit) != (actualFormatInfo.stencilBits > 0 && stencilBlit);
+
+ if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() &&
+ !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
+ (!(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 ? NULL : &readBox;
+
+ mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, dstX, dstY, 0,
+ readTexture, readSubresource, pSrcBox);
+ result = true;
+ }
+ 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)
+ {
+ result = mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize,
+ drawTexture, drawSubresource, drawArea, drawSize,
+ scissor);
+ }
+ else if (depthBlit)
+ {
+ result = mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize,
+ scissor);
+ }
+ else if (stencilBlit)
+ {
+ result = mBlit->copyStencil(readTexture, readSubresource, readArea, readSize,
+ drawTexture, drawSubresource, drawArea, drawSize,
+ scissor);
+ }
+ else
+ {
+ GLenum format = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()).format;
+ result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize,
+ scissor, format, filter);
+ }
+ }
+
+ SafeRelease(readTexture);
+ SafeRelease(readSRV);
+
+ return result;
+}
+
+ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource)
+{
+ D3D11_TEXTURE2D_DESC textureDesc;
+ source->GetDesc(&textureDesc);
+
+ if (textureDesc.SampleDesc.Count > 1)
+ {
+ D3D11_TEXTURE2D_DESC resolveDesc;
+ resolveDesc.Width = textureDesc.Width;
+ resolveDesc.Height = textureDesc.Height;
+ resolveDesc.MipLevels = 1;
+ resolveDesc.ArraySize = 1;
+ resolveDesc.Format = textureDesc.Format;
+ resolveDesc.SampleDesc.Count = 1;
+ resolveDesc.SampleDesc.Quality = 0;
+ resolveDesc.Usage = textureDesc.Usage;
+ resolveDesc.BindFlags = textureDesc.BindFlags;
+ resolveDesc.CPUAccessFlags = 0;
+ resolveDesc.MiscFlags = 0;
+
+ ID3D11Texture2D *resolveTexture = NULL;
+ HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture);
+ if (FAILED(result))
+ {
+ ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result);
+ return NULL;
+ }
+
+ mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format);
+ return resolveTexture;
+ }
+ else
+ {
+ source->AddRef();
+ return source;
+ }
+}
+
+void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel)
+{
+ ASSERT(attachment->isTexture());
+ gl::Texture *texture = attachment->getTexture();
+
+ TextureStorage *texStorage = texture->getNativeTexture();
+ if (texStorage)
+ {
+ TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage);
+ if (!texStorage11)
+ {
+ ERR("texture storage pointer unexpectedly null.");
+ return;
+ }
+
+ texStorage11->invalidateSwizzleCacheLevel(mipLevel);
+ }
+}
+
+void Renderer11::invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer)
+{
+ for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ {
+ gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(colorAttachment);
+ if (attachment && attachment->isTexture())
+ {
+ invalidateFBOAttachmentSwizzles(attachment, attachment->mipLevel());
+ }
+ }
+
+ gl::FramebufferAttachment *depthAttachment = framebuffer->getDepthbuffer();
+ if (depthAttachment && depthAttachment->isTexture())
+ {
+ invalidateFBOAttachmentSwizzles(depthAttachment, depthAttachment->mipLevel());
+ }
+
+ gl::FramebufferAttachment *stencilAttachment = framebuffer->getStencilbuffer();
+ if (stencilAttachment && stencilAttachment->isTexture())
+ {
+ invalidateFBOAttachmentSwizzles(stencilAttachment, stencilAttachment->mipLevel());
+ }
+}
+
+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;
+}
+
+rx::VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const
+{
+ return d3d11::GetVertexFormatInfo(vertexFormat).conversionType;
+}
+
+GLenum Renderer11::getVertexComponentType(const gl::VertexFormat &vertexFormat) const
+{
+ return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormat).nativeFormat).componentType;
+}
+
+void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const
+{
+ d3d11_gl::GenerateCaps(mDevice, outCaps, outTextureCaps, outExtensions);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
new file mode 100644
index 0000000000..2a53fa1672
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
@@ -0,0 +1,346 @@
+//
+// 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 LIBGLESV2_RENDERER_RENDERER11_H_
+#define LIBGLESV2_RENDERER_RENDERER11_H_
+
+#include "common/angleutils.h"
+#include "libGLESv2/angletypes.h"
+#include "common/mathutil.h"
+
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
+#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h"
+#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h"
+#include "libGLESv2/renderer/RenderTarget.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace rx
+{
+
+class VertexDataManager;
+class IndexDataManager;
+class StreamingIndexBufferInterface;
+class Blit11;
+class Clear11;
+class PixelTransfer11;
+struct PackPixelsParams;
+
+enum
+{
+ MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024,
+ MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024
+};
+
+class Renderer11 : public Renderer
+{
+ public:
+ Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay);
+ virtual ~Renderer11();
+
+ static Renderer11 *makeRenderer11(Renderer *renderer);
+
+ virtual EGLint initialize();
+ virtual bool resetDevice();
+
+ virtual int generateConfigs(ConfigDesc **configDescList);
+ virtual void deleteConfigs(ConfigDesc *configDescList);
+
+ virtual void sync(bool block);
+
+ virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
+
+ virtual gl::Error generateSwizzle(gl::Texture *texture);
+ virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
+ virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture);
+
+ virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]);
+
+ virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
+ virtual gl::Error setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
+ unsigned int sampleMask);
+ virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
+ int stencilBackRef, bool frontFaceCCW);
+
+ virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+ virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
+ bool ignoreViewport);
+
+ virtual bool applyPrimitiveType(GLenum mode, GLsizei count);
+ virtual gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer);
+ virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
+ bool rasterizerDiscard, bool transformFeedbackActive);
+ virtual gl::Error applyUniforms(const gl::ProgramBinary &programBinary);
+ virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[],
+ GLint first, GLsizei count, GLsizei instances);
+ virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
+ virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]);
+
+ virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive);
+ virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
+ gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
+
+ virtual gl::Error clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
+
+ virtual void markAllStateDirty();
+
+ // lost device
+ void notifyDeviceLost();
+ virtual bool isDeviceLost();
+ virtual bool testDeviceLost(bool notify);
+ virtual bool testDeviceResettable();
+
+ virtual DWORD getAdapterVendor() const;
+ virtual std::string getRendererDescription() const;
+ virtual GUID getAdapterIdentifier() const;
+
+ virtual unsigned int getReservedVertexUniformVectors() const;
+ virtual unsigned int getReservedFragmentUniformVectors() const;
+ virtual unsigned int getReservedVertexUniformBuffers() const;
+ virtual unsigned int getReservedFragmentUniformBuffers() const;
+ virtual bool getShareHandleSupport() const;
+ virtual bool getPostSubBufferSupport() const;
+
+ virtual int getMajorShaderModel() const;
+ virtual int getMinSwapInterval() const;
+ virtual int getMaxSwapInterval() const;
+
+ // Pixel operations
+ virtual bool copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source);
+ virtual bool copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source);
+ virtual bool copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source);
+ virtual bool copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source);
+
+ virtual bool copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level);
+ virtual bool copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level);
+ virtual bool copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
+ virtual bool copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
+
+ virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
+ const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter);
+
+ virtual gl::Error readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+ GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
+
+ // RenderTarget creation
+ virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth);
+ virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples);
+
+ // Shader creation
+ virtual ShaderImpl *createShader(GLenum type);
+ virtual ProgramImpl *createProgram();
+
+ // Shader operations
+ virtual void releaseShaderCompiler();
+ virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
+ const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+ bool separatedOutputBuffers);
+ virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
+ const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+ bool separatedOutputBuffers, D3DWorkaroundType workaround);
+ virtual UniformStorage *createUniformStorage(size_t storageSize);
+
+ // Image operations
+ virtual Image *createImage();
+ virtual void generateMipmap(Image *dest, Image *source);
+ virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
+ virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
+ virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels);
+ virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
+ virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
+
+ // Texture creation
+ virtual TextureImpl *createTexture(GLenum target);
+
+ // Buffer creation
+ virtual BufferImpl *createBuffer();
+ virtual VertexBuffer *createVertexBuffer();
+ virtual IndexBuffer *createIndexBuffer();
+
+ // Vertex Array creation
+ virtual VertexArrayImpl *createVertexArray();
+
+ // Query and Fence creation
+ virtual QueryImpl *createQuery(GLenum type);
+ virtual FenceImpl *createFence();
+
+ // Transform Feedback creation
+ virtual TransformFeedbackImpl* createTransformFeedback();
+
+ // D3D11-renderer specific methods
+ ID3D11Device *getDevice() { return mDevice; }
+ ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
+ IDXGIFactory *getDxgiFactory() { return mDxgiFactory; };
+ bool isLevel9() { return mFeatureLevel <= D3D_FEATURE_LEVEL_9_3; }
+
+ Blit11 *getBlitter() { return mBlit; }
+
+ // Buffer-to-texture and Texture-to-buffer copies
+ virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const;
+ virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+ GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
+
+ bool getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource);
+ void unapplyRenderTargets();
+ void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView);
+ void packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams &params, uint8_t *pixelsOut);
+
+ virtual bool getLUID(LUID *adapterLuid) const;
+ virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const;
+ virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Renderer11);
+
+ virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const;
+
+ gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
+ gl::Error drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances);
+
+ gl::Error readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format,
+ GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
+
+ bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
+ RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
+ bool colorBlit, bool depthBlit, bool stencilBlit);
+ ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
+
+ static void invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel);
+ static void invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer);
+
+ HMODULE mD3d11Module;
+ HMODULE mDxgiModule;
+ EGLNativeDisplayType mDc;
+ EGLint mRequestedDisplay;
+
+ HLSLCompiler mCompiler;
+
+ bool mDeviceLost;
+
+ void initializeDevice();
+ void releaseDeviceResources();
+ int getMinorShaderModel() const;
+ void release();
+
+ RenderStateCache mStateCache;
+
+ // current render target states
+ unsigned int mAppliedRenderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
+ unsigned int mAppliedDepthbufferSerial;
+ unsigned int mAppliedStencilbufferSerial;
+ bool mDepthStencilInitialized;
+ bool mRenderTargetDescInitialized;
+ rx::RenderTarget::Desc mRenderTargetDesc;
+
+ // Currently applied sampler states
+ std::vector<bool> mForceSetVertexSamplerStates;
+ std::vector<gl::SamplerState> mCurVertexSamplerStates;
+
+ std::vector<bool> mForceSetPixelSamplerStates;
+ std::vector<gl::SamplerState> mCurPixelSamplerStates;
+
+ // Currently applied textures
+ std::vector<ID3D11ShaderResourceView*> mCurVertexSRVs;
+ std::vector<ID3D11ShaderResourceView*> mCurPixelSRVs;
+
+ // Currently applied blend state
+ bool mForceSetBlendState;
+ gl::BlendState mCurBlendState;
+ gl::ColorF mCurBlendColor;
+ unsigned int mCurSampleMask;
+
+ // Currently applied rasterizer state
+ bool mForceSetRasterState;
+ gl::RasterizerState mCurRasterState;
+
+ // Currently applied depth stencil state
+ bool mForceSetDepthStencilState;
+ gl::DepthStencilState mCurDepthStencilState;
+ int mCurStencilRef;
+ int mCurStencilBackRef;
+
+ // Currently applied scissor rectangle
+ bool mForceSetScissor;
+ bool mScissorEnabled;
+ gl::Rectangle mCurScissor;
+
+ // Currently applied viewport
+ bool mForceSetViewport;
+ gl::Rectangle mCurViewport;
+ float mCurNear;
+ float mCurFar;
+
+ // Currently applied primitive topology
+ D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology;
+
+ // Currently applied index buffer
+ ID3D11Buffer *mAppliedIB;
+ DXGI_FORMAT mAppliedIBFormat;
+ unsigned int mAppliedIBOffset;
+
+ // Currently applied transform feedback buffers
+ ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
+ GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
+
+ // Currently applied shaders
+ ID3D11VertexShader *mAppliedVertexShader;
+ ID3D11GeometryShader *mAppliedGeometryShader;
+ ID3D11GeometryShader *mCurPointGeometryShader;
+ ID3D11PixelShader *mAppliedPixelShader;
+
+ dx_VertexConstants mVertexConstants;
+ dx_VertexConstants mAppliedVertexConstants;
+ ID3D11Buffer *mDriverConstantBufferVS;
+ ID3D11Buffer *mCurrentVertexConstantBuffer;
+ unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
+
+ dx_PixelConstants mPixelConstants;
+ dx_PixelConstants mAppliedPixelConstants;
+ ID3D11Buffer *mDriverConstantBufferPS;
+ ID3D11Buffer *mCurrentPixelConstantBuffer;
+ unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_VERTEX_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;
+
+ // Sync query
+ ID3D11Query *mSyncQuery;
+
+ ID3D11Device *mDevice;
+ D3D_FEATURE_LEVEL mFeatureLevel;
+ ID3D11DeviceContext *mDeviceContext;
+ IDXGIAdapter *mDxgiAdapter;
+ DXGI_ADAPTER_DESC mAdapterDescription;
+ char mDescription[128];
+ IDXGIFactory *mDxgiFactory;
+};
+
+}
+#endif // LIBGLESV2_RENDERER_RENDERER11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp
index 2e455e3af5..52f34887fb 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp
@@ -1,6 +1,5 @@
-#include "precompiled.h"
//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -8,9 +7,8 @@
// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader
// executable implementation details.
-#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h"
-
-#include "common/debug.h"
+#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
namespace rx
{
@@ -21,18 +19,16 @@ ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D
mPixelExecutable = executable;
mVertexExecutable = NULL;
mGeometryExecutable = NULL;
-
- mConstantBuffer = NULL;
+ mStreamOutExecutable = NULL;
}
-ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable)
+ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut)
: ShaderExecutable(function, length)
{
mVertexExecutable = executable;
mPixelExecutable = NULL;
mGeometryExecutable = NULL;
-
- mConstantBuffer = NULL;
+ mStreamOutExecutable = streamOut;
}
ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable)
@@ -41,29 +37,15 @@ ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D
mGeometryExecutable = executable;
mVertexExecutable = NULL;
mPixelExecutable = NULL;
-
- mConstantBuffer = NULL;
+ mStreamOutExecutable = NULL;
}
ShaderExecutable11::~ShaderExecutable11()
{
- if (mVertexExecutable)
- {
- mVertexExecutable->Release();
- }
- if (mPixelExecutable)
- {
- mPixelExecutable->Release();
- }
- if (mGeometryExecutable)
- {
- mGeometryExecutable->Release();
- }
-
- if (mConstantBuffer)
- {
- mConstantBuffer->Release();
- }
+ SafeRelease(mVertexExecutable);
+ SafeRelease(mPixelExecutable);
+ SafeRelease(mGeometryExecutable);
+ SafeRelease(mStreamOutExecutable);
}
ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutable *executable)
@@ -87,23 +69,42 @@ ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const
return mGeometryExecutable;
}
-ID3D11Buffer *ShaderExecutable11::getConstantBuffer(ID3D11Device *device, unsigned int registerCount)
+ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const
+{
+ return mStreamOutExecutable;
+}
+
+UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize)
+ : UniformStorage(initialSize),
+ mConstantBuffer(NULL)
{
- if (!mConstantBuffer && registerCount > 0)
+ ID3D11Device *d3d11Device = renderer->getDevice();
+
+ if (initialSize > 0)
{
D3D11_BUFFER_DESC constantBufferDescription = {0};
- constantBufferDescription.ByteWidth = registerCount * sizeof(float[4]);
+ constantBufferDescription.ByteWidth = 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 = device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer);
+ HRESULT result = d3d11Device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer);
+ UNUSED_ASSERTION_VARIABLE(result);
ASSERT(SUCCEEDED(result));
}
+}
- return mConstantBuffer;
+UniformStorage11::~UniformStorage11()
+{
+ SafeRelease(mConstantBuffer);
}
-} \ No newline at end of file
+const UniformStorage11 *UniformStorage11::makeUniformStorage11(const UniformStorage *uniformStorage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(const UniformStorage11*, uniformStorage));
+ return static_cast<const UniformStorage11*>(uniformStorage);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h
index c6ec1cf7d2..74a1e03915 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -14,12 +14,14 @@
namespace rx
{
+class Renderer11;
+class UniformStorage11;
class ShaderExecutable11 : public ShaderExecutable
{
public:
ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable);
- ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable);
+ ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut);
ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable);
virtual ~ShaderExecutable11();
@@ -29,8 +31,7 @@ class ShaderExecutable11 : public ShaderExecutable
ID3D11PixelShader *getPixelShader() const;
ID3D11VertexShader *getVertexShader() const;
ID3D11GeometryShader *getGeometryShader() const;
-
- ID3D11Buffer *getConstantBuffer(ID3D11Device *device, unsigned int registerCount);
+ ID3D11GeometryShader *getStreamOutShader() const;
private:
DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11);
@@ -38,7 +39,20 @@ class ShaderExecutable11 : public ShaderExecutable
ID3D11PixelShader *mPixelExecutable;
ID3D11VertexShader *mVertexExecutable;
ID3D11GeometryShader *mGeometryExecutable;
+ ID3D11GeometryShader *mStreamOutExecutable;
+};
+
+class UniformStorage11 : public UniformStorage
+{
+ public:
+ UniformStorage11(Renderer11 *renderer, size_t initialSize);
+ virtual ~UniformStorage11();
+
+ static const UniformStorage11 *makeUniformStorage11(const UniformStorage *uniformStorage);
+ ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; }
+
+ private:
ID3D11Buffer *mConstantBuffer;
};
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
index bd97d5cff5..4b29be055d 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
@@ -1,19 +1,20 @@
-#include "precompiled.h"
//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// 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 "libGLESv2/renderer/d3d11/SwapChain11.h"
+#include "common/platform.h"
+#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
+#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
-#include "libGLESv2/renderer/d3d11/Renderer11.h"
-
-#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h"
-#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h"
+// Precompiled shaders
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h"
+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h"
namespace rx
{
@@ -30,6 +31,7 @@ SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDL
mOffscreenSRView = NULL;
mDepthStencilTexture = NULL;
mDepthStencilDSView = NULL;
+ mDepthStencilSRView = NULL;
mQuadVB = NULL;
mPassThroughSampler = NULL;
mPassThroughIL = NULL;
@@ -37,6 +39,8 @@ SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDL
mPassThroughPS = NULL;
mWidth = -1;
mHeight = -1;
+ mViewportWidth = -1;
+ mViewportHeight = -1;
mSwapInterval = 0;
mAppCreatedShareHandle = mShareHandle != NULL;
mPassThroughResourcesInit = false;
@@ -57,6 +61,7 @@ void SwapChain11::release()
SafeRelease(mOffscreenSRView);
SafeRelease(mDepthStencilTexture);
SafeRelease(mDepthStencilDSView);
+ SafeRelease(mDepthStencilSRView);
SafeRelease(mQuadVB);
SafeRelease(mPassThroughSampler);
SafeRelease(mPassThroughIL);
@@ -76,6 +81,7 @@ void SwapChain11::releaseOffscreenTexture()
SafeRelease(mOffscreenSRView);
SafeRelease(mDepthStencilTexture);
SafeRelease(mDepthStencilDSView);
+ SafeRelease(mDepthStencilSRView);
}
EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
@@ -89,6 +95,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
ASSERT(backbufferHeight >= 1);
// Preserve the render target content
+#if !defined(ANGLE_PLATFORM_WINRT)
ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
if (previousOffscreenTexture)
{
@@ -96,9 +103,12 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
}
const int previousWidth = mWidth;
const int previousHeight = mHeight;
+#endif
releaseOffscreenTexture();
+ const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat);
+
// If the app passed in a share handle, open the resource
// See EGL_ANGLE_d3d_share_handle_client_buffer
if (mAppCreatedShareHandle)
@@ -114,7 +124,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
}
result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
- tempResource11->Release();
+ SafeRelease(tempResource11);
if (FAILED(result))
{
@@ -127,11 +137,11 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
mOffscreenTexture->GetDesc(&offscreenTextureDesc);
- if (offscreenTextureDesc.Width != (UINT)backbufferWidth
- || offscreenTextureDesc.Height != (UINT)backbufferHeight
- || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat)
- || offscreenTextureDesc.MipLevels != 1
- || offscreenTextureDesc.ArraySize != 1)
+ if (offscreenTextureDesc.Width != (UINT)backbufferWidth ||
+ offscreenTextureDesc.Height != (UINT)backbufferHeight ||
+ offscreenTextureDesc.Format != backbufferFormatInfo.texFormat ||
+ offscreenTextureDesc.MipLevels != 1 ||
+ offscreenTextureDesc.ArraySize != 1)
{
ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
release();
@@ -145,7 +155,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
offscreenTextureDesc.Width = backbufferWidth;
offscreenTextureDesc.Height = backbufferHeight;
- offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
+ offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
offscreenTextureDesc.MipLevels = 1;
offscreenTextureDesc.ArraySize = 1;
offscreenTextureDesc.SampleDesc.Count = 1;
@@ -172,7 +182,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
}
}
- d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");
+ 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)
@@ -188,7 +198,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
else
{
result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
- offscreenTextureResource->Release();
+ SafeRelease(offscreenTextureResource);
if (FAILED(result))
{
@@ -198,32 +208,45 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
}
}
}
-
- HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);
+
+ 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 render target");
+ d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target");
- result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView);
+ D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc;
+ offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat;
+ offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ offscreenSRVDesc.Texture2D.MostDetailedMip = 0;
+ offscreenSRVDesc.Texture2D.MipLevels = -1;
+
+ result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView);
ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource");
+ d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource");
+
+ const d3d11::TextureFormat &depthBufferFormatInfo = d3d11::GetTextureFormatInfo(mDepthBufferFormat);
if (mDepthBufferFormat != GL_NONE)
{
- D3D11_TEXTURE2D_DESC depthStencilDesc = {0};
- depthStencilDesc.Width = backbufferWidth;
- depthStencilDesc.Height = backbufferHeight;
- depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat);
- depthStencilDesc.MipLevels = 1;
- depthStencilDesc.ArraySize = 1;
- depthStencilDesc.SampleDesc.Count = 1;
- depthStencilDesc.SampleDesc.Quality = 0;
- depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
- depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
- depthStencilDesc.CPUAccessFlags = 0;
- depthStencilDesc.MiscFlags = 0;
-
- result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture);
+ 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 | D3D11_BIND_SHADER_RESOURCE;
+ depthStencilTextureDesc.CPUAccessFlags = 0;
+ depthStencilTextureDesc.MiscFlags = 0;
+
+ result = device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture);
if (FAILED(result))
{
ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
@@ -238,16 +261,37 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
return EGL_BAD_ALLOC;
}
}
- d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture");
+ 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, NULL, &mDepthStencilDSView);
+ result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView);
ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view");
+ d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view");
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc;
+ depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat;
+ depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ depthStencilSRVDesc.Texture2D.MostDetailedMip = 0;
+ depthStencilSRVDesc.Texture2D.MipLevels = -1;
+
+ result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource");
}
mWidth = backbufferWidth;
mHeight = backbufferHeight;
+#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP
+ mViewportWidth = backbufferWidth;
+ mViewportHeight = backbufferHeight;
+#endif
+#if !defined(ANGLE_PLATFORM_WINRT)
if (previousOffscreenTexture != NULL)
{
D3D11_BOX sourceBox = {0};
@@ -262,13 +306,14 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
const int yoffset = std::max(mHeight - previousHeight, 0);
deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
- previousOffscreenTexture->Release();
+ SafeRelease(previousOffscreenTexture);
if (mSwapChain)
{
- swapRect(0, 0, mWidth, mHeight);
+ swapRect(0, 0, mWidth, mHeight, SWAP_NORMAL);
}
}
+#endif
return EGL_SUCCESS;
}
@@ -295,8 +340,15 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
SafeRelease(mBackBufferRTView);
// Resize swap chain
- DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
- HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0);
+ HRESULT result;
+#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP // Windows phone swap chain is never resized, only the texture is
+#if !defined(ANGLE_PLATFORM_WINRT)
+ const int bufferCount = 1;
+#else
+ const int bufferCount = 2;
+#endif
+ const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat);
+ result = mSwapChain->ResizeBuffers(bufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0);
if (FAILED(result))
{
@@ -312,6 +364,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
return EGL_BAD_ALLOC;
}
}
+#endif
result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
ASSERT(SUCCEEDED(result));
@@ -361,51 +414,60 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
if (mWindow)
{
-#if !defined(ANGLE_OS_WINRT)
+ const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat);
+
IDXGIFactory *factory = mRenderer->getDxgiFactory();
+#if !defined(ANGLE_PLATFORM_WINRT)
DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
- swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
swapChainDesc.BufferDesc.Width = backbufferWidth;
swapChainDesc.BufferDesc.Height = backbufferHeight;
- swapChainDesc.BufferCount = 2;
- 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.Windowed = TRUE;
+ swapChainDesc.BufferDesc.Format = backbufferFormatInfo.texFormat;
+ swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+ swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = mWindow;
+ swapChainDesc.Windowed = TRUE;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+ swapChainDesc.Flags = 0;
+
+ HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
#else
- IDXGIFactory2 *factory;
- HRESULT result = mRenderer->getDxgiFactory()->QueryInterface(IID_PPV_ARGS(&factory));
+ IDXGIFactory2 *factory2;
+ HRESULT result = factory->QueryInterface(IID_PPV_ARGS(&factory2));
ASSERT(SUCCEEDED(result));
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
- swapChainDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
- swapChainDesc.Width = backbufferWidth;
- swapChainDesc.Height = backbufferHeight;
+ swapChainDesc.Width = 0;
+ swapChainDesc.Height = 0;
+ swapChainDesc.Format = backbufferFormatInfo.texFormat;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.Stereo = FALSE;
-#if !defined(ANGLE_OS_WINPHONE)
+ swapChainDesc.Flags = 0;
+#if WINAPI_FAMILY==WINAPI_FAMILY_PC_APP
+ swapChainDesc.Scaling = DXGI_SCALING_NONE;
swapChainDesc.BufferCount = 2;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
-#else
+#elif WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
swapChainDesc.BufferCount = 1;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
#endif
-#endif
- swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- swapChainDesc.Flags = 0;
- swapChainDesc.SampleDesc.Count = 1;
- swapChainDesc.SampleDesc.Quality = 0;
-#if !defined(ANGLE_OS_WINRT)
- HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
-#else
IDXGISwapChain1 *swapChain;
- result = factory->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain);
+ result = factory2->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain);
mSwapChain = swapChain;
+ HRESULT hr = swapChain->GetDesc1(&swapChainDesc);
+ ASSERT(SUCCEEDED(hr));
+ mViewportWidth = swapChainDesc.Width;
+ mViewportHeight = swapChainDesc.Height;
#endif
-
if (FAILED(result))
{
ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
@@ -415,28 +477,10 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
{
return EGL_CONTEXT_LOST;
}
-#if !defined(ANGLE_OS_WINRT)
else
{
- // We cannot create a swap chain for an HWND that is owned by a different process on some versions of
- // windows
- DWORD currentProcessId = GetCurrentProcessId();
- DWORD wndProcessId;
- GetWindowThreadProcessId(mWindow, &wndProcessId);
-
- if (currentProcessId != wndProcessId)
- {
- ERR("Could not create swap chain, window owned by different process");
- return EGL_BAD_NATIVE_WINDOW;
- }
- else
- {
- return EGL_BAD_ALLOC;
- }
+ return EGL_BAD_ALLOC;
}
-#else
- return EGL_BAD_ALLOC;
-#endif
}
result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
@@ -493,7 +537,7 @@ void SwapChain11::initPassThroughResources()
samplerDesc.BorderColor[2] = 0.0f;
samplerDesc.BorderColor[3] = 0.0f;
samplerDesc.MinLOD = 0;
- samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
+ samplerDesc.MaxLOD = FLT_MAX;
result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
ASSERT(SUCCEEDED(result));
@@ -505,21 +549,21 @@ void SwapChain11::initPassThroughResources()
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
- result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL);
+ 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_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS);
+ 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_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS);
+ result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS);
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
}
// parameters should be validated/clamped by caller
-EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags)
{
if (!mSwapChain)
{
@@ -550,10 +594,13 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
float u2 = (x + width) / float(mWidth);
float v2 = (y + height) / float(mHeight);
- 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);
+ const int rotateL = flags & SWAP_ROTATE_90;
+ const int rotateR = flags & SWAP_ROTATE_270;
+
+ d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1);
+ d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2);
+ d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1);
+ d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2);
deviceContext->Unmap(mQuadVB, 0);
@@ -583,8 +630,8 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
- viewport.Width = mWidth;
- viewport.Height = mHeight;
+ viewport.Width = mViewportWidth;
+ viewport.Height = mViewportHeight;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
deviceContext->RSSetViewports(1, &viewport);
@@ -596,7 +643,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
// Draw
deviceContext->Draw(4, 0);
-#if ANGLE_FORCE_VSYNC_OFF
+#ifdef ANGLE_FORCE_VSYNC_OFF
result = mSwapChain->Present(0, 0);
#else
result = mSwapChain->Present(mSwapInterval, 0);
@@ -605,6 +652,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
if (result == DXGI_ERROR_DEVICE_REMOVED)
{
HRESULT removedReason = device->GetDeviceRemovedReason();
+ UNUSED_TRACE_VARIABLE(removedReason);
ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
return EGL_CONTEXT_LOST;
}
@@ -628,61 +676,33 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
return EGL_SUCCESS;
}
-// Increments refcount on texture.
-// caller must Release() the returned texture
ID3D11Texture2D *SwapChain11::getOffscreenTexture()
{
- if (mOffscreenTexture)
- {
- mOffscreenTexture->AddRef();
- }
-
return mOffscreenTexture;
}
-// Increments refcount on view.
-// caller must Release() the returned view
ID3D11RenderTargetView *SwapChain11::getRenderTarget()
{
- if (mOffscreenRTView)
- {
- mOffscreenRTView->AddRef();
- }
-
return mOffscreenRTView;
}
-// Increments refcount on view.
-// caller must Release() the returned view
ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
{
- if (mOffscreenSRView)
- {
- mOffscreenSRView->AddRef();
- }
-
return mOffscreenSRView;
}
-// Increments refcount on view.
-// caller must Release() the returned view
ID3D11DepthStencilView *SwapChain11::getDepthStencil()
{
- if (mDepthStencilDSView)
- {
- mDepthStencilDSView->AddRef();
- }
-
return mDepthStencilDSView;
}
-ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
+ID3D11ShaderResourceView * SwapChain11::getDepthStencilShaderResource()
{
- if (mDepthStencilTexture)
- {
- mDepthStencilTexture->AddRef();
- }
+ return mDepthStencilSRView;
+}
+ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
+{
return mDepthStencilTexture;
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h
index 2a030c839d..b30b78568a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h
@@ -25,7 +25,7 @@ class SwapChain11 : public SwapChain
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 EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags);
virtual void recreate();
virtual ID3D11Texture2D *getOffscreenTexture();
@@ -34,6 +34,7 @@ class SwapChain11 : public SwapChain
virtual ID3D11Texture2D *getDepthStencilTexture();
virtual ID3D11DepthStencilView *getDepthStencil();
+ virtual ID3D11ShaderResourceView *getDepthStencilShaderResource();
EGLint getWidth() const { return mWidth; }
EGLint getHeight() const { return mHeight; }
@@ -51,6 +52,8 @@ class SwapChain11 : public SwapChain
Renderer11 *mRenderer;
EGLint mHeight;
EGLint mWidth;
+ EGLint mViewportWidth;
+ EGLint mViewportHeight;
bool mAppCreatedShareHandle;
unsigned int mSwapInterval;
bool mPassThroughResourcesInit;
@@ -66,6 +69,7 @@ class SwapChain11 : public SwapChain
ID3D11Texture2D *mDepthStencilTexture;
ID3D11DepthStencilView *mDepthStencilDSView;
+ ID3D11ShaderResourceView *mDepthStencilSRView;
ID3D11Buffer *mQuadVB;
ID3D11SamplerState *mPassThroughSampler;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
new file mode 100644
index 0000000000..91e7147da6
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -0,0 +1,1937 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
+#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d/d3d11/Blit11.h"
+#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Image11.h"
+#include "libGLESv2/renderer/d3d/TextureD3D.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/ImageIndex.h"
+
+#include "common/utilities.h"
+
+namespace rx
+{
+
+TextureStorage11::SwizzleCacheValue::SwizzleCacheValue()
+ : swizzleRed(GL_NONE), swizzleGreen(GL_NONE), swizzleBlue(GL_NONE), swizzleAlpha(GL_NONE)
+{
+}
+
+TextureStorage11::SwizzleCacheValue::SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha)
+ : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha)
+{
+}
+
+bool TextureStorage11::SwizzleCacheValue::operator==(const SwizzleCacheValue &other) const
+{
+ return swizzleRed == other.swizzleRed &&
+ swizzleGreen == other.swizzleGreen &&
+ swizzleBlue == other.swizzleBlue &&
+ swizzleAlpha == other.swizzleAlpha;
+}
+
+bool TextureStorage11::SwizzleCacheValue::operator!=(const SwizzleCacheValue &other) const
+{
+ return !(*this == other);
+}
+
+TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle)
+ : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle)
+{
+}
+
+bool TextureStorage11::SRVKey::operator==(const SRVKey &rhs) const
+{
+ return baseLevel == rhs.baseLevel &&
+ mipLevels == rhs.mipLevels &&
+ swizzle == rhs.swizzle;
+}
+
+TextureStorage11::SRVCache::~SRVCache()
+{
+ for (size_t i = 0; i < cache.size(); i++)
+ {
+ SafeRelease(cache[i].srv);
+ }
+}
+
+ID3D11ShaderResourceView *TextureStorage11::SRVCache::find(const SRVKey &key) const
+{
+ for (size_t i = 0; i < cache.size(); i++)
+ {
+ if (cache[i].key == key)
+ {
+ return cache[i].srv;
+ }
+ }
+
+ return NULL;
+}
+
+ID3D11ShaderResourceView *TextureStorage11::SRVCache::add(const SRVKey &key, ID3D11ShaderResourceView *srv)
+{
+ SRVPair pair = {key, srv};
+ cache.push_back(pair);
+
+ return srv;
+}
+
+TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
+ : mBindFlags(bindFlags),
+ mTopLevel(0),
+ mMipLevels(0),
+ mTextureFormat(DXGI_FORMAT_UNKNOWN),
+ mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
+ mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
+ mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
+ mTextureWidth(0),
+ mTextureHeight(0),
+ mTextureDepth(0)
+{
+ mRenderer = Renderer11::makeRenderer11(renderer);
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mLevelSRVs[i] = NULL;
+ }
+}
+
+TextureStorage11::~TextureStorage11()
+{
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ SafeRelease(mLevelSRVs[level]);
+ }
+}
+
+TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
+ return static_cast<TextureStorage11*>(storage);
+}
+
+DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, bool renderTarget)
+{
+ UINT bindFlags = 0;
+
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat);
+ 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;
+}
+
+UINT TextureStorage11::getBindFlags() const
+{
+ return mBindFlags;
+}
+
+int TextureStorage11::getTopLevel() const
+{
+ return mTopLevel;
+}
+
+bool TextureStorage11::isRenderTarget() const
+{
+ return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
+}
+
+bool TextureStorage11::isManaged() const
+{
+ return false;
+}
+
+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(int mipLevel, int layerTarget) const
+{
+ UINT index = 0;
+ if (getResource())
+ {
+ index = D3D11CalcSubresource(mipLevel, layerTarget, mMipLevels);
+ }
+ return index;
+}
+
+ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &samplerState)
+{
+ bool swizzleRequired = samplerState.swizzleRequired();
+ bool mipmapping = gl::IsMipmapFiltered(samplerState);
+ unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.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 - samplerState.baseLevel);
+
+ if (swizzleRequired)
+ {
+ verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha);
+ }
+
+ SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired);
+ ID3D11ShaderResourceView *srv = srvCache.find(key);
+
+ if(srv)
+ {
+ return srv;
+ }
+
+ DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat);
+ ID3D11Resource *texture = swizzleRequired ? getSwizzleTexture() : getResource();
+
+ srv = createSRV(samplerState.baseLevel, mipLevels, format, texture);
+
+ return srvCache.add(key, srv);
+}
+
+ID3D11ShaderResourceView *TextureStorage11::getSRVLevel(int mipLevel)
+{
+ if (mipLevel >= 0 && mipLevel < getLevelCount())
+ {
+ if (!mLevelSRVs[mipLevel])
+ {
+ mLevelSRVs[mipLevel] = createSRV(mipLevel, 1, mShaderResourceFormat, getResource());
+ }
+
+ return mLevelSRVs[mipLevel];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
+{
+ SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
+ 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 = getSRVLevel(level);
+ ID3D11RenderTargetView *destRTV = getSwizzleRenderTarget(level);
+
+ gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
+
+ Blit11 *blitter = mRenderer->getBlitter();
+
+ gl::Error error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mSwizzleCache[level] = swizzleTarget;
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel)
+{
+ if (mipLevel >= 0 && static_cast<unsigned int>(mipLevel) < ArraySize(mSwizzleCache))
+ {
+ // The default constructor of SwizzleCacheValue has GL_NONE for all channels which is not a
+ // valid swizzle combination
+ mSwizzleCache[mipLevel] = SwizzleCacheValue();
+ }
+}
+
+void TextureStorage11::invalidateSwizzleCache()
+{
+ for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++)
+ {
+ invalidateSwizzleCacheLevel(mipLevel);
+ }
+}
+
+bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource,
+ int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth)
+{
+ if (srcTexture)
+ {
+ invalidateSwizzleCacheLevel(level);
+
+ gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
+ gl::Box copyArea(xoffset, yoffset, zoffset, width, height, depth);
+
+ 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 = getResource();
+ unsigned int dstSubresource = getSubresourceIndex(level + mTopLevel, layerTarget);
+
+ ASSERT(dstTexture);
+
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
+ if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0))
+ {
+ // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead
+ Blit11 *blitter = mRenderer->getBlitter();
+
+ return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize,
+ dstTexture, dstSubresource, copyArea, texSize,
+ NULL);
+ }
+ else
+ {
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
+
+ D3D11_BOX srcBox;
+ srcBox.left = copyArea.x;
+ srcBox.top = copyArea.y;
+ srcBox.right = copyArea.x + roundUp((unsigned int)width, dxgiFormatInfo.blockWidth);
+ srcBox.bottom = copyArea.y + roundUp((unsigned int)height, dxgiFormatInfo.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 ? NULL : &srcBox);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource,
+ int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth)
+{
+ if (dstTexture)
+ {
+ ID3D11Resource *srcTexture = getResource();
+ unsigned int srcSubresource = getSubresourceIndex(level + mTopLevel, layerTarget);
+
+ ASSERT(srcTexture);
+
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ context->CopySubresourceRegion(dstTexture, dstSubresource, xoffset, yoffset, zoffset,
+ srcTexture, srcSubresource, NULL);
+ return true;
+ }
+
+ return false;
+}
+
+void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
+{
+ if (source && dest)
+ {
+ ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
+ ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
+
+ if (sourceSRV && destRTV)
+ {
+ 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();
+
+ blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL,
+ gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR);
+ }
+ }
+}
+
+void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
+{
+ SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
+ for (unsigned int level = 0; level < mMipLevels; level++)
+ {
+ ASSERT(mSwizzleCache[level] == swizzleTarget);
+ }
+}
+
+TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
+ : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE),
+ mTexture(swapchain->getOffscreenTexture()),
+ mSwizzleTexture(NULL)
+{
+ mTexture->AddRef();
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mAssociatedImages[i] = NULL;
+ mRenderTarget[i] = NULL;
+ mSwizzleRenderTargets[i] = NULL;
+ }
+
+ D3D11_TEXTURE2D_DESC texDesc;
+ mTexture->GetDesc(&texDesc);
+ mMipLevels = texDesc.MipLevels;
+ mTextureFormat = texDesc.Format;
+ mTextureWidth = texDesc.Width;
+ mTextureHeight = texDesc.Height;
+ mTextureDepth = 1;
+
+ ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource();
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srv->GetDesc(&srvDesc);
+ mShaderResourceFormat = srvDesc.Format;
+
+ ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ offscreenRTV->GetDesc(&rtvDesc);
+ mRenderTargetFormat = rtvDesc.Format;
+
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat);
+ mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
+ mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
+ mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
+
+ mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
+
+ initializeSerials(1, 1);
+}
+
+TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
+ : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)),
+ mTexture(NULL),
+ mSwizzleTexture(NULL)
+{
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mAssociatedImages[i] = NULL;
+ mRenderTarget[i] = NULL;
+ mSwizzleRenderTargets[i] = NULL;
+ }
+
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
+ mTextureFormat = formatInfo.texFormat;
+ mShaderResourceFormat = formatInfo.srvFormat;
+ mDepthStencilFormat = formatInfo.dsvFormat;
+ mRenderTargetFormat = formatInfo.rtvFormat;
+ mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
+ mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
+ mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
+
+ // 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 (width > 0 && height > 0)
+ {
+ // adjust size if needed for compressed textures
+ d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = width; // Compressed texture size constraints?
+ desc.Height = height;
+ desc.MipLevels = desc.MipLevels = mRenderer->isLevel9() ? 1 : ((levels > 0) ? (mTopLevel + levels) : 0);
+ desc.ArraySize = 1;
+ desc.Format = mTextureFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
+
+ // this can happen from windows TDR
+ if (d3d11::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ else if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ ERR("Creating image failed.");
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ else
+ {
+ mTexture->GetDesc(&desc);
+ mMipLevels = desc.MipLevels;
+ mTextureWidth = desc.Width;
+ mTextureHeight = desc.Height;
+ mTextureDepth = 1;
+ }
+ }
+
+ initializeSerials(getLevelCount(), 1);
+}
+
+TextureStorage11_2D::~TextureStorage11_2D()
+{
+ for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ if (mAssociatedImages[i] != NULL)
+ {
+ 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 (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ SafeDelete(mRenderTarget[i]);
+ SafeRelease(mSwizzleRenderTargets[i]);
+ }
+}
+
+TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
+ return static_cast<TextureStorage11_2D*>(storage);
+}
+
+void TextureStorage11_2D::associateImage(Image11* image, int level, int layerTarget)
+{
+ 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(int level, int layerTarget, Image11* expectedImage)
+{
+ 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(int level, int layerTarget, Image11* expectedImage)
+{
+ 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] = NULL;
+ }
+ }
+}
+
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
+void TextureStorage11_2D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
+{
+ 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] != NULL && 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 NULL too.
+ mAssociatedImages[level]->recoverFromAssociatedStorage();
+ }
+ }
+ }
+}
+
+ID3D11Resource *TextureStorage11_2D::getResource() const
+{
+ return mTexture;
+}
+
+RenderTarget *TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index)
+{
+ ASSERT(!index.hasLayer());
+
+ int level = index.mipIndex;
+
+ if (level >= 0 && level < getLevelCount())
+ {
+ if (!mRenderTarget[level])
+ {
+ ID3D11ShaderResourceView *srv = getSRVLevel(level);
+ if (!srv)
+ {
+ return NULL;
+ }
+
+ if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mRenderTargetFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = mTopLevel + level;
+
+ ID3D11RenderTargetView *rtv;
+ HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ }
+ else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = mDepthStencilFormat;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ dsvDesc.Texture2D.MipSlice = mTopLevel + level;
+ dsvDesc.Flags = 0;
+
+ ID3D11DepthStencilView *dsv;
+ HRESULT result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ SafeRelease(srv);
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(dsv);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+
+ return mRenderTarget[level];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+ID3D11ShaderResourceView *TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
+{
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
+ srvDesc.Texture2D.MipLevels = mipLevels;
+
+ ID3D11ShaderResourceView *SRV = NULL;
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ ASSERT(SUCCEEDED(result));
+
+ return SRV;
+}
+
+void TextureStorage11_2D::generateMipmaps()
+{
+ // Base level must already be defined
+
+ for (int level = 1; level < getLevelCount(); level++)
+ {
+ invalidateSwizzleCacheLevel(level);
+
+ gl::ImageIndex srcIndex = gl::ImageIndex::Make2D(level - 1);
+ gl::ImageIndex destIndex = gl::ImageIndex::Make2D(level);
+
+ RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex));
+ RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex));
+
+ generateMipmapLayer(source, dest);
+ }
+}
+
+ID3D11Resource *TextureStorage11_2D::getSwizzleTexture()
+{
+ if (!mSwizzleTexture)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = 1;
+ desc.Format = mSwizzleTextureFormat;
+ 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, NULL, &mSwizzleTexture);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+
+ return mSwizzleTexture;
+}
+
+ID3D11RenderTargetView *TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel)
+{
+ if (mipLevel >= 0 && mipLevel < getLevelCount())
+ {
+ if (!mSwizzleRenderTargets[mipLevel])
+ {
+ ID3D11Resource *swizzleTexture = getSwizzleTexture();
+ if (!swizzleTexture)
+ {
+ return NULL;
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mSwizzleRenderTargetFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
+
+ HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+
+ return mSwizzleRenderTargets[mipLevel];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
+ : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
+{
+ mTexture = NULL;
+ mSwizzleTexture = NULL;
+
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ mSwizzleRenderTargets[level] = NULL;
+ for (unsigned int face = 0; face < 6; face++)
+ {
+ mAssociatedImages[face][level] = NULL;
+ mRenderTarget[face][level] = NULL;
+ }
+ }
+
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
+ mTextureFormat = formatInfo.texFormat;
+ mShaderResourceFormat = formatInfo.srvFormat;
+ mDepthStencilFormat = formatInfo.dsvFormat;
+ mRenderTargetFormat = formatInfo.rtvFormat;
+ mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
+ mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
+ mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
+
+ // 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 (size > 0)
+ {
+ // adjust size if needed for compressed textures
+ int height = size;
+ d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel);
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = size;
+ desc.Height = size;
+ desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
+ desc.ArraySize = 6;
+ desc.Format = mTextureFormat;
+ 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;
+
+ HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ ERR("Creating image failed.");
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ else
+ {
+ mTexture->GetDesc(&desc);
+ mMipLevels = desc.MipLevels;
+ mTextureWidth = desc.Width;
+ mTextureHeight = desc.Height;
+ mTextureDepth = 1;
+ }
+ }
+
+ initializeSerials(getLevelCount() * 6, 6);
+}
+
+
+TextureStorage11_Cube::~TextureStorage11_Cube()
+{
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ for (unsigned int face = 0; face < 6; face++)
+ {
+ if (mAssociatedImages[face][level] != NULL)
+ {
+ 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);
+
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ SafeRelease(mSwizzleRenderTargets[level]);
+ for (unsigned int face = 0; face < 6; face++)
+ {
+ SafeDelete(mRenderTarget[face][level]);
+ }
+ }
+}
+
+TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
+ return static_cast<TextureStorage11_Cube*>(storage);
+}
+
+void TextureStorage11_Cube::associateImage(Image11* image, int level, int layerTarget)
+{
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(0 <= layerTarget && layerTarget < 6);
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ if (0 <= layerTarget && layerTarget < 6)
+ {
+ mAssociatedImages[layerTarget][level] = image;
+ }
+ }
+}
+
+bool TextureStorage11_Cube::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
+{
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ if (0 <= layerTarget && layerTarget < 6)
+ {
+ // 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(int level, int layerTarget, Image11* expectedImage)
+{
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(0 <= layerTarget && layerTarget < 6);
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ if (0 <= layerTarget && layerTarget < 6)
+ {
+ ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
+
+ if (mAssociatedImages[layerTarget][level] == expectedImage)
+ {
+ mAssociatedImages[layerTarget][level] = NULL;
+ }
+ }
+ }
+}
+
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
+void TextureStorage11_Cube::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
+{
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(0 <= layerTarget && layerTarget < 6);
+
+ if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
+ {
+ if (0 <= layerTarget && layerTarget < 6)
+ {
+ // No need to let the old Image recover its data, if it is also the incoming Image.
+ if (mAssociatedImages[layerTarget][level] != NULL && 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 NULL too.
+ mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage();
+ }
+ }
+ }
+ }
+}
+
+ID3D11Resource *TextureStorage11_Cube::getResource() const
+{
+ return mTexture;
+}
+
+RenderTarget *TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index)
+{
+ int faceIndex = index.layerIndex;
+ int level = index.mipIndex;
+
+ if (level >= 0 && level < getLevelCount())
+ {
+ if (!mRenderTarget[faceIndex][level])
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result;
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = mShaderResourceFormat;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = faceIndex;
+ srvDesc.Texture2DArray.ArraySize = 1;
+
+ ID3D11ShaderResourceView *srv;
+ result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mRenderTargetFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
+ rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
+ rtvDesc.Texture2DArray.ArraySize = 1;
+
+ ID3D11RenderTargetView *rtv;
+ result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ SafeRelease(srv);
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ SafeRelease(srv);
+ }
+ else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = mDepthStencilFormat;
+ 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(mTexture, &dsvDesc, &dsv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ SafeRelease(srv);
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(dsv);
+ SafeRelease(srv);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+
+ return mRenderTarget[faceIndex][level];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
+{
+ 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 d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format);
+ if (dxgiFormatInfo.componentType == GL_INT || dxgiFormatInfo.componentType == GL_UNSIGNED_INT)
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = 0;
+ srvDesc.Texture2DArray.ArraySize = 6;
+ }
+ else
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ srvDesc.TextureCube.MipLevels = mipLevels;
+ srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
+ }
+
+ ID3D11ShaderResourceView *SRV = NULL;
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ ASSERT(SUCCEEDED(result));
+
+ return SRV;
+}
+
+void TextureStorage11_Cube::generateMipmaps()
+{
+ // Base level must already be defined
+
+ for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+ {
+ for (int level = 1; level < getLevelCount(); level++)
+ {
+ invalidateSwizzleCacheLevel(level);
+
+ gl::ImageIndex srcIndex = gl::ImageIndex::MakeCube(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1);
+ gl::ImageIndex destIndex = gl::ImageIndex::MakeCube(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level);
+
+ RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex));
+ RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex));
+
+ generateMipmapLayer(source, dest);
+ }
+ }
+}
+
+ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture()
+{
+ if (!mSwizzleTexture)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = 6;
+ desc.Format = mSwizzleTextureFormat;
+ 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, NULL, &mSwizzleTexture);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+
+ return mSwizzleTexture;
+}
+
+ID3D11RenderTargetView *TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel)
+{
+ if (mipLevel >= 0 && mipLevel < getLevelCount())
+ {
+ if (!mSwizzleRenderTargets[mipLevel])
+ {
+ ID3D11Resource *swizzleTexture = getSwizzleTexture();
+ if (!swizzleTexture)
+ {
+ return NULL;
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mSwizzleRenderTargetFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Texture2DArray.FirstArraySlice = 0;
+ rtvDesc.Texture2DArray.ArraySize = 6;
+
+ HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+
+ return mSwizzleRenderTargets[mipLevel];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget,
+ GLsizei width, GLsizei height, GLsizei depth, int levels)
+ : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
+{
+ mTexture = NULL;
+ mSwizzleTexture = NULL;
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mAssociatedImages[i] = NULL;
+ mLevelRenderTargets[i] = NULL;
+ mSwizzleRenderTargets[i] = NULL;
+ }
+
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
+ mTextureFormat = formatInfo.texFormat;
+ mShaderResourceFormat = formatInfo.srvFormat;
+ mDepthStencilFormat = formatInfo.dsvFormat;
+ mRenderTargetFormat = formatInfo.rtvFormat;
+ mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
+ mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
+ mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
+
+ // 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 (width > 0 && height > 0 && depth > 0)
+ {
+ // adjust size if needed for compressed textures
+ d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE3D_DESC desc;
+ desc.Width = width;
+ desc.Height = height;
+ desc.Depth = depth;
+ desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
+ desc.Format = mTextureFormat;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture);
+
+ // this can happen from windows TDR
+ if (d3d11::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ else if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ ERR("Creating image failed.");
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ else
+ {
+ mTexture->GetDesc(&desc);
+ mMipLevels = desc.MipLevels;
+ mTextureWidth = desc.Width;
+ mTextureHeight = desc.Height;
+ mTextureDepth = desc.Depth;
+ }
+ }
+
+ initializeSerials(getLevelCount() * depth, depth);
+}
+
+TextureStorage11_3D::~TextureStorage11_3D()
+{
+ for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ if (mAssociatedImages[i] != NULL)
+ {
+ 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]);
+ }
+}
+
+TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage));
+ return static_cast<TextureStorage11_3D*>(storage);
+}
+
+void TextureStorage11_3D::associateImage(Image11* image, int level, int layerTarget)
+{
+ 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(int level, int layerTarget, Image11* expectedImage)
+{
+ 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(int level, int layerTarget, Image11* expectedImage)
+{
+ 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] = NULL;
+ }
+ }
+}
+
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
+void TextureStorage11_3D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
+{
+ 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] != NULL && 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 NULL too.
+ mAssociatedImages[level]->recoverFromAssociatedStorage();
+ }
+ }
+ }
+}
+
+ID3D11Resource *TextureStorage11_3D::getResource() const
+{
+ return mTexture;
+}
+
+ID3D11ShaderResourceView *TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
+{
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+ srvDesc.Texture3D.MostDetailedMip = baseLevel;
+ srvDesc.Texture3D.MipLevels = mipLevels;
+
+ ID3D11ShaderResourceView *SRV = NULL;
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ ASSERT(SUCCEEDED(result));
+
+ return SRV;
+}
+
+RenderTarget *TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index)
+{
+ int mipLevel = index.mipIndex;
+
+ if (mipLevel >= 0 && mipLevel < getLevelCount())
+ {
+ ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN);
+
+ if (!index.hasLayer())
+ {
+ if (!mLevelRenderTargets[mipLevel])
+ {
+ ID3D11ShaderResourceView *srv = getSRVLevel(mipLevel);
+ if (!srv)
+ {
+ return NULL;
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mRenderTargetFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+ rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Texture3D.FirstWSlice = 0;
+ rtvDesc.Texture3D.WSize = -1;
+
+ ID3D11RenderTargetView *rtv;
+ HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ SafeRelease(srv);
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ mLevelRenderTargets[mipLevel] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel));
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ }
+
+ return mLevelRenderTargets[mipLevel];
+ }
+ else
+ {
+ int layer = index.layerIndex;
+
+ LevelLayerKey key(mipLevel, layer);
+ if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result;
+
+ // TODO, what kind of SRV is expected here?
+ ID3D11ShaderResourceView *srv = NULL;
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mRenderTargetFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+ rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Texture3D.FirstWSlice = layer;
+ rtvDesc.Texture3D.WSize = 1;
+
+ ID3D11RenderTargetView *rtv;
+ result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ SafeRelease(srv);
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ mLevelLayerRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ SafeRelease(srv);
+ }
+
+ return mLevelLayerRenderTargets[key];
+ }
+ }
+
+ return NULL;
+}
+
+void TextureStorage11_3D::generateMipmaps()
+{
+ // Base level must already be defined
+
+ for (int level = 1; level < getLevelCount(); level++)
+ {
+ invalidateSwizzleCacheLevel(level);
+
+ gl::ImageIndex srcIndex = gl::ImageIndex::Make3D(level - 1);
+ gl::ImageIndex destIndex = gl::ImageIndex::Make3D(level);
+
+ RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex));
+ RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex));
+
+ generateMipmapLayer(source, dest);
+ }
+}
+
+ID3D11Resource *TextureStorage11_3D::getSwizzleTexture()
+{
+ if (!mSwizzleTexture)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE3D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.Depth = mTextureDepth;
+ desc.MipLevels = mMipLevels;
+ desc.Format = mSwizzleTextureFormat;
+ 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, NULL, &mSwizzleTexture);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture3D*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+
+ return mSwizzleTexture;
+}
+
+ID3D11RenderTargetView *TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel)
+{
+ if (mipLevel >= 0 && mipLevel < getLevelCount())
+ {
+ if (!mSwizzleRenderTargets[mipLevel])
+ {
+ ID3D11Resource *swizzleTexture = getSwizzleTexture();
+ if (!swizzleTexture)
+ {
+ return NULL;
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mSwizzleRenderTargetFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+ rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Texture3D.FirstWSlice = 0;
+ rtvDesc.Texture3D.WSize = -1;
+
+ HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+
+ return mSwizzleRenderTargets[mipLevel];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget,
+ GLsizei width, GLsizei height, GLsizei depth, int levels)
+ : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
+{
+ mTexture = NULL;
+ mSwizzleTexture = NULL;
+
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ mSwizzleRenderTargets[level] = NULL;
+ }
+
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
+ mTextureFormat = formatInfo.texFormat;
+ mShaderResourceFormat = formatInfo.srvFormat;
+ mDepthStencilFormat = formatInfo.dsvFormat;
+ mRenderTargetFormat = formatInfo.rtvFormat;
+ mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
+ mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
+ mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
+
+ // 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 (width > 0 && height > 0 && depth > 0)
+ {
+ // adjust size if needed for compressed textures
+ d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = width;
+ desc.Height = height;
+ desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
+ desc.ArraySize = depth;
+ desc.Format = mTextureFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
+
+ // this can happen from windows TDR
+ if (d3d11::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ else if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ ERR("Creating image failed.");
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ else
+ {
+ mTexture->GetDesc(&desc);
+ mMipLevels = desc.MipLevels;
+ mTextureWidth = desc.Width;
+ mTextureHeight = desc.Height;
+ mTextureDepth = desc.ArraySize;
+ }
+ }
+
+ initializeSerials(getLevelCount() * depth, depth);
+}
+
+TextureStorage11_2DArray::~TextureStorage11_2DArray()
+{
+ for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++)
+ {
+ 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();
+}
+
+TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage));
+ return static_cast<TextureStorage11_2DArray*>(storage);
+}
+
+void TextureStorage11_2DArray::associateImage(Image11* image, int level, int layerTarget)
+{
+ ASSERT(0 <= level && level < getLevelCount());
+
+ if (0 <= level && level < getLevelCount())
+ {
+ LevelLayerKey key(level, layerTarget);
+ mAssociatedImages[key] = image;
+ }
+}
+
+bool TextureStorage11_2DArray::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
+{
+ 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(int level, int layerTarget, Image11* expectedImage)
+{
+ LevelLayerKey key(level, layerTarget);
+
+ bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage));
+ ASSERT(imageAssociationCorrect);
+
+ if (imageAssociationCorrect)
+ {
+ mAssociatedImages[key] = NULL;
+ }
+}
+
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
+void TextureStorage11_2DArray::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
+{
+ LevelLayerKey key(level, layerTarget);
+
+ ASSERT(mAssociatedImages.find(key) != mAssociatedImages.end());
+
+ if (mAssociatedImages.find(key) != mAssociatedImages.end())
+ {
+ if (mAssociatedImages[key] != NULL && 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 NULL too.
+ mAssociatedImages[key]->recoverFromAssociatedStorage();
+ }
+ }
+ }
+}
+
+ID3D11Resource *TextureStorage11_2DArray::getResource() const
+{
+ return mTexture;
+}
+
+ID3D11ShaderResourceView *TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
+{
+ 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;
+
+ ID3D11ShaderResourceView *SRV = NULL;
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ ASSERT(SUCCEEDED(result));
+
+ return SRV;
+}
+
+RenderTarget *TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index)
+{
+ ASSERT(index.hasLayer());
+
+ int mipLevel = index.mipIndex;
+ int layer = index.layerIndex;
+
+ if (mipLevel >= 0 && mipLevel < getLevelCount())
+ {
+ LevelLayerKey key(mipLevel, layer);
+ if (mRenderTargets.find(key) == mRenderTargets.end())
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result;
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = mShaderResourceFormat;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = layer;
+ srvDesc.Texture2DArray.ArraySize = 1;
+
+ ID3D11ShaderResourceView *srv;
+ result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mRenderTargetFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Texture2DArray.FirstArraySlice = layer;
+ rtvDesc.Texture2DArray.ArraySize = 1;
+
+ ID3D11RenderTargetView *rtv;
+ result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ SafeRelease(srv);
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ SafeRelease(srv);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+
+ return mRenderTargets[key];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+void TextureStorage11_2DArray::generateMipmaps()
+{
+ // Base level must already be defined
+
+ for (int level = 0; level < getLevelCount(); level++)
+ {
+ invalidateSwizzleCacheLevel(level);
+ for (unsigned int layer = 0; layer < mTextureDepth; layer++)
+ {
+ gl::ImageIndex sourceIndex = gl::ImageIndex::Make2DArray(level - 1, layer);
+ gl::ImageIndex destIndex = gl::ImageIndex::Make2DArray(level, layer);
+
+ RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(sourceIndex));
+ RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex));
+
+ generateMipmapLayer(source, dest);
+ }
+ }
+}
+
+ID3D11Resource *TextureStorage11_2DArray::getSwizzleTexture()
+{
+ if (!mSwizzleTexture)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = mTextureDepth;
+ desc.Format = mSwizzleTextureFormat;
+ 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, NULL, &mSwizzleTexture);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+
+ return mSwizzleTexture;
+}
+
+ID3D11RenderTargetView *TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel)
+{
+ if (mipLevel >= 0 && mipLevel < getLevelCount())
+ {
+ if (!mSwizzleRenderTargets[mipLevel])
+ {
+ ID3D11Resource *swizzleTexture = getSwizzleTexture();
+ if (!swizzleTexture)
+ {
+ return NULL;
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mSwizzleRenderTargetFormat;
+ 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]);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+
+ return mSwizzleRenderTargets[mipLevel];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h
new file mode 100644
index 0000000000..9d63b2699d
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h
@@ -0,0 +1,313 @@
+//
+// 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 LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
+#define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
+
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/Error.h"
+#include "libGLESv2/renderer/d3d/TextureStorage.h"
+
+#include <map>
+
+namespace gl
+{
+struct ImageIndex;
+}
+
+namespace rx
+{
+class RenderTarget;
+class RenderTarget11;
+class Renderer;
+class Renderer11;
+class SwapChain11;
+class Image11;
+
+class TextureStorage11 : public TextureStorage
+{
+ public:
+ virtual ~TextureStorage11();
+
+ static TextureStorage11 *makeTextureStorage11(TextureStorage *storage);
+
+ static DWORD GetTextureBindFlags(GLenum internalFormat, bool renderTarget);
+
+ UINT getBindFlags() const;
+
+ virtual ID3D11Resource *getResource() const = 0;
+ virtual ID3D11ShaderResourceView *getSRV(const gl::SamplerState &samplerState);
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0;
+
+ virtual void generateMipmaps() = 0;
+
+ virtual int getTopLevel() const;
+ virtual bool isRenderTarget() const;
+ virtual bool isManaged() const;
+ virtual int getLevelCount() const;
+ UINT getSubresourceIndex(int mipLevel, int layerTarget) const;
+
+ gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
+ void invalidateSwizzleCacheLevel(int mipLevel);
+ void invalidateSwizzleCache();
+
+ bool updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource, int level,
+ int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth);
+
+ bool copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, int level,
+ int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth);
+
+ virtual void associateImage(Image11* image, int level, int layerTarget) = 0;
+ virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage) = 0;
+ virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) = 0;
+ virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) = 0;
+
+ protected:
+ TextureStorage11(Renderer *renderer, UINT bindFlags);
+ void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest);
+ int getLevelWidth(int mipLevel) const;
+ int getLevelHeight(int mipLevel) const;
+ int getLevelDepth(int mipLevel) const;
+
+ virtual ID3D11Resource *getSwizzleTexture() = 0;
+ virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel) = 0;
+ ID3D11ShaderResourceView *getSRVLevel(int mipLevel);
+
+ virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) = 0;
+
+ void verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
+
+ Renderer11 *mRenderer;
+ int mTopLevel;
+ unsigned int mMipLevels;
+
+ DXGI_FORMAT mTextureFormat;
+ DXGI_FORMAT mShaderResourceFormat;
+ DXGI_FORMAT mRenderTargetFormat;
+ DXGI_FORMAT mDepthStencilFormat;
+ DXGI_FORMAT mSwizzleTextureFormat;
+ DXGI_FORMAT mSwizzleShaderResourceFormat;
+ DXGI_FORMAT mSwizzleRenderTargetFormat;
+ unsigned int mTextureWidth;
+ unsigned int mTextureHeight;
+ unsigned int mTextureDepth;
+
+ struct SwizzleCacheValue
+ {
+ GLenum swizzleRed;
+ GLenum swizzleGreen;
+ GLenum swizzleBlue;
+ GLenum swizzleAlpha;
+
+ SwizzleCacheValue();
+ SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha);
+
+ bool operator ==(const SwizzleCacheValue &other) const;
+ bool operator !=(const SwizzleCacheValue &other) const;
+ };
+ SwizzleCacheValue mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ struct SRVKey
+ {
+ SRVKey(int baseLevel = 0, int mipLevels = 0, bool swizzle = false);
+
+ bool operator==(const SRVKey &rhs) const;
+
+ int baseLevel;
+ int mipLevels;
+ bool swizzle;
+ };
+
+ struct SRVPair
+ {
+ SRVKey key;
+ ID3D11ShaderResourceView *srv;
+ };
+
+ struct SRVCache
+ {
+ ~SRVCache();
+
+ ID3D11ShaderResourceView *find(const SRVKey &key) const;
+ ID3D11ShaderResourceView *add(const SRVKey &key, ID3D11ShaderResourceView *srv);
+
+ std::vector<SRVPair> cache;
+ };
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage11);
+
+ const UINT mBindFlags;
+
+ SRVCache srvCache;
+ ID3D11ShaderResourceView *mLevelSRVs[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureStorage11_2D : public TextureStorage11
+{
+ public:
+ TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain);
+ TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
+ virtual ~TextureStorage11_2D();
+
+ static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage);
+
+ virtual ID3D11Resource *getResource() const;
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
+
+ virtual void generateMipmaps();
+
+ virtual void associateImage(Image11* image, int level, int layerTarget);
+ virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage);
+ virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage);
+ virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage);
+
+ protected:
+ virtual ID3D11Resource *getSwizzleTexture();
+ virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D);
+
+ virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture);
+
+ ID3D11Texture2D *mTexture;
+ RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ ID3D11Texture2D *mSwizzleTexture;
+ ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureStorage11_Cube : public TextureStorage11
+{
+ public:
+ TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels);
+ virtual ~TextureStorage11_Cube();
+
+ static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage);
+
+ virtual ID3D11Resource *getResource() const;
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
+
+ virtual void generateMipmaps();
+
+ virtual void associateImage(Image11* image, int level, int layerTarget);
+ virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage);
+ virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage);
+ virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage);
+
+ protected:
+ virtual ID3D11Resource *getSwizzleTexture();
+ virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube);
+
+ virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture);
+
+ ID3D11Texture2D *mTexture;
+ RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ ID3D11Texture2D *mSwizzleTexture;
+ ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+
+ Image11 *mAssociatedImages[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureStorage11_3D : public TextureStorage11
+{
+ public:
+ TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget,
+ GLsizei width, GLsizei height, GLsizei depth, int levels);
+ virtual ~TextureStorage11_3D();
+
+ static TextureStorage11_3D *makeTextureStorage11_3D(TextureStorage *storage);
+
+ virtual ID3D11Resource *getResource() const;
+
+ // Handles both layer and non-layer RTs
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
+
+ virtual void generateMipmaps();
+
+ virtual void associateImage(Image11* image, int level, int layerTarget);
+ virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage);
+ virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage);
+ virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage);
+
+ protected:
+ virtual ID3D11Resource *getSwizzleTexture();
+ virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage11_3D);
+
+ virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture);
+
+ 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(Renderer *renderer, GLenum internalformat, bool renderTarget,
+ GLsizei width, GLsizei height, GLsizei depth, int levels);
+ virtual ~TextureStorage11_2DArray();
+
+ static TextureStorage11_2DArray *makeTextureStorage11_2DArray(TextureStorage *storage);
+
+ virtual ID3D11Resource *getResource() const;
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
+
+ virtual void generateMipmaps();
+
+ virtual void associateImage(Image11* image, int level, int layerTarget);
+ virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage);
+ virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage);
+ virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage);
+
+ protected:
+ virtual ID3D11Resource *getSwizzleTexture();
+ virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2DArray);
+
+ virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture);
+
+ 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 // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h
new file mode 100644
index 0000000000..590cb9f05a
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h
@@ -0,0 +1,42 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexArray11.h: Defines the rx::VertexArray11 class which implements rx::VertexArrayImpl.
+
+#ifndef LIBGLESV2_RENDERER_VERTEXARRAY11_H_
+#define LIBGLESV2_RENDERER_VERTEXARRAY11_H_
+
+#include "libGLESv2/renderer/VertexArrayImpl.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+class Renderer11;
+
+class VertexArray11 : public VertexArrayImpl
+{
+ public:
+ VertexArray11(rx::Renderer11 *renderer)
+ : VertexArrayImpl(),
+ mRenderer(renderer)
+ {
+ }
+ virtual ~VertexArray11() { }
+
+ virtual void setElementArrayBuffer(const gl::Buffer *buffer) { }
+ virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { }
+ virtual void setAttributeDivisor(size_t idx, GLuint divisor) { }
+ virtual void enableAttribute(size_t idx, bool enabledState) { }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VertexArray11);
+
+ rx::Renderer11 *mRenderer;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_VERTEXARRAY11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp
new file mode 100644
index 0000000000..9bc5b1d2d1
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp
@@ -0,0 +1,209 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/VertexAttribute.h"
+
+namespace rx
+{
+
+VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer)
+{
+ mBuffer = NULL;
+ mBufferSize = 0;
+ mDynamicUsage = false;
+}
+
+VertexBuffer11::~VertexBuffer11()
+{
+ 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);
+ }
+ }
+
+ mBufferSize = size;
+ mDynamicUsage = dynamicUsage;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer));
+ return static_cast<VertexBuffer11*>(vetexBuffer);
+}
+
+gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+ GLint start, GLsizei count, GLsizei instances, unsigned int offset)
+{
+ if (!mBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+ }
+
+ gl::Buffer *buffer = attrib.buffer.get();
+ int inputStride = ComputeVertexAttributeStride(attrib);
+ 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);
+ }
+
+ uint8_t *output = reinterpret_cast<uint8_t*>(mappedResource.pData) + offset;
+
+ const uint8_t *input = NULL;
+ if (attrib.enabled)
+ {
+ if (buffer)
+ {
+ Buffer11 *storage = Buffer11::makeBuffer11(buffer->getImplementation());
+ input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset);
+ }
+ else
+ {
+ input = static_cast<const uint8_t*>(attrib.pointer);
+ }
+ }
+ else
+ {
+ input = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
+ }
+
+ if (instances == 0 || attrib.divisor == 0)
+ {
+ input += inputStride * start;
+ }
+
+ gl::VertexFormat vertexFormat(attrib, currentValue.Type);
+ const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat);
+ ASSERT(vertexFormatInfo.copyFunction != NULL);
+ vertexFormatInfo.copyFunction(input, inputStride, count, output);
+
+ dxContext->Unmap(mBuffer, 0);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
+ GLsizei instances, unsigned int *outSpaceRequired) const
+{
+ unsigned int elementCount = 0;
+ if (attrib.enabled)
+ {
+ if (instances == 0 || attrib.divisor == 0)
+ {
+ elementCount = count;
+ }
+ else
+ {
+ // Round up to divisor, if possible
+ elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
+ }
+
+ gl::VertexFormat vertexFormat(attrib);
+ const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat);
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat);
+ unsigned int elementSize = dxgiFormatInfo.pixelBytes;
+ if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
+ {
+ if (outSpaceRequired)
+ {
+ *outSpaceRequired = elementSize * elementCount;
+ }
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
+ }
+ }
+ else
+ {
+ const unsigned int elementSize = 4;
+ if (outSpaceRequired)
+ {
+ *outSpaceRequired = elementSize * 4;
+ }
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+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;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h
new file mode 100644
index 0000000000..0e10da1df8
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h
@@ -0,0 +1,52 @@
+//
+// 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 LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
+#define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
+
+#include "libGLESv2/renderer/d3d/VertexBuffer.h"
+
+namespace rx
+{
+class Renderer11;
+
+class VertexBuffer11 : public VertexBuffer
+{
+ public:
+ explicit VertexBuffer11(rx::Renderer11 *const renderer);
+ virtual ~VertexBuffer11();
+
+ virtual gl::Error initialize(unsigned int size, bool dynamicUsage);
+
+ static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer);
+
+ virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+ GLint start, GLsizei count, GLsizei instances, unsigned int offset);
+
+ virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
+ unsigned int *outSpaceRequired) const;
+
+ virtual unsigned int getBufferSize() const;
+ virtual gl::Error setBufferSize(unsigned int size);
+ virtual gl::Error discard();
+
+ ID3D11Buffer *getBuffer() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VertexBuffer11);
+
+ rx::Renderer11 *const mRenderer;
+
+ ID3D11Buffer *mBuffer;
+ unsigned int mBufferSize;
+ bool mDynamicUsage;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
new file mode 100644
index 0000000000..c07828757d
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
@@ -0,0 +1,1075 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/renderer/generatemip.h"
+#include "libGLESv2/renderer/loadimage.h"
+#include "libGLESv2/renderer/copyimage.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/copyvertex.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+typedef std::map<DXGI_FORMAT, GLenum> DXGIToESFormatMap;
+
+inline void AddDXGIToESEntry(DXGIToESFormatMap *map, DXGI_FORMAT key, GLenum value)
+{
+ map->insert(std::make_pair(key, value));
+}
+
+static DXGIToESFormatMap BuildDXGIToESFormatMap()
+{
+ DXGIToESFormatMap map;
+
+ AddDXGIToESEntry(&map, DXGI_FORMAT_UNKNOWN, GL_NONE);
+
+ AddDXGIToESEntry(&map, DXGI_FORMAT_A8_UNORM, GL_ALPHA8_EXT);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UNORM, GL_R8);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UNORM, GL_RG8);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM, GL_RGBA8);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_B8G8R8A8_UNORM, GL_BGRA8_EXT);
+
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SNORM, GL_R8_SNORM);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SNORM, GL_RG8_SNORM);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SNORM, GL_RGBA8_SNORM);
+
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UINT, GL_R8UI);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UINT, GL_R16UI);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32_UINT, GL_R32UI);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UINT, GL_RG8UI);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_UINT, GL_RG16UI);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_UINT, GL_RG32UI);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_UINT, GL_RGB32UI);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UINT, GL_RGBA8UI);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_UINT, GL_RGBA16UI);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_UINT, GL_RGBA32UI);
+
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SINT, GL_R8I);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R16_SINT, GL_R16I);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32_SINT, GL_R32I);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SINT, GL_RG8I);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_SINT, GL_RG16I);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_SINT, GL_RG32I);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_SINT, GL_RGB32I);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SINT, GL_RGBA8I);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_SINT, GL_RGBA16I);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_SINT, GL_RGBA32I);
+
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UNORM, GL_RGB10_A2);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UINT, GL_RGB10_A2UI);
+
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R16_FLOAT, GL_R16F);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_FLOAT, GL_RG16F);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F);
+
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT, GL_R32F);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_FLOAT, GL_RG32F);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_FLOAT, GL_RGB32F);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, GL_RGBA32F);
+
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, GL_RGB9_E5);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R11G11B10_FLOAT, GL_R11F_G11F_B10F);
+
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R16_TYPELESS, GL_DEPTH_COMPONENT16);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UNORM, GL_DEPTH_COMPONENT16);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_D16_UNORM, GL_DEPTH_COMPONENT16);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R24G8_TYPELESS, GL_DEPTH24_STENCIL8_OES);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, GL_DEPTH24_STENCIL8_OES);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_OES);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32G8X24_TYPELESS, GL_DEPTH32F_STENCIL8);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, GL_DEPTH32F_STENCIL8);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_R32_TYPELESS, GL_DEPTH_COMPONENT32F);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT, GL_DEPTH_COMPONENT32F);
+
+ AddDXGIToESEntry(&map, DXGI_FORMAT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
+ AddDXGIToESEntry(&map, DXGI_FORMAT_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
+
+ return map;
+}
+
+struct D3D11FastCopyFormat
+{
+ GLenum destFormat;
+ GLenum destType;
+ ColorCopyFunction copyFunction;
+
+ D3D11FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction)
+ : destFormat(destFormat), destType(destType), copyFunction(copyFunction)
+ { }
+
+ bool operator<(const D3D11FastCopyFormat& other) const
+ {
+ return memcmp(this, &other, sizeof(D3D11FastCopyFormat)) < 0;
+ }
+};
+
+typedef std::multimap<DXGI_FORMAT, D3D11FastCopyFormat> D3D11FastCopyMap;
+
+static D3D11FastCopyMap BuildFastCopyMap()
+{
+ D3D11FastCopyMap map;
+
+ map.insert(std::make_pair(DXGI_FORMAT_B8G8R8A8_UNORM, D3D11FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8)));
+
+ return map;
+}
+
+struct DXGIDepthStencilInfo
+{
+ unsigned int depthBits;
+ unsigned int depthOffset;
+ unsigned int stencilBits;
+ unsigned int stencilOffset;
+};
+
+typedef std::map<DXGI_FORMAT, DXGIDepthStencilInfo> DepthStencilInfoMap;
+typedef std::pair<DXGI_FORMAT, DXGIDepthStencilInfo> DepthStencilInfoPair;
+
+static inline void InsertDXGIDepthStencilInfo(DepthStencilInfoMap *map, DXGI_FORMAT format, unsigned int depthBits,
+ unsigned int depthOffset, unsigned int stencilBits, unsigned int stencilOffset)
+{
+ DXGIDepthStencilInfo info;
+ info.depthBits = depthBits;
+ info.depthOffset = depthOffset;
+ info.stencilBits = stencilBits;
+ info.stencilOffset = stencilOffset;
+
+ map->insert(std::make_pair(format, info));
+}
+
+static DepthStencilInfoMap BuildDepthStencilInfoMap()
+{
+ DepthStencilInfoMap map;
+
+ InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_TYPELESS, 16, 0, 0, 0);
+ InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_UNORM, 16, 0, 0, 0);
+ InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D16_UNORM, 16, 0, 0, 0);
+
+ InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24G8_TYPELESS, 24, 0, 8, 24);
+ InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 24, 0, 8, 24);
+ InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 24, 0, 8, 24);
+
+ InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_TYPELESS, 32, 0, 0, 0);
+ InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0);
+ InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT, 32, 0, 0, 0);
+
+ InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 32, 0, 8, 32);
+ InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 32, 0, 8, 32);
+ InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 32, 0, 8, 32);
+
+ return map;
+}
+
+typedef std::map<DXGI_FORMAT, DXGIFormat> DXGIFormatInfoMap;
+
+DXGIFormat::DXGIFormat()
+ : pixelBytes(0),
+ blockWidth(0),
+ blockHeight(0),
+ depthBits(0),
+ depthOffset(0),
+ stencilBits(0),
+ stencilOffset(0),
+ internalFormat(GL_NONE),
+ componentType(GL_NONE),
+ mipGenerationFunction(NULL),
+ colorReadFunction(NULL),
+ fastCopyFunctions()
+{
+}
+
+ColorCopyFunction DXGIFormat::getFastCopyFunction(GLenum format, GLenum type) const
+{
+ FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type));
+ return (iter != fastCopyFunctions.end()) ? iter->second : NULL;
+}
+
+void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight,
+ GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc)
+{
+ DXGIFormat info;
+ info.pixelBytes = pixelBits / 8;
+ info.blockWidth = blockWidth;
+ info.blockHeight = blockHeight;
+
+ static const DepthStencilInfoMap dsInfoMap = BuildDepthStencilInfoMap();
+ DepthStencilInfoMap::const_iterator dsInfoIter = dsInfoMap.find(dxgiFormat);
+ if (dsInfoIter != dsInfoMap.end())
+ {
+ info.depthBits = dsInfoIter->second.depthBits;
+ info.depthOffset = dsInfoIter->second.depthOffset;
+ info.stencilBits = dsInfoIter->second.stencilBits;
+ info.stencilOffset = dsInfoIter->second.stencilOffset;
+ }
+ else
+ {
+ info.depthBits = 0;
+ info.depthOffset = 0;
+ info.stencilBits = 0;
+ info.stencilOffset = 0;
+ }
+
+ static const DXGIToESFormatMap dxgiToESMap = BuildDXGIToESFormatMap();
+ DXGIToESFormatMap::const_iterator dxgiToESIter = dxgiToESMap.find(dxgiFormat);
+ info.internalFormat = (dxgiToESIter != dxgiToESMap.end()) ? dxgiToESIter->second : GL_NONE;
+
+ info.componentType = componentType;
+
+ info.mipGenerationFunction = mipFunc;
+ info.colorReadFunction = readFunc;
+
+ static const D3D11FastCopyMap fastCopyMap = BuildFastCopyMap();
+ std::pair<D3D11FastCopyMap::const_iterator, D3D11FastCopyMap::const_iterator> fastCopyIter = fastCopyMap.equal_range(dxgiFormat);
+ for (D3D11FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++)
+ {
+ info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction));
+ }
+
+ map->insert(std::make_pair(dxgiFormat, info));
+}
+
+// A map to determine the pixel size and mipmap generation function of a given DXGI format
+static DXGIFormatInfoMap BuildDXGIFormatInfoMap()
+{
+ DXGIFormatInfoMap map;
+
+ // | DXGI format |S |W |H |Component Type | Mip generation function | Color read function
+ AddDXGIFormat(&map, DXGI_FORMAT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL);
+
+ AddDXGIFormat(&map, DXGI_FORMAT_A8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<A8>, ReadColor<A8, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8>, ReadColor<R8, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8G8>, ReadColor<R8G8, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8G8B8A8>, ReadColor<R8G8B8A8, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8G8B8A8>, ReadColor<R8G8B8A8, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat>);
+
+ AddDXGIFormat(&map, DXGI_FORMAT_R8_SNORM, 8, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip<R8S>, ReadColor<R8S, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip<R8G8S>, ReadColor<R8G8S, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip<R8G8B8A8S>, ReadColor<R8G8B8A8S, GLfloat>);
+
+ AddDXGIFormat(&map, DXGI_FORMAT_R8_UINT, 8, 1, 1, GL_UNSIGNED_INT, GenerateMip<R8>, ReadColor<R8, GLuint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip<R16>, ReadColor<R16, GLuint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32>, ReadColor<R32, GLuint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip<R8G8>, ReadColor<R8G8, GLuint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R16G16>, ReadColor<R16G16, GLuint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32G32_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32G32>, ReadColor<R32G32, GLuint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_UINT, 96, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32G32B32>, ReadColor<R32G32B32, GLuint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R8G8B8A8>, ReadColor<R8G8B8A8, GLuint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip<R16G16B16A16>, ReadColor<R16G16B16A16, GLuint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_UINT, 128, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32G32B32A32>, ReadColor<R32G32B32A32, GLuint>);
+
+ AddDXGIFormat(&map, DXGI_FORMAT_R8_SINT, 8, 1, 1, GL_INT, GenerateMip<R8S>, ReadColor<R8S, GLint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16_SINT, 16, 1, 1, GL_INT, GenerateMip<R16S>, ReadColor<R16S, GLint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32_SINT, 32, 1, 1, GL_INT, GenerateMip<R32S>, ReadColor<R32S, GLint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SINT, 16, 1, 1, GL_INT, GenerateMip<R8G8S>, ReadColor<R8G8S, GLint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SINT, 32, 1, 1, GL_INT, GenerateMip<R16G16S>, ReadColor<R16G16S, GLint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32G32_SINT, 64, 1, 1, GL_INT, GenerateMip<R32G32S>, ReadColor<R32G32S, GLint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_SINT, 96, 1, 1, GL_INT, GenerateMip<R32G32B32S>, ReadColor<R32G32B32S, GLint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SINT, 32, 1, 1, GL_INT, GenerateMip<R8G8B8A8S>, ReadColor<R8G8B8A8S, GLint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SINT, 64, 1, 1, GL_INT, GenerateMip<R16G16B16A16S>, ReadColor<R16G16B16A16S, GLint>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_SINT, 128, 1, 1, GL_INT, GenerateMip<R32G32B32A32S>, ReadColor<R32G32B32A32S, GLint>);
+
+ AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R10G10B10A2>, ReadColor<R10G10B10A2, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R10G10B10A2>, ReadColor<R10G10B10A2, GLuint>);
+
+ AddDXGIFormat(&map, DXGI_FORMAT_R16_FLOAT, 16, 1, 1, GL_FLOAT, GenerateMip<R16F>, ReadColor<R16F, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16G16_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>);
+
+ AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip<R32F>, ReadColor<R32F, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32G32_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_FLOAT, 96, 1, 1, GL_FLOAT, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 128, 1, 1, GL_FLOAT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>);
+
+ AddDXGIFormat(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 32, 1, 1, GL_FLOAT, GenerateMip<R9G9B9E5>, ReadColor<R9G9B9E5, GLfloat>);
+ AddDXGIFormat(&map, DXGI_FORMAT_R11G11B10_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip<R11G11B10F>, ReadColor<R11G11B10F, GLfloat>);
+
+ AddDXGIFormat(&map, DXGI_FORMAT_R16_TYPELESS, 16, 1, 1, GL_NONE, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_D16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_R24G8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 32, 1, 1, GL_UNSIGNED_INT, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 64, 1, 1, GL_UNSIGNED_INT, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_R32_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT, 32, 1, 1, GL_FLOAT, NULL, NULL);
+
+ AddDXGIFormat(&map, DXGI_FORMAT_BC1_UNORM, 64, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_BC2_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_BC3_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL);
+
+ // Useful formats for vertex buffers
+ AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UNORM, 64, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL);
+ AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SNORM, 64, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL);
+
+ return map;
+}
+
+const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format)
+{
+ static const DXGIFormatInfoMap infoMap = BuildDXGIFormatInfoMap();
+ DXGIFormatInfoMap::const_iterator iter = infoMap.find(format);
+ if (iter != infoMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ static DXGIFormat defaultInfo;
+ return defaultInfo;
+ }
+}
+
+struct SwizzleSizeType
+{
+ size_t maxComponentSize;
+ GLenum componentType;
+
+ SwizzleSizeType()
+ : maxComponentSize(0), componentType(GL_NONE)
+ { }
+
+ SwizzleSizeType(size_t maxComponentSize, GLenum componentType)
+ : maxComponentSize(maxComponentSize), componentType(componentType)
+ { }
+
+ bool operator<(const SwizzleSizeType& other) const
+ {
+ return (maxComponentSize != other.maxComponentSize) ? (maxComponentSize < other.maxComponentSize)
+ : (componentType < other.componentType);
+ }
+};
+
+struct SwizzleFormatInfo
+{
+ DXGI_FORMAT mTexFormat;
+ DXGI_FORMAT mSRVFormat;
+ DXGI_FORMAT mRTVFormat;
+
+ SwizzleFormatInfo()
+ : mTexFormat(DXGI_FORMAT_UNKNOWN), mSRVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN)
+ { }
+
+ SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat)
+ : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat)
+ { }
+};
+
+typedef std::map<SwizzleSizeType, SwizzleFormatInfo> SwizzleInfoMap;
+typedef std::pair<SwizzleSizeType, SwizzleFormatInfo> SwizzleInfoPair;
+
+static SwizzleInfoMap BuildSwizzleInfoMap()
+{
+ SwizzleInfoMap map;
+
+ map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM )));
+ map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM)));
+ map.insert(SwizzleInfoPair(SwizzleSizeType(24, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT)));
+ map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT)));
+
+ map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_SIGNED_NORMALIZED ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM )));
+
+ map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT)));
+ map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT)));
+
+ map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT )));
+ map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT )));
+ map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT )));
+
+ map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT )));
+ map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT )));
+ map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT )));
+
+ return map;
+}
+
+typedef std::pair<GLint, InitializeTextureDataFunction> InternalFormatInitializerPair;
+typedef std::map<GLint, InitializeTextureDataFunction> InternalFormatInitializerMap;
+
+static InternalFormatInitializerMap BuildInternalFormatInitializerMap()
+{
+ InternalFormatInitializerMap map;
+
+ map.insert(InternalFormatInitializerPair(GL_RGB8, Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF> ));
+ map.insert(InternalFormatInitializerPair(GL_RGB565, Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF> ));
+ map.insert(InternalFormatInitializerPair(GL_SRGB8, Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF> ));
+ map.insert(InternalFormatInitializerPair(GL_RGB16F, Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>));
+ map.insert(InternalFormatInitializerPair(GL_RGB32F, Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>));
+ map.insert(InternalFormatInitializerPair(GL_RGB8UI, Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01> ));
+ map.insert(InternalFormatInitializerPair(GL_RGB8I, Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01> ));
+ map.insert(InternalFormatInitializerPair(GL_RGB16UI, Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001> ));
+ map.insert(InternalFormatInitializerPair(GL_RGB16I, Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001> ));
+ map.insert(InternalFormatInitializerPair(GL_RGB32UI, Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001> ));
+ map.insert(InternalFormatInitializerPair(GL_RGB32I, Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001> ));
+
+ return map;
+}
+
+// ES3 image loading functions vary based on the internal format and data type given,
+// this map type determines the loading function from the internal format and type supplied
+// to glTex*Image*D and the destination DXGI_FORMAT. Source formats and types are taken from
+// Tables 3.2 and 3.3 of the ES 3 spec.
+typedef std::pair<GLenum, LoadImageFunction> TypeLoadFunctionPair;
+typedef std::map<GLenum, std::vector<TypeLoadFunctionPair> > D3D11LoadFunctionMap;
+
+static 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();
+}
+
+static 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();
+}
+
+// A helper function to insert data into the D3D11LoadFunctionMap with fewer characters.
+static inline void InsertLoadFunction(D3D11LoadFunctionMap *map, GLenum internalFormat, GLenum type,
+ LoadImageFunction loadFunc)
+{
+ (*map)[internalFormat].push_back(TypeLoadFunctionPair(type, loadFunc));
+}
+
+D3D11LoadFunctionMap BuildD3D11LoadFunctionMap()
+{
+ D3D11LoadFunctionMap map;
+
+ // | Internal format | Type | Load function |
+ InsertLoadFunction(&map, GL_RGBA8, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> );
+ InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> );
+ InsertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> );
+ InsertLoadFunction(&map, GL_SRGB8_ALPHA8, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> );
+ InsertLoadFunction(&map, GL_RGBA8_SNORM, GL_BYTE, LoadToNative<GLbyte, 4> );
+ InsertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4, LoadRGBA4ToRGBA8 );
+ InsertLoadFunction(&map, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative<GLuint, 1> );
+ InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, LoadRGB5A1ToRGBA8 );
+ InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_INT_2_10_10_10_REV, LoadRGB10A2ToRGBA8 );
+ InsertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT, LoadToNative<GLhalf, 4> );
+ InsertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT_OES, LoadToNative<GLhalf, 4> );
+ InsertLoadFunction(&map, GL_RGBA32F, GL_FLOAT, LoadToNative<GLfloat, 4> );
+ InsertLoadFunction(&map, GL_RGBA16F, GL_FLOAT, Load32FTo16F<4> );
+ InsertLoadFunction(&map, GL_RGBA8UI, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> );
+ InsertLoadFunction(&map, GL_RGBA8I, GL_BYTE, LoadToNative<GLbyte, 4> );
+ InsertLoadFunction(&map, GL_RGBA16UI, GL_UNSIGNED_SHORT, LoadToNative<GLushort, 4> );
+ InsertLoadFunction(&map, GL_RGBA16I, GL_SHORT, LoadToNative<GLshort, 4> );
+ InsertLoadFunction(&map, GL_RGBA32UI, GL_UNSIGNED_INT, LoadToNative<GLuint, 4> );
+ InsertLoadFunction(&map, GL_RGBA32I, GL_INT, LoadToNative<GLint, 4> );
+ InsertLoadFunction(&map, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative<GLuint, 1> );
+ InsertLoadFunction(&map, GL_RGB8, GL_UNSIGNED_BYTE, LoadToNative3To4<GLubyte, 0xFF> );
+ InsertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_BYTE, LoadToNative3To4<GLubyte, 0xFF> );
+ InsertLoadFunction(&map, GL_SRGB8, GL_UNSIGNED_BYTE, LoadToNative3To4<GLubyte, 0xFF> );
+ InsertLoadFunction(&map, GL_RGB8_SNORM, GL_BYTE, LoadToNative3To4<GLbyte, 0x7F> );
+ InsertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, LoadR5G6B5ToRGBA8 );
+ InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_UNSIGNED_INT_10F_11F_11F_REV, LoadToNative<GLuint, 1> );
+ InsertLoadFunction(&map, GL_RGB9_E5, GL_UNSIGNED_INT_5_9_9_9_REV, LoadToNative<GLuint, 1> );
+ InsertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT, LoadToNative3To4<GLhalf, gl::Float16One>);
+ InsertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT_OES, LoadToNative3To4<GLhalf, gl::Float16One>);
+ InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT, LoadRGB16FToRG11B10F );
+ InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT_OES, LoadRGB16FToRG11B10F );
+ InsertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT, LoadRGB16FToRGB9E5 );
+ InsertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT_OES, LoadRGB16FToRGB9E5 );
+ InsertLoadFunction(&map, GL_RGB32F, GL_FLOAT, LoadToNative3To4<GLfloat, gl::Float32One>);
+ InsertLoadFunction(&map, GL_RGB16F, GL_FLOAT, LoadRGB32FToRGBA16F );
+ InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_FLOAT, LoadRGB32FToRG11B10F );
+ InsertLoadFunction(&map, GL_RGB9_E5, GL_FLOAT, LoadRGB32FToRGB9E5 );
+ InsertLoadFunction(&map, GL_RGB8UI, GL_UNSIGNED_BYTE, LoadToNative3To4<GLubyte, 0x01> );
+ InsertLoadFunction(&map, GL_RGB8I, GL_BYTE, LoadToNative3To4<GLbyte, 0x01> );
+ InsertLoadFunction(&map, GL_RGB16UI, GL_UNSIGNED_SHORT, LoadToNative3To4<GLushort, 0x0001> );
+ InsertLoadFunction(&map, GL_RGB16I, GL_SHORT, LoadToNative3To4<GLshort, 0x0001> );
+ InsertLoadFunction(&map, GL_RGB32UI, GL_UNSIGNED_INT, LoadToNative3To4<GLuint, 0x00000001> );
+ InsertLoadFunction(&map, GL_RGB32I, GL_INT, LoadToNative3To4<GLint, 0x00000001> );
+ InsertLoadFunction(&map, GL_RG8, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 2> );
+ InsertLoadFunction(&map, GL_RG8_SNORM, GL_BYTE, LoadToNative<GLbyte, 2> );
+ InsertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT, LoadToNative<GLhalf, 2> );
+ InsertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT_OES, LoadToNative<GLhalf, 2> );
+ InsertLoadFunction(&map, GL_RG32F, GL_FLOAT, LoadToNative<GLfloat, 2> );
+ InsertLoadFunction(&map, GL_RG16F, GL_FLOAT, Load32FTo16F<2> );
+ InsertLoadFunction(&map, GL_RG8UI, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 2> );
+ InsertLoadFunction(&map, GL_RG8I, GL_BYTE, LoadToNative<GLbyte, 2> );
+ InsertLoadFunction(&map, GL_RG16UI, GL_UNSIGNED_SHORT, LoadToNative<GLushort, 2> );
+ InsertLoadFunction(&map, GL_RG16I, GL_SHORT, LoadToNative<GLshort, 2> );
+ InsertLoadFunction(&map, GL_RG32UI, GL_UNSIGNED_INT, LoadToNative<GLuint, 2> );
+ InsertLoadFunction(&map, GL_RG32I, GL_INT, LoadToNative<GLint, 2> );
+ InsertLoadFunction(&map, GL_R8, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 1> );
+ InsertLoadFunction(&map, GL_R8_SNORM, GL_BYTE, LoadToNative<GLbyte, 1> );
+ InsertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT, LoadToNative<GLhalf, 1> );
+ InsertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT_OES, LoadToNative<GLhalf, 1> );
+ InsertLoadFunction(&map, GL_R32F, GL_FLOAT, LoadToNative<GLfloat, 1> );
+ InsertLoadFunction(&map, GL_R16F, GL_FLOAT, Load32FTo16F<1> );
+ InsertLoadFunction(&map, GL_R8UI, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 1> );
+ InsertLoadFunction(&map, GL_R8I, GL_BYTE, LoadToNative<GLbyte, 1> );
+ InsertLoadFunction(&map, GL_R16UI, GL_UNSIGNED_SHORT, LoadToNative<GLushort, 1> );
+ InsertLoadFunction(&map, GL_R16I, GL_SHORT, LoadToNative<GLshort, 1> );
+ InsertLoadFunction(&map, GL_R32UI, GL_UNSIGNED_INT, LoadToNative<GLuint, 1> );
+ InsertLoadFunction(&map, GL_R32I, GL_INT, LoadToNative<GLint, 1> );
+ InsertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, LoadToNative<GLushort, 1> );
+ InsertLoadFunction(&map, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, LoadR32ToR24G8 );
+ InsertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_INT, LoadR32ToR16 );
+ InsertLoadFunction(&map, GL_DEPTH_COMPONENT32F, GL_FLOAT, LoadToNative<GLfloat, 1> );
+ InsertLoadFunction(&map, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, LoadR32ToR24G8 );
+ InsertLoadFunction(&map, GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, LoadToNative<GLuint, 2> );
+
+ // Unsized formats
+ // Load functions are unreachable because they are converted to sized internal formats based on
+ // the format and type before loading takes place.
+ InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_BYTE, UnreachableLoadFunction );
+ InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, UnreachableLoadFunction );
+ InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, UnreachableLoadFunction );
+ InsertLoadFunction(&map, GL_RGB, GL_UNSIGNED_BYTE, UnreachableLoadFunction );
+ InsertLoadFunction(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, UnreachableLoadFunction );
+ InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction );
+ InsertLoadFunction(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, UnreachableLoadFunction );
+ InsertLoadFunction(&map, GL_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction );
+
+ // From GL_OES_texture_float
+ InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, LoadLA32FToRGBA32F );
+ InsertLoadFunction(&map, GL_LUMINANCE, GL_FLOAT, LoadL32FToRGBA32F );
+ InsertLoadFunction(&map, GL_ALPHA, GL_FLOAT, LoadA32FToRGBA32F );
+
+ // From GL_OES_texture_half_float
+ InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, LoadLA16FToRGBA16F );
+ InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F );
+ InsertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT, LoadL16FToRGBA16F );
+ InsertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F );
+ InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT, LoadA16FToRGBA16F );
+ InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F );
+
+ // From GL_EXT_texture_storage
+ InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadA8ToRGBA8 );
+ InsertLoadFunction(&map, GL_LUMINANCE8_EXT, GL_UNSIGNED_BYTE, LoadL8ToRGBA8 );
+ InsertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadLA8ToRGBA8 );
+ InsertLoadFunction(&map, GL_ALPHA32F_EXT, GL_FLOAT, LoadA32FToRGBA32F );
+ InsertLoadFunction(&map, GL_LUMINANCE32F_EXT, GL_FLOAT, LoadL32FToRGBA32F );
+ InsertLoadFunction(&map, GL_LUMINANCE_ALPHA32F_EXT, GL_FLOAT, LoadLA32FToRGBA32F );
+ InsertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT, LoadA16FToRGBA16F );
+ InsertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F );
+ InsertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT, LoadL16FToRGBA16F );
+ InsertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F );
+ InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT, LoadLA16FToRGBA16F );
+ InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F );
+
+ // From GL_ANGLE_depth_texture
+ InsertLoadFunction(&map, GL_DEPTH_COMPONENT32_OES, GL_UNSIGNED_INT, LoadR32ToR24G8 );
+
+ // From GL_EXT_texture_format_BGRA8888
+ InsertLoadFunction(&map, GL_BGRA8_EXT, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> );
+ InsertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, LoadRGBA4ToRGBA8 );
+ InsertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> );
+ InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, LoadRGB5A1ToRGBA8 );
+ InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> );
+
+ // Compressed formats
+ // From ES 3.0.1 spec, table 3.16
+ // | Internal format | Type | Load function |
+ InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction );
+ InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction );
+ InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction );
+ InsertLoadFunction(&map, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction );
+ InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction );
+ InsertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction );
+ InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction );
+ InsertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction );
+ InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction );
+ InsertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction );
+ InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction );
+
+ // From GL_EXT_texture_compression_dxt1
+ InsertLoadFunction(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>);
+ InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>);
+
+ // From GL_ANGLE_texture_compression_dxt3
+ InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>);
+
+ // From GL_ANGLE_texture_compression_dxt5
+ InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>);
+
+ return map;
+}
+
+// For sized GL internal formats, there is only one corresponding D3D11 format. This map type allows
+// querying for the DXGI texture formats to use for textures, SRVs, RTVs and DSVs given a GL internal
+// format.
+typedef std::map<GLenum, TextureFormat> D3D11ES3FormatMap;
+
+TextureFormat::TextureFormat()
+ : texFormat(DXGI_FORMAT_UNKNOWN),
+ srvFormat(DXGI_FORMAT_UNKNOWN),
+ rtvFormat(DXGI_FORMAT_UNKNOWN),
+ dsvFormat(DXGI_FORMAT_UNKNOWN),
+ renderFormat(DXGI_FORMAT_UNKNOWN),
+ swizzleTexFormat(DXGI_FORMAT_UNKNOWN),
+ swizzleSRVFormat(DXGI_FORMAT_UNKNOWN),
+ swizzleRTVFormat(DXGI_FORMAT_UNKNOWN),
+ dataInitializerFunction(NULL),
+ loadFunctions()
+{
+}
+
+static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat,
+ DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat)
+{
+ TextureFormat info;
+ info.texFormat = texFormat;
+ info.srvFormat = srvFormat;
+ info.rtvFormat = rtvFormat;
+ info.dsvFormat = dsvFormat;
+
+ // Given a GL internal format, the renderFormat is the DSV format if it is depth- or stencil-renderable,
+ // the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise.
+ if (dsvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ info.renderFormat = dsvFormat;
+ }
+ else if (rtvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ info.renderFormat = rtvFormat;
+ }
+ else if (texFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ info.renderFormat = texFormat;
+ }
+ else
+ {
+ info.renderFormat = DXGI_FORMAT_UNKNOWN;
+ }
+
+ // Compute the swizzle formats
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ if (internalFormat != GL_NONE && formatInfo.pixelBytes > 0)
+ {
+ if (formatInfo.componentCount != 4 || texFormat == DXGI_FORMAT_UNKNOWN ||
+ srvFormat == DXGI_FORMAT_UNKNOWN || rtvFormat == DXGI_FORMAT_UNKNOWN)
+ {
+ // Get the maximum sized component
+ unsigned int maxBits = 1;
+ if (formatInfo.compressed)
+ {
+ unsigned int compressedBitsPerBlock = formatInfo.pixelBytes * 8;
+ unsigned int blockSize = formatInfo.compressedBlockWidth * formatInfo.compressedBlockHeight;
+ maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits);
+ }
+ else
+ {
+ maxBits = std::max(maxBits, formatInfo.alphaBits);
+ maxBits = std::max(maxBits, formatInfo.redBits);
+ maxBits = std::max(maxBits, formatInfo.greenBits);
+ maxBits = std::max(maxBits, formatInfo.blueBits);
+ maxBits = std::max(maxBits, formatInfo.luminanceBits);
+ maxBits = std::max(maxBits, formatInfo.depthBits);
+ }
+
+ maxBits = roundUp(maxBits, 8U);
+
+ static const SwizzleInfoMap swizzleMap = BuildSwizzleInfoMap();
+ SwizzleInfoMap::const_iterator swizzleIter = swizzleMap.find(SwizzleSizeType(maxBits, formatInfo.componentType));
+ ASSERT(swizzleIter != swizzleMap.end());
+
+ const SwizzleFormatInfo &swizzleInfo = swizzleIter->second;
+ info.swizzleTexFormat = swizzleInfo.mTexFormat;
+ info.swizzleSRVFormat = swizzleInfo.mSRVFormat;
+ info.swizzleRTVFormat = swizzleInfo.mRTVFormat;
+ }
+ else
+ {
+ // The original texture format is suitable for swizzle operations
+ info.swizzleTexFormat = texFormat;
+ info.swizzleSRVFormat = srvFormat;
+ info.swizzleRTVFormat = rtvFormat;
+ }
+ }
+ else
+ {
+ // Not possible to swizzle with this texture format since it is either unsized or GL_NONE
+ info.swizzleTexFormat = DXGI_FORMAT_UNKNOWN;
+ info.swizzleSRVFormat = DXGI_FORMAT_UNKNOWN;
+ info.swizzleRTVFormat = DXGI_FORMAT_UNKNOWN;
+ }
+
+ // Check if there is an initialization function for this texture format
+ static const InternalFormatInitializerMap initializerMap = BuildInternalFormatInitializerMap();
+ InternalFormatInitializerMap::const_iterator initializerIter = initializerMap.find(internalFormat);
+ info.dataInitializerFunction = (initializerIter != initializerMap.end()) ? initializerIter->second : NULL;
+
+ // Gather all the load functions for this internal format
+ static const D3D11LoadFunctionMap loadFunctions = BuildD3D11LoadFunctionMap();
+ D3D11LoadFunctionMap::const_iterator loadFunctionIter = loadFunctions.find(internalFormat);
+ if (loadFunctionIter != loadFunctions.end())
+ {
+ const std::vector<TypeLoadFunctionPair> &loadFunctionVector = loadFunctionIter->second;
+ for (size_t i = 0; i < loadFunctionVector.size(); i++)
+ {
+ GLenum type = loadFunctionVector[i].first;
+ LoadImageFunction function = loadFunctionVector[i].second;
+ info.loadFunctions.insert(std::make_pair(type, function));
+ }
+ }
+
+ map->insert(std::make_pair(internalFormat, info));
+}
+
+static D3D11ES3FormatMap BuildD3D11FormatMap()
+{
+ D3D11ES3FormatMap map;
+
+ // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format |
+ InsertD3D11FormatInfo(&map, GL_NONE, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_R8, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RG8, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RG8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB8, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB565, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGBA4, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB5_A1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGBA8, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGBA8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB10_A2, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB10_A2UI, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_SRGB8, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_SRGB8_ALPHA8, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_R16F, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RG16F, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB16F, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGBA16F, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_R32F, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RG32F, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB32F, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGBA32F, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_R11F_G11F_B10F, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB9_E5, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_R8I, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_R8UI, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_R16I, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_R16UI, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_R32I, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_R32UI, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RG8I, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RG8UI, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RG16I, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RG16UI, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RG32I, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RG32UI, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB8I, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB8UI, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB16I, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB16UI, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB32I, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB32UI, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGBA8I, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGBA8UI, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGBA16I, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGBA16UI, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGBA32I, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGBA32UI, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN);
+
+ // Unsized formats, TODO: Are types of float and half float allowed for the unsized types? Would it change the DXGI format?
+ InsertD3D11FormatInfo(&map, GL_ALPHA, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_LUMINANCE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGB, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_RGBA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_BGRA_EXT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN);
+
+ // From GL_EXT_texture_storage
+ // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format |
+ InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN );
+ InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN );
+ InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN );
+ InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN );
+ InsertD3D11FormatInfo(&map, GL_ALPHA16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN );
+ InsertD3D11FormatInfo(&map, GL_LUMINANCE16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN );
+ InsertD3D11FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN );
+ InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN );
+ InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN );
+ InsertD3D11FormatInfo(&map, GL_BGRA8_EXT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN );
+ InsertD3D11FormatInfo(&map, GL_BGRA4_ANGLEX, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN );
+ InsertD3D11FormatInfo(&map, GL_BGR5_A1_ANGLEX, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN );
+
+ // Depth stencil formats
+ InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT16, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM );
+ InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT24, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT );
+ InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32F, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT );
+ InsertD3D11FormatInfo(&map, GL_DEPTH24_STENCIL8, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT );
+ InsertD3D11FormatInfo(&map, GL_DEPTH32F_STENCIL8, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT_S8X24_UINT);
+ InsertD3D11FormatInfo(&map, GL_STENCIL_INDEX8, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_X24_TYPELESS_G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT );
+
+ // From GL_ANGLE_depth_texture
+ // Since D3D11 doesn't have a D32_UNORM format, use D24S8 which has comparable precision and matches the ES3 format.
+ InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT);
+
+ // Compressed formats, From ES 3.0.1 spec, table 3.16
+ // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format |
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+
+ // From GL_EXT_texture_compression_dxt1
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+
+ // From GL_ANGLE_texture_compression_dxt3
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+
+ // From GL_ANGLE_texture_compression_dxt5
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+
+ return map;
+}
+
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat)
+{
+ static const D3D11ES3FormatMap formatMap = BuildD3D11FormatMap();
+ D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat);
+ if (iter != formatMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ static const TextureFormat defaultInfo;
+ return defaultInfo;
+ }
+}
+
+typedef std::map<gl::VertexFormat, VertexFormat> D3D11VertexFormatInfoMap;
+typedef std::pair<gl::VertexFormat, VertexFormat> D3D11VertexFormatPair;
+
+VertexFormat::VertexFormat()
+ : conversionType(VERTEX_CONVERT_NONE),
+ nativeFormat(DXGI_FORMAT_UNKNOWN),
+ copyFunction(NULL)
+{
+}
+
+static void AddVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLboolean normalized, GLuint componentCount,
+ VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction)
+{
+ gl::VertexFormat inputFormat(inputType, normalized, componentCount, false);
+
+ VertexFormat info;
+ info.conversionType = conversionType;
+ info.nativeFormat = nativeFormat;
+ info.copyFunction = copyFunction;
+
+ map->insert(D3D11VertexFormatPair(inputFormat, info));
+}
+
+static void AddIntegerVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLuint componentCount,
+ VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction)
+{
+ gl::VertexFormat inputFormat(inputType, GL_FALSE, componentCount, true);
+
+ VertexFormat info;
+ info.conversionType = conversionType;
+ info.nativeFormat = nativeFormat;
+ info.copyFunction = copyFunction;
+
+ map->insert(D3D11VertexFormatPair(inputFormat, info));
+}
+
+static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap()
+{
+ D3D11VertexFormatInfoMap map;
+
+ // TODO: column legend
+
+ //
+ // Float formats
+ //
+
+ // GL_BYTE -- un-normalized
+ AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 0>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 0>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 1>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 0>);
+
+ // GL_BYTE -- normalized
+ AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData<GLbyte, 1, 0>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, &CopyNativeVertexData<GLbyte, 2, 0>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 3, INT8_MAX>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 4, 0>);
+
+ // GL_UNSIGNED_BYTE -- un-normalized
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 1>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 0>);
+
+ // GL_UNSIGNED_BYTE -- normalized
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData<GLubyte, 1, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, &CopyNativeVertexData<GLubyte, 2, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 3, UINT8_MAX>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 4, 0>);
+
+ // GL_SHORT -- un-normalized
+ AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 0>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 0>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 1>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 0>);
+
+ // GL_SHORT -- normalized
+ AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData<GLshort, 1, 0>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData<GLshort, 2, 0>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 3, INT16_MAX>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 4, 0>);
+
+ // GL_UNSIGNED_SHORT -- un-normalized
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 1>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 0>);
+
+ // GL_UNSIGNED_SHORT -- normalized
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData<GLushort, 1, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, &CopyNativeVertexData<GLushort, 2, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 3, UINT16_MAX>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 4, 0>);
+
+ // GL_INT -- un-normalized
+ AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 0>);
+ AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 0>);
+ AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 0>);
+ AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 0>);
+
+ // GL_INT -- normalized
+ AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLint, 1, true>);
+ AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLint, 2, true>);
+ AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLint, 3, true>);
+ AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLint, 4, true>);
+
+ // GL_UNSIGNED_INT -- un-normalized
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData<GLuint, 1, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, &CopyNativeVertexData<GLuint, 2, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, &CopyNativeVertexData<GLuint, 3, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, &CopyNativeVertexData<GLuint, 4, 0>);
+
+ // GL_UNSIGNED_INT -- normalized
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLuint, 1, true>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLuint, 2, true>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLuint, 3, true>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLuint, 4, true>);
+
+ // GL_FIXED
+ AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1>);
+ AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<2>);
+ AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &Copy32FixedTo32FVertexData<3>);
+ AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &Copy32FixedTo32FVertexData<4>);
+
+ // GL_HALF_FLOAT
+ AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData<GLhalf, 1, 0>);
+ AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, &CopyNativeVertexData<GLhalf, 2, 0>);
+ AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 3, gl::Float16One>);
+ AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 4, 0>);
+
+ // GL_FLOAT
+ AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData<GLfloat, 1, 0>);
+ AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData<GLfloat, 2, 0>);
+ AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, &CopyNativeVertexData<GLfloat, 3, 0>);
+ AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyNativeVertexData<GLfloat, 4, 0>);
+
+ // GL_INT_2_10_10_10_REV
+ AddVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<true, false, true>);
+ AddVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<true, true, true>);
+
+ // GL_UNSIGNED_INT_2_10_10_10_REV
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<false, false, true>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, &CopyNativeVertexData<GLuint, 1, 0>);
+
+ //
+ // Integer Formats
+ //
+
+ // GL_BYTE
+ AddIntegerVertexFormatInfo(&map, GL_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 1>);
+ AddIntegerVertexFormatInfo(&map, GL_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 0>);
+
+ // GL_UNSIGNED_BYTE
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 1>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 0>);
+
+ // GL_SHORT
+ AddIntegerVertexFormatInfo(&map, GL_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 3, 1>);
+ AddIntegerVertexFormatInfo(&map, GL_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 0>);
+
+ // GL_UNSIGNED_SHORT
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 1>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 0>);
+
+ // GL_INT
+ AddIntegerVertexFormatInfo(&map, GL_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 0>);
+
+ // GL_UNSIGNED_INT
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLuint, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLuint, 2, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLuint, 3, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLuint, 4, 0>);
+
+ // GL_INT_2_10_10_10_REV
+ AddIntegerVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyXYZ10W2ToXYZW32FVertexData<true, true, false>);
+
+ // GL_UNSIGNED_INT_2_10_10_10_REV
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData<GLuint, 1, 0>);
+
+ return map;
+}
+
+const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat)
+{
+ static const D3D11VertexFormatInfoMap vertexFormatMap = BuildD3D11VertexFormatInfoMap();
+
+ D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMap.find(vertexFormat);
+ if (iter != vertexFormatMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ static const VertexFormat defaultInfo;
+ return defaultInfo;
+ }
+}
+
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h
new file mode 100644
index 0000000000..ea11aaa74c
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h
@@ -0,0 +1,84 @@
+//
+// 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 LIBGLESV2_RENDERER_FORMATUTILS11_H_
+#define LIBGLESV2_RENDERER_FORMATUTILS11_H_
+
+#include "libGLESv2/formatutils.h"
+
+#include <map>
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+typedef std::map<std::pair<GLenum, GLenum>, ColorCopyFunction> FastCopyFunctionMap;
+
+struct DXGIFormat
+{
+ DXGIFormat();
+
+ GLuint pixelBytes;
+ GLuint blockWidth;
+ GLuint blockHeight;
+
+ GLuint depthBits;
+ GLuint depthOffset;
+ GLuint stencilBits;
+ GLuint stencilOffset;
+
+ GLenum internalFormat;
+ GLenum componentType;
+
+ MipGenerationFunction mipGenerationFunction;
+ ColorReadFunction colorReadFunction;
+
+ FastCopyFunctionMap fastCopyFunctions;
+ ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const;
+};
+const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format);
+
+struct TextureFormat
+{
+ TextureFormat();
+
+ DXGI_FORMAT texFormat;
+ DXGI_FORMAT srvFormat;
+ DXGI_FORMAT rtvFormat;
+ DXGI_FORMAT dsvFormat;
+ DXGI_FORMAT renderFormat;
+
+ DXGI_FORMAT swizzleTexFormat;
+ DXGI_FORMAT swizzleSRVFormat;
+ DXGI_FORMAT swizzleRTVFormat;
+
+ InitializeTextureDataFunction dataInitializerFunction;
+
+ typedef std::map<GLenum, LoadImageFunction> LoadFunctionMap;
+ LoadFunctionMap loadFunctions;
+};
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat);
+
+struct VertexFormat
+{
+ VertexFormat();
+
+ VertexConversionType conversionType;
+ DXGI_FORMAT nativeFormat;
+ VertexCopyFunction copyFunction;
+};
+const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat);
+
+}
+
+}
+
+#endif // LIBGLESV2_RENDERER_FORMATUTILS11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
new file mode 100644
index 0000000000..2af97e73f0
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -0,0 +1,1216 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/Framebuffer.h"
+
+#include "common/debug.h"
+
+#include <algorithm>
+
+#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY
+# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2
+#endif
+#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT
+# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1
+#endif
+#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT
+# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4
+#endif
+#ifndef D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT
+# define D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT 65535
+#endif
+#ifndef D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT
+# define D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT 1048575
+#endif
+#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION
+# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512
+#endif
+#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION
+# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096
+#endif
+#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION
+# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048
+#endif
+#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
+# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256
+#endif
+#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION
+# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096
+#endif
+#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION
+# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384
+#endif
+#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION
+# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048
+#endif
+#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
+# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048
+#endif
+#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP
+# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32
+#endif
+#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP
+# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32
+#endif
+#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT
+# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32
+#endif
+#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT
+# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32
+#endif
+#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT
+# define D3D10_1_SO_BUFFER_SLOT_COUNT 4
+#endif
+#ifndef D3D11_SO_BUFFER_SLOT_COUNT
+# define D3D11_SO_BUFFER_SLOT_COUNT 4
+#endif
+#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
+# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14
+#endif
+#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT
+# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16
+#endif
+#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
+# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8
+#endif
+#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
+# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7
+#endif
+#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT
+# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096
+#endif
+#ifndef D3D11_PS_INPUT_REGISTER_COUNT
+# define D3D11_PS_INPUT_REGISTER_COUNT 32
+#endif
+#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT
+# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32
+#endif
+#ifndef D3D11_VS_OUTPUT_REGISTER_COUNT
+# define D3D11_VS_OUTPUT_REGISTER_COUNT 32
+#endif
+
+namespace rx
+{
+
+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;
+}
+
+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;
+ default: UNREACHABLE(); return D3D11_QUERY_EVENT;
+ }
+}
+
+}
+
+
+namespace d3d11_gl
+{
+
+static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, ID3D11Device *device)
+{
+ gl::TextureCaps textureCaps;
+
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat);
+
+ UINT formatSupport;
+ if (SUCCEEDED(device->CheckFormatSupport(formatInfo.texFormat, &formatSupport)))
+ {
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+ {
+ textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0);
+ }
+ else
+ {
+ textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0) &&
+ ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) != 0) &&
+ ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D) != 0);
+ }
+ }
+
+ if (SUCCEEDED(device->CheckFormatSupport(formatInfo.renderFormat, &formatSupport)) &&
+ ((formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET) != 0))
+ {
+ for (size_t sampleCount = 1; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount++)
+ {
+ UINT qualityCount = 0;
+ if (SUCCEEDED(device->CheckMultisampleQualityLevels(formatInfo.renderFormat, sampleCount, &qualityCount)) &&
+ qualityCount > 0)
+ {
+ textureCaps.sampleCounts.insert(sampleCount);
+ }
+ }
+ }
+
+ textureCaps.filterable = SUCCEEDED(device->CheckFormatSupport(formatInfo.srvFormat, &formatSupport)) &&
+ ((formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) != 0;
+ textureCaps.renderable = (SUCCEEDED(device->CheckFormatSupport(formatInfo.rtvFormat, &formatSupport)) &&
+ ((formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) != 0) ||
+ (SUCCEEDED(device->CheckFormatSupport(formatInfo.dsvFormat, &formatSupport)) &&
+ ((formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) != 0));
+
+ return textureCaps;
+}
+
+static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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 true; // Provided that mipmaps & wrap modes are not used
+
+ default: UNREACHABLE(); return false;
+ }
+}
+
+static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery
+
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout
+
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static 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)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)
+{
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout
+
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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 D3D9 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;
+ }
+}
+
+static 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
+ META_ASSERT(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32);
+ META_ASSERT(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32);
+
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static 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
+ META_ASSERT(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32);
+ META_ASSERT(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32);
+
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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::VSSetConstantBuffers
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1: return 255;
+
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+static size_t GetReservedVertexUniformBuffers()
+{
+ // Reserve one buffer for the application uniforms, and one for driver uniforms
+ return 2;
+}
+
+static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers();
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers();
+
+ // Uniform blocks not supported in D3D9 feature levels
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1: return 0;
+
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+static size_t GetReservedVertexOutputVectors()
+{
+ // We potentially reserve varyings for gl_Position, dx_Position, gl_FragCoord and gl_PointSize
+ return 4;
+}
+
+static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT);
+
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
+
+ case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
+
+ // Use D3D9 SM3 and SM2 limits
+ case D3D_FEATURE_LEVEL_9_3: return 10 - GetReservedVertexOutputVectors();
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors();
+
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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 in D3D9 feature levels 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;
+ }
+}
+
+static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+static size_t GetReservedPixelUniformBuffers()
+{
+ // Reserve one buffer for the application uniforms, and one for driver uniforms
+ return 2;
+}
+
+static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers();
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers();
+
+ // Uniform blocks not supported in D3D9 feature levels
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1: return 0;
+
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
+
+ // Use D3D9 SM3 and SM2 limits
+ case D3D_FEATURE_LEVEL_9_3: return 10 - GetReservedVertexOutputVectors();
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors();
+
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static 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)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static size_t GetMaximumStreamOutputInterleavedComponenets(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ 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;
+ }
+}
+
+static size_t GetMaximumStreamOutputSeparateCompeonents(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if _MSC_VER >= 1700
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponenets(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;
+ }
+}
+
+void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions)
+{
+ 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, device);
+ textureCapsMap->insert(*internalFormat, textureCaps);
+
+ maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
+
+ if (gl::GetInternalFormatInfo(*internalFormat).compressed)
+ {
+ caps->compressedTextureFormats.push_back(*internalFormat);
+ }
+ }
+
+ D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel();
+
+ // GL core feature limits
+ caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
+ caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel);
+ caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel);
+ caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel);
+ caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel);
+
+ // Unimplemented, set to minimum required
+ caps->maxLODBias = 2.0f;
+
+ // No specific limits on render target size, maximum 2D texture size is equivalent
+ caps->maxRenderbufferSize = caps->max2DTextureSize;
+
+ // Maximum draw buffers and color attachments are the same, max color attachments could eventually be
+ // increased to 16
+ caps->maxDrawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel);
+ caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel);
+
+ // D3D11 has the same limit for viewport width and height
+ caps->maxViewportWidth = GetMaximumViewportSize(featureLevel);
+ caps->maxViewportHeight = caps->maxViewportWidth;
+
+ // Choose a reasonable maximum, enforced in the shader.
+ caps->minAliasedPointSize = 1.0f;
+ caps->maxAliasedPointSize = 1024.0f;
+
+ // Wide lines not supported
+ caps->minAliasedLineWidth = 1.0f;
+ caps->maxAliasedLineWidth = 1.0f;
+
+ // Primitive count limits
+ caps->maxElementsIndices = GetMaximumDrawIndexedIndexCount(featureLevel);
+ caps->maxElementsVertices = GetMaximumDrawVertexCount(featureLevel);
+
+ // Program and shader binary formats (no supported shader binary formats)
+ caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
+
+ // We do not wait for server fence objects internally, so report a max timeout of zero.
+ caps->maxServerWaitTimeout = 0;
+
+ // Vertex shader limits
+ caps->maxVertexAttributes = GetMaximumVertexInputSlots(featureLevel);
+ caps->maxVertexUniformComponents = GetMaximumVertexUniformVectors(featureLevel) * 4;
+ caps->maxVertexUniformVectors = GetMaximumVertexUniformVectors(featureLevel);
+ caps->maxVertexUniformBlocks = GetMaximumVertexUniformBlocks(featureLevel);
+ caps->maxVertexOutputComponents = GetMaximumVertexOutputVectors(featureLevel) * 4;
+ caps->maxVertexTextureImageUnits = GetMaximumVertexTextureUnits(featureLevel);
+
+ // Fragment shader limits
+ caps->maxFragmentUniformComponents = GetMaximumPixelUniformVectors(featureLevel) * 4;
+ caps->maxFragmentUniformVectors = GetMaximumPixelUniformVectors(featureLevel);
+ caps->maxFragmentUniformBlocks = GetMaximumPixelUniformBlocks(featureLevel);
+ caps->maxFragmentInputComponents = GetMaximumPixelInputVectors(featureLevel) * 4;
+ caps->maxTextureImageUnits = GetMaximumPixelTextureUnits(featureLevel);
+ caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel);
+ caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel);
+
+ // Aggregate shader limits
+ caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks;
+ caps->maxUniformBlockSize = GetMaximumConstantBufferSize(featureLevel);
+
+ // Setting a large alignment forces uniform buffers to bind with zero offset
+ caps->uniformBufferOffsetAlignment = static_cast<GLuint>(std::numeric_limits<GLint>::max());
+
+ 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 = GetMaximumVertexOutputVectors(featureLevel) * 4;
+ caps->maxVaryingVectors = GetMaximumVertexOutputVectors(featureLevel);
+ caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
+
+ // Transform feedback limits
+ caps->maxTransformFeedbackInterleavedComponents = GetMaximumStreamOutputInterleavedComponenets(featureLevel);
+ caps->maxTransformFeedbackSeparateAttributes = GetMaximumStreamOutputBuffers(featureLevel);
+ caps->maxTransformFeedbackSeparateComponents = GetMaximumStreamOutputSeparateCompeonents(featureLevel);
+
+ // GL extension support
+ extensions->setTextureExtensionSupport(*textureCapsMap);
+ extensions->elementIndexUint = true;
+ extensions->packedDepthStencil = 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->robustness = true;
+ extensions->blendMinMax = true;
+ extensions->framebufferBlit = true;
+ extensions->framebufferMultisample = true;
+ extensions->maxSamples = maxSamples;
+ extensions->instancedArrays = GetInstancingSupport(featureLevel);
+ extensions->packReverseRowOrder = true;
+ extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel);
+ extensions->shaderTextureLOD = true;
+ extensions->fragDepth = true;
+ extensions->textureUsage = true; // This could be false since it has no effect in D3D11
+ extensions->translatedShaderSource = true;
+}
+
+}
+
+namespace d3d11
+{
+
+void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
+{
+ const DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(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, GLuint width, GLuint height, GLuint depth,
+ GLuint mipLevels, std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData,
+ std::vector< std::vector<BYTE> > *outData)
+{
+ const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat);
+ ASSERT(d3dFormatInfo.dataInitializerFunction != NULL);
+
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(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;
+ }
+}
+
+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(__MINGW32__) && defined(_DEBUG)
+ return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name);
+#else
+ return S_OK;
+#endif
+}
+
+RenderTarget11 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
+{
+ RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
+ return RenderTarget11::makeRenderTarget11(renderTarget);
+}
+
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h
new file mode 100644
index 0000000000..4c05eb9256
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h
@@ -0,0 +1,185 @@
+//
+// 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 LIBGLESV2_RENDERER_RENDERER11_UTILS_H
+#define LIBGLESV2_RENDERER_RENDERER11_UTILS_H
+
+#include "libGLESv2/angletypes.h"
+#include "libGLESv2/Caps.h"
+
+#include <vector>
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace rx
+{
+class RenderTarget11;
+
+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);
+
+D3D11_QUERY ConvertQueryType(GLenum queryType);
+
+}
+
+namespace d3d11_gl
+{
+
+void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions);
+
+}
+
+namespace d3d11
+{
+
+void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset);
+
+void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth,
+ GLuint mipLevels, std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData,
+ std::vector< std::vector<BYTE> > *outData);
+
+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;
+ }
+}
+
+template <unsigned int N>
+inline ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name)
+{
+ ID3D11VertexShader *vs = NULL;
+ HRESULT result = device->CreateVertexShader(byteCode, N, NULL, &vs);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(SUCCEEDED(result));
+ SetDebugName(vs, name);
+ return vs;
+}
+
+template <unsigned int N>
+inline ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name)
+{
+ ID3D11GeometryShader *gs = NULL;
+ HRESULT result = device->CreateGeometryShader(byteCode, N, NULL, &gs);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(SUCCEEDED(result));
+ SetDebugName(gs, name);
+ return gs;
+}
+
+template <unsigned int N>
+inline ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name)
+{
+ ID3D11PixelShader *ps = NULL;
+ HRESULT result = device->CreatePixelShader(byteCode, N, NULL, &ps);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(SUCCEEDED(result));
+ SetDebugName(ps, name);
+ return ps;
+}
+
+// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to
+// represent an entire buffer.
+template <class T>
+inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value)
+{
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+
+ memcpy(mappedResource.pData, &value, sizeof(T));
+
+ context->Unmap(constantBuffer, 0);
+}
+
+RenderTarget11 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment);
+
+}
+
+}
+
+#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl
new file mode 100644
index 0000000000..20e6623a30
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl
@@ -0,0 +1,76 @@
+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;
+}
+
+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 = 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/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl
new file mode 100644
index 0000000000..b4cf38076e
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl
@@ -0,0 +1,106 @@
+// 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;
+#if SM4
+ float4 color4 : SV_TARGET4;
+ float4 color5 : SV_TARGET5;
+ float4 color6 : SV_TARGET6;
+ float4 color7 : SV_TARGET7;
+#endif
+};
+
+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;
+#if SM4
+ outColor.color4 = inColor;
+ outColor.color5 = inColor;
+ outColor.color6 = inColor;
+ outColor.color7 = inColor;
+#endif
+ 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/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
new file mode 100644
index 0000000000..8671c39fb7
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
@@ -0,0 +1,111 @@
+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;
+}
+
+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);
+}
+
+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/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl
new file mode 100644
index 0000000000..c23c9032ec
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/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/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl
new file mode 100644
index 0000000000..505e222137
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/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/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp
index d73df6418d..f061a32c52 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp
@@ -1,74 +1,71 @@
-#include "precompiled.h"
//
// 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.
//
-// Blit.cpp: Surface copy utility class.
+// Blit9.cpp: Surface copy utility class.
-#include "libGLESv2/renderer/d3d9/Blit.h"
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d9/TextureStorage9.h"
-#include "libGLESv2/renderer/d3d9/RenderTarget9.h"
-#include "libGLESv2/renderer/d3d9/Renderer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Blit9.h"
+#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
+#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
+#include "libGLESv2/main.h"
namespace
{
-#include "libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h"
-#include "libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h"
-#include "libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h"
-#include "libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h"
-#include "libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h"
+// Precompiled shaders
+#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/standardvs.h"
+#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/flipyvs.h"
+#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/passthroughps.h"
+#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/luminanceps.h"
+#include "libGLESv2/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
+ g_vs20_VS_standard,
+ g_vs20_VS_flipy,
+ g_ps20_PS_passthrough,
+ g_ps20_PS_luminance,
+ g_ps20_PS_componentmask
};
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)
+ sizeof(g_vs20_VS_standard),
+ sizeof(g_vs20_VS_flipy),
+ sizeof(g_ps20_PS_passthrough),
+ sizeof(g_ps20_PS_luminance),
+ sizeof(g_ps20_PS_componentmask)
};
}
namespace rx
{
-Blit::Blit(rx::Renderer9 *renderer)
+Blit9::Blit9(rx::Renderer9 *renderer)
: mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL)
{
initGeometry();
memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
}
-Blit::~Blit()
+Blit9::~Blit9()
{
- if (mSavedStateBlock) mSavedStateBlock->Release();
- if (mQuadVertexBuffer) mQuadVertexBuffer->Release();
- if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release();
+ SafeRelease(mSavedStateBlock);
+ SafeRelease(mQuadVertexBuffer);
+ SafeRelease(mQuadVertexDeclaration);
for (int i = 0; i < SHADER_COUNT; i++)
{
- if (mCompiledShaders[i])
- {
- mCompiledShaders[i]->Release();
- }
+ SafeRelease(mCompiledShaders[i]);
}
}
-void Blit::initGeometry()
+void Blit9::initGeometry()
{
static const float quad[] =
{
@@ -116,7 +113,7 @@ void Blit::initGeometry()
}
template <class D3DShaderType>
-bool Blit::setShader(ShaderId source, const char *profile,
+bool Blit9::setShader(ShaderId source, const char *profile,
D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length),
HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
{
@@ -154,17 +151,17 @@ bool Blit::setShader(ShaderId source, const char *profile,
return true;
}
-bool Blit::setVertexShader(ShaderId shader)
+bool Blit9::setVertexShader(ShaderId shader)
{
return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader);
}
-bool Blit::setPixelShader(ShaderId shader)
+bool Blit9::setPixelShader(ShaderId shader)
{
return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader);
}
-RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const
+RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const
{
D3DSURFACE_DESC desc;
surface->GetDesc(&desc);
@@ -178,7 +175,7 @@ RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const
return rect;
}
-bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
+bool Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
{
IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
if (!texture)
@@ -204,24 +201,24 @@ bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
render();
- texture->Release();
+ SafeRelease(texture);
restoreState();
return true;
}
-bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
+bool Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
{
RenderTarget9 *renderTarget = NULL;
IDirect3DSurface9 *source = NULL;
- gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
+ gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
if (colorbuffer)
{
- renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
+ renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer);
}
-
+
if (renderTarget)
{
source = renderTarget->getSurface();
@@ -233,31 +230,31 @@ bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum des
return gl::error(GL_OUT_OF_MEMORY, false);
}
- TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
+ TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage);
IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true);
bool result = false;
-
+
if (destSurface)
{
result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
- destSurface->Release();
+ SafeRelease(destSurface);
}
- source->Release();
+ SafeRelease(source);
return result;
}
-bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
+bool Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
{
RenderTarget9 *renderTarget = NULL;
IDirect3DSurface9 *source = NULL;
- gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
+ gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
if (colorbuffer)
{
- renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
+ renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer);
}
-
+
if (renderTarget)
{
source = renderTarget->getSurface();
@@ -269,21 +266,21 @@ bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum des
return gl::error(GL_OUT_OF_MEMORY, false);
}
- TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
+ TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage);
IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true);
bool result = false;
if (destSurface)
{
result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
- destSurface->Release();
+ SafeRelease(destSurface);
}
- source->Release();
+ SafeRelease(source);
return result;
}
-bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
+bool Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
{
if (!dest)
{
@@ -316,7 +313,7 @@ bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFo
return true;
}
-bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
+bool Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
{
IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
if (!texture)
@@ -339,14 +336,14 @@ bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLen
render();
}
- texture->Release();
+ SafeRelease(texture);
restoreState();
return true;
}
-bool Blit::setFormatConvertShaders(GLenum destFormat)
+bool Blit9::setFormatConvertShaders(GLenum destFormat)
{
bool okay = setVertexShader(SHADER_VS_STANDARD);
@@ -356,6 +353,8 @@ bool Blit::setFormatConvertShaders(GLenum destFormat)
case GL_RGBA:
case GL_BGRA_EXT:
case GL_RGB:
+ case GL_RG_EXT:
+ case GL_RED_EXT:
case GL_ALPHA:
okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
break;
@@ -375,41 +374,99 @@ bool Blit::setFormatConvertShaders(GLenum destFormat)
// The meaning of this constant depends on the shader that was selected.
// See the shader assembly code above for details.
- float psConst0[4] = { 0, 0, 0, 0 };
+ // 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:
- psConst0[X] = 1;
- psConst0[Z] = 1;
+ 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:
- psConst0[X] = 1;
- psConst0[W] = 1;
+ 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:
- psConst0[Z] = 1;
+ 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:
- psConst0[Y] = 1;
+ 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:
- psConst0[X] = 1;
+ 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, psConst0, 1);
+ mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2);
return true;
}
-IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
+IDirect3DTexture9 *Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
{
if (!surface)
{
@@ -437,26 +494,26 @@ IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- texture->Release();
+ SafeRelease(texture);
return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
}
mRenderer->endScene();
result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
- textureSurface->Release();
+ SafeRelease(textureSurface);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- texture->Release();
+ SafeRelease(texture);
return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
}
return texture;
}
-void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
+void Blit9::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
{
IDirect3DDevice9 *device = mRenderer->getDevice();
@@ -473,7 +530,7 @@ void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
}
-void Blit::setCommonBlitState()
+void Blit9::setCommonBlitState()
{
IDirect3DDevice9 *device = mRenderer->getDevice();
@@ -503,7 +560,7 @@ void Blit::setCommonBlitState()
}
}
-void Blit::render()
+void Blit9::render()
{
IDirect3DDevice9 *device = mRenderer->getDevice();
@@ -514,7 +571,7 @@ void Blit::render()
hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}
-void Blit::saveState()
+void Blit9::saveState()
{
IDirect3DDevice9 *device = mRenderer->getDevice();
@@ -530,12 +587,12 @@ void Blit::saveState()
setCommonBlitState();
- static const float dummyConst[4] = { 0, 0, 0, 0 };
+ static const float dummyConst[8] = { 0 };
device->SetVertexShader(NULL);
- device->SetVertexShaderConstantF(0, dummyConst, 1);
+ device->SetVertexShaderConstantF(0, dummyConst, 2);
device->SetPixelShader(NULL);
- device->SetPixelShaderConstantF(0, dummyConst, 1);
+ device->SetPixelShaderConstantF(0, dummyConst, 2);
D3DVIEWPORT9 dummyVp;
dummyVp.X = 0;
@@ -566,23 +623,15 @@ void Blit::saveState()
}
}
-void Blit::restoreState()
+void Blit9::restoreState()
{
IDirect3DDevice9 *device = mRenderer->getDevice();
device->SetDepthStencilSurface(mSavedDepthStencil);
- if (mSavedDepthStencil != NULL)
- {
- mSavedDepthStencil->Release();
- mSavedDepthStencil = NULL;
- }
+ SafeRelease(mSavedDepthStencil);
device->SetRenderTarget(0, mSavedRenderTarget);
- if (mSavedRenderTarget != NULL)
- {
- mSavedRenderTarget->Release();
- mSavedRenderTarget = NULL;
- }
+ SafeRelease(mSavedRenderTarget);
ASSERT(mSavedStateBlock != NULL);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h
index 3718028e66..46a3ee1cf3 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h
@@ -4,13 +4,15 @@
// found in the LICENSE file.
//
-// Blit.cpp: Surface copy utility class.
+// Blit9.cpp: Surface copy utility class.
-#ifndef LIBGLESV2_BLIT_H_
-#define LIBGLESV2_BLIT_H_
+#ifndef LIBGLESV2_BLIT9_H_
+#define LIBGLESV2_BLIT9_H_
#include "common/angleutils.h"
+#include <GLES2/gl2.h>
+
namespace gl
{
class Framebuffer;
@@ -19,19 +21,18 @@ class Framebuffer;
namespace rx
{
class Renderer9;
-class TextureStorageInterface2D;
-class TextureStorageInterfaceCube;
+class TextureStorage;
-class Blit
+class Blit9
{
public:
- explicit Blit(Renderer9 *renderer);
- ~Blit();
+ explicit Blit9(Renderer9 *renderer);
+ ~Blit9();
// Copy from source surface to dest surface.
// sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
- bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level);
- bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level);
+ bool copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level);
+ bool copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, 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)
@@ -87,8 +88,8 @@ class Blit
IDirect3DSurface9 *mSavedRenderTarget;
IDirect3DSurface9 *mSavedDepthStencil;
- DISALLOW_COPY_AND_ASSIGN(Blit);
+ DISALLOW_COPY_AND_ASSIGN(Blit9);
};
}
-#endif // LIBGLESV2_BLIT_H_
+#endif // LIBGLESV2_BLIT9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp
new file mode 100644
index 0000000000..c02db515a2
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp
@@ -0,0 +1,121 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d9/Buffer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+Buffer9::Buffer9(rx::Renderer9 *renderer)
+ : BufferD3D(),
+ mRenderer(renderer),
+ mSize(0)
+{}
+
+Buffer9::~Buffer9()
+{
+ mSize = 0;
+}
+
+Buffer9 *Buffer9::makeBuffer9(BufferImpl *buffer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(Buffer9*, buffer));
+ return static_cast<Buffer9*>(buffer);
+}
+
+gl::Error Buffer9::setData(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)
+ {
+ memcpy(mMemory.data(), data, size);
+ }
+
+ invalidateStaticData();
+
+ if (usage == GL_STATIC_DRAW)
+ {
+ initializeStaticData();
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void *Buffer9::getData()
+{
+ return mMemory.data();
+}
+
+gl::Error Buffer9::setSubData(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)
+ {
+ 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 = makeBuffer9(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(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Buffer9::unmap()
+{
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+void Buffer9::markTransformFeedbackUsage()
+{
+ UNREACHABLE();
+}
+
+Renderer* Buffer9::getRenderer()
+{
+ return mRenderer;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h
new file mode 100644
index 0000000000..e78182f905
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h
@@ -0,0 +1,52 @@
+//
+// 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 LIBGLESV2_RENDERER_BUFFER9_H_
+#define LIBGLESV2_RENDERER_BUFFER9_H_
+
+#include "libGLESv2/renderer/d3d/BufferD3D.h"
+#include "libGLESv2/renderer/d3d/MemoryBuffer.h"
+#include "libGLESv2/angletypes.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Buffer9 : public BufferD3D
+{
+ public:
+ Buffer9(rx::Renderer9 *renderer);
+ virtual ~Buffer9();
+
+ static Buffer9 *makeBuffer9(BufferImpl *buffer);
+
+ // BufferD3D implementation
+ virtual size_t getSize() const { return mSize; }
+ virtual bool supportsDirectBinding() const { return false; }
+ virtual Renderer* getRenderer();
+
+ // BufferImpl implementation
+ virtual gl::Error setData(const void* data, size_t size, GLenum usage);
+ virtual void *getData();
+ virtual gl::Error setSubData(const void* data, size_t size, size_t offset);
+ virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
+ virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr);
+ virtual gl::Error unmap();
+ virtual void markTransformFeedbackUsage();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Buffer9);
+
+ rx::Renderer9 *mRenderer;
+ MemoryBuffer mMemory;
+ size_t mSize;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_BUFFER9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp
new file mode 100644
index 0000000000..e352a5f50a
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp
@@ -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.
+//
+
+// Fence9.cpp: Defines the rx::Fence9 class.
+
+#include "libGLESv2/renderer/d3d/d3d9/Fence9.h"
+#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+Fence9::Fence9(rx::Renderer9 *renderer)
+{
+ mRenderer = renderer;
+ mQuery = NULL;
+}
+
+Fence9::~Fence9()
+{
+ SafeRelease(mQuery);
+}
+
+bool Fence9::isSet() const
+{
+ return mQuery != NULL;
+}
+
+void Fence9::set()
+{
+ if (!mQuery)
+ {
+ mQuery = mRenderer->allocateEventQuery();
+ if (!mQuery)
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ HRESULT result = mQuery->Issue(D3DISSUE_END);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(SUCCEEDED(result));
+}
+
+bool Fence9::test(bool flushCommandBuffer)
+{
+ 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, true);
+ }
+
+ ASSERT(result == S_OK || result == S_FALSE);
+
+ return (result == S_OK);
+}
+
+bool Fence9::hasError() const
+{
+ return mRenderer->isDeviceLost();
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h
index 9f17641e51..e923a2178c 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h
@@ -21,11 +21,10 @@ class Fence9 : public FenceImpl
explicit Fence9(rx::Renderer9 *renderer);
virtual ~Fence9();
- GLboolean isFence();
- void setFence(GLenum condition);
- GLboolean testFence();
- void finishFence();
- void getFenceiv(GLenum pname, GLint *params);
+ bool isSet() const;
+ void set();
+ bool test(bool flushCommandBuffer);
+ bool hasError() const;
private:
DISALLOW_COPY_AND_ASSIGN(Fence9);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
index cd12d8cc9e..18383fba78 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -8,17 +7,17 @@
// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to
// the actual underlying surfaces of a Texture.
-#include "libGLESv2/renderer/d3d9/Image9.h"
-
+#include "libGLESv2/renderer/d3d/d3d9/Image9.h"
+#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h"
#include "libGLESv2/main.h"
#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/renderer/d3d9/Renderer9.h"
-#include "libGLESv2/renderer/d3d9/RenderTarget9.h"
-#include "libGLESv2/renderer/d3d9/TextureStorage9.h"
-#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/generatemip.h"
namespace rx
{
@@ -34,10 +33,7 @@ Image9::Image9()
Image9::~Image9()
{
- if (mSurface)
- {
- mSurface->Release();
- }
+ SafeRelease(mSurface);
}
void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface)
@@ -54,6 +50,9 @@ void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sour
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.mipGenerationFunction != NULL);
+
D3DLOCKED_RECT sourceLocked = {0};
result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY);
ASSERT(SUCCEEDED(result));
@@ -62,37 +61,17 @@ void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sour
result = destSurface->LockRect(&destLocked, NULL, 0);
ASSERT(SUCCEEDED(result));
- const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(sourceLocked.pBits);
- unsigned char *destData = reinterpret_cast<unsigned char*>(destLocked.pBits);
+ const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(sourceLocked.pBits);
+ uint8_t *destData = reinterpret_cast<uint8_t*>(destLocked.pBits);
if (sourceData && destData)
{
- switch (sourceDesc.Format)
- {
- case D3DFMT_L8:
- GenerateMip<L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
- break;
- case D3DFMT_A8L8:
- GenerateMip<A8L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
- break;
- case D3DFMT_A8R8G8B8:
- case D3DFMT_X8R8G8B8:
- GenerateMip<A8R8G8B8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
- break;
- case D3DFMT_A16B16G16R16F:
- GenerateMip<A16B16G16R16F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
- break;
- case D3DFMT_A32B32G32R32F:
- GenerateMip<A32B32G32R32F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
- break;
- default:
- UNREACHABLE();
- break;
- }
-
- destSurface->UnlockRect();
- sourceSurface->UnlockRect();
+ d3dFormatInfo.mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0,
+ destData, destLocked.Pitch, 0);
}
+
+ destSurface->UnlockRect();
+ sourceSurface->UnlockRect();
}
Image9 *Image9::makeImage9(Image *img)
@@ -117,20 +96,23 @@ void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *so
{
D3DLOCKED_RECT sourceLock = {0};
D3DLOCKED_RECT destLock = {0};
-
+
source->LockRect(&sourceLock, NULL, 0);
dest->LockRect(&destLock, NULL, 0);
-
+
if (sourceLock.pBits && destLock.pBits)
{
D3DSURFACE_DESC desc;
source->GetDesc(&desc);
- int rows = d3d9::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height;
- int bytes = d3d9::ComputeRowSize(desc.Format, desc.Width);
- ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch);
+ 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(int i = 0; i < rows; i++)
+ for(unsigned int i = 0; i < rows; i++)
{
memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes);
}
@@ -141,10 +123,17 @@ void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *so
else UNREACHABLE();
}
-bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
+bool Image9::redefine(rx::Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease)
{
+ // 3D textures are not supported by the D3D9 backend.
+ ASSERT(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 != width ||
mHeight != height ||
+ mDepth != depth ||
mInternalFormat != internalformat ||
forceRelease)
{
@@ -152,16 +141,18 @@ bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei widt
mWidth = width;
mHeight = height;
+ mDepth = depth;
mInternalFormat = internalformat;
+
// compute the d3d format that will be used
- mD3DFormat = mRenderer->ConvertTextureInternalFormat(internalformat);
- mActualFormat = d3d9_gl::GetEquivalentFormat(mD3DFormat);
+ const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat);
+ mD3DFormat = d3d9FormatInfo.texFormat;
+ mActualFormat = d3dFormatInfo.internalFormat;
+ mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN);
- if (mSurface)
- {
- mSurface->Release();
- mSurface = NULL;
- }
+ SafeRelease(mSurface);
+ mDirty = (d3d9FormatInfo.dataInitializerFunction != NULL);
return true;
}
@@ -180,14 +171,13 @@ void Image9::createSurface()
IDirect3DSurface9 *newSurface = NULL;
const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
const D3DFORMAT d3dFormat = getD3DFormat();
- ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures
if (mWidth != 0 && mHeight != 0)
{
int levelToFetch = 0;
GLsizei requestWidth = mWidth;
GLsizei requestHeight = mHeight;
- gl::MakeValidSize(true, gl::IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch);
+ d3d9::MakeValidSize(true, d3dFormat, &requestWidth, &requestHeight, &levelToFetch);
IDirect3DDevice9 *device = mRenderer->getDevice();
@@ -202,7 +192,27 @@ void Image9::createSurface()
}
newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
- newTexture->Release();
+ 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));
+
+ d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast<uint8_t*>(lockedRect.pBits),
+ lockedRect.Pitch, 0);
+
+ result = newSurface->UnlockRect();
+ ASSERT(SUCCEEDED(result));
+ }
}
mSurface = newSurface;
@@ -232,15 +242,11 @@ void Image9::unlock()
if (mSurface)
{
HRESULT result = mSurface->UnlockRect();
+ UNUSED_ASSERTION_VARIABLE(result);
ASSERT(SUCCEEDED(result));
}
}
-bool Image9::isRenderableFormat() const
-{
- return TextureStorage9::IsTextureFormatRenderable(getD3DFormat());
-}
-
D3DFORMAT Image9::getD3DFormat() const
{
// this should only happen if the image hasn't been redefined first
@@ -250,6 +256,13 @@ D3DFORMAT Image9::getD3DFormat() const
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;
+}
+
IDirect3DSurface9 *Image9::getSurface()
{
createSurface();
@@ -257,15 +270,15 @@ IDirect3DSurface9 *Image9::getSurface()
return mSurface;
}
-void Image9::setManagedSurface(TextureStorageInterface2D *storage, int level)
+void Image9::setManagedSurface2D(TextureStorage *storage, int level)
{
- TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
+ TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage);
setManagedSurface(storage9->getSurfaceLevel(level, false));
}
-void Image9::setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level)
+void Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level)
{
- TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
+ TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage);
setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false));
}
@@ -280,7 +293,7 @@ void Image9::setManagedSurface(IDirect3DSurface9 *surface)
if (mSurface)
{
copyLockableSurfaces(surface, mSurface);
- mSurface->Release();
+ SafeRelease(mSurface);
}
mSurface = surface;
@@ -288,22 +301,38 @@ void Image9::setManagedSurface(IDirect3DSurface9 *surface)
}
}
-bool Image9::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+bool Image9::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
{
ASSERT(getSurface() != NULL);
- TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
- return updateSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height);
+ TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage);
+ return copyToSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height);
}
-bool Image9::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+bool Image9::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
{
ASSERT(getSurface() != NULL);
- TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
- return updateSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height);
+ TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage);
+ return copyToSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height);
+}
+
+bool Image9::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
+{
+ // 3D textures are not supported by the D3D9 backend.
+ UNREACHABLE();
+ return false;
}
-bool Image9::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+bool Image9::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height)
{
+ // 2D array textures are not supported by the D3D9 backend.
+ UNREACHABLE();
+ return false;
+}
+
+bool Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ ASSERT(width > 0 && height > 0);
+
if (!destSurface)
return false;
@@ -334,26 +363,36 @@ bool Image9::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint
copyLockableSurfaces(surf, sourceSurface);
result = device->UpdateSurface(surf, &rect, destSurface, &point);
ASSERT(SUCCEEDED(result));
- surf->Release();
+ SafeRelease(surf);
}
}
else
{
- // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
+ // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point);
+ UNUSED_ASSERTION_VARIABLE(result);
ASSERT(SUCCEEDED(result));
}
}
- destSurface->Release();
+ SafeRelease(destSurface);
return true;
}
// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
// into the target pixel rectangle.
-void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLint unpackAlignment, const void *input)
+void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+ GLint unpackAlignment, GLenum type, const void *input)
{
+ // 3D textures are not supported by the D3D9 backend.
+ ASSERT(zoffset == 0 && depth == 1);
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+ GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment);
+
+ const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
+ ASSERT(d3dFormatInfo.loadFunction != NULL);
+
RECT lockRect =
{
xoffset, yoffset,
@@ -367,100 +406,32 @@ void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heigh
return;
}
-
- GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
-
- switch (mInternalFormat)
- {
- case GL_ALPHA8_EXT:
-#if defined(__SSE2__)
- if (gl::supportsSSE2())
- {
- loadAlphaDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- }
- else
-#endif
- {
- loadAlphaDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- }
- break;
- case GL_LUMINANCE8_EXT:
- loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8);
- break;
- case GL_ALPHA32F_EXT:
- loadAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_LUMINANCE32F_EXT:
- loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_ALPHA16F_EXT:
- loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_LUMINANCE16F_EXT:
- loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_LUMINANCE8_ALPHA8_EXT:
- loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8);
- break;
- case GL_LUMINANCE_ALPHA32F_EXT:
- loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_LUMINANCE_ALPHA16F_EXT:
- loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_RGB8_OES:
- loadRGBUByteDataToBGRX(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_RGB565:
- loadRGB565DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_RGBA8_OES:
-#if defined(__SSE2__)
- if (gl::supportsSSE2())
- {
- loadRGBAUByteDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- }
- else
-#endif
- {
- loadRGBAUByteDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- }
- break;
- case GL_RGBA4:
- loadRGBA4444DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_RGB5_A1:
- loadRGBA5551DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_BGRA8_EXT:
- loadBGRADataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
- case GL_RGB32F_EXT:
- loadRGBFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_RGB16F_EXT:
- loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_RGBA32F_EXT:
- loadRGBAFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- case GL_RGBA16F_EXT:
- loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
- break;
- default: UNREACHABLE();
- }
+ d3dFormatInfo.loadFunction(width, height, depth,
+ reinterpret_cast<const uint8_t*>(input), inputRowPitch, 0,
+ reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0);
unlock();
}
-void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
const void *input)
{
- ASSERT(xoffset % 4 == 0);
- ASSERT(yoffset % 4 == 0);
+ // 3D textures are not supported by the D3D9 backend.
+ ASSERT(zoffset == 0 && depth == 1);
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+ GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
+
+ const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
+
+ ASSERT(xoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0);
+ ASSERT(yoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0);
- RECT lockRect = {
+ ASSERT(d3d9FormatInfo.loadFunction != NULL);
+
+ RECT lockRect =
+ {
xoffset, yoffset,
xoffset + width, yoffset + height
};
@@ -472,29 +443,28 @@ void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLs
return;
}
- GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
- GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
- int rows = inputSize / inputPitch;
- for (int i = 0; i < rows; ++i)
- {
- memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
- }
+ d3d9FormatInfo.loadFunction(width, height, depth,
+ reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
+ reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0);
unlock();
}
// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
-void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
{
+ // ES3.0 only behaviour to copy into a 3d texture
+ ASSERT(zoffset == 0);
+
RenderTarget9 *renderTarget = NULL;
IDirect3DSurface9 *surface = NULL;
- gl::Renderbuffer *colorbuffer = source->getColorbuffer(0);
+ gl::FramebufferAttachment *colorbuffer = source->getColorbuffer(0);
if (colorbuffer)
{
- renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
+ renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer);
}
-
+
if (renderTarget)
{
surface = renderTarget->getSurface();
@@ -511,13 +481,13 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width,
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))
{
ERR("Could not create matching destination surface.");
- surface->Release();
+ SafeRelease(surface);
return gl::error(GL_OUT_OF_MEMORY);
}
@@ -526,8 +496,8 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width,
if (FAILED(result))
{
ERR("GetRenderTargetData unexpectedly failed.");
- renderTargetData->Release();
- surface->Release();
+ SafeRelease(renderTargetData);
+ SafeRelease(surface);
return gl::error(GL_OUT_OF_MEMORY);
}
@@ -540,20 +510,20 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width,
if (FAILED(result))
{
ERR("Failed to lock the source surface (rectangle might be invalid).");
- renderTargetData->Release();
- surface->Release();
+ SafeRelease(renderTargetData);
+ SafeRelease(surface);
return gl::error(GL_OUT_OF_MEMORY);
}
D3DLOCKED_RECT destLock = {0};
result = lock(&destLock, &destRect);
-
+
if (FAILED(result))
{
ERR("Failed to lock the destination surface (rectangle might be invalid).");
renderTargetData->UnlockRect();
- renderTargetData->Release();
- surface->Release();
+ SafeRelease(renderTargetData);
+ SafeRelease(surface);
return gl::error(GL_OUT_OF_MEMORY);
}
@@ -727,8 +697,8 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width,
unlock();
renderTargetData->UnlockRect();
- renderTargetData->Release();
- surface->Release();
+ SafeRelease(renderTargetData);
+ SafeRelease(surface);
mDirty = true;
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h
new file mode 100644
index 0000000000..08d8ee3545
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h
@@ -0,0 +1,78 @@
+//
+// 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 LIBGLESV2_RENDERER_IMAGE9_H_
+#define LIBGLESV2_RENDERER_IMAGE9_H_
+
+#include "libGLESv2/renderer/d3d/ImageD3D.h"
+#include "common/debug.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Renderer;
+class Renderer9;
+
+class Image9 : public ImageD3D
+{
+ public:
+ Image9();
+ ~Image9();
+
+ static Image9 *makeImage9(Image *img);
+
+ static void generateMipmap(Image9 *dest, Image9 *source);
+ static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface);
+ static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source);
+
+ virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease);
+
+ D3DFORMAT getD3DFormat() const;
+
+ virtual bool isDirty() const;
+ IDirect3DSurface9 *getSurface();
+
+ virtual void setManagedSurface2D(TextureStorage *storage, int level);
+ virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level);
+ virtual bool copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+ virtual bool copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+ virtual bool copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+ virtual bool copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height);
+
+ virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+ GLint unpackAlignment, GLenum type, const void *input);
+ virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+ const void *input);
+
+ virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset,GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Image9);
+
+ void createSurface();
+ void setManagedSurface(IDirect3DSurface9 *surface);
+ bool copyToSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+ HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect);
+ void unlock();
+
+ Renderer9 *mRenderer;
+
+ D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable.
+ D3DFORMAT mD3DFormat;
+
+ IDirect3DSurface9 *mSurface;
+};
+}
+
+#endif // LIBGLESV2_RENDERER_IMAGE9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp
new file mode 100644
index 0000000000..1c51b9e985
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp
@@ -0,0 +1,173 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h"
+#include "libGLESv2/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->getRendererExtensions().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);
+}
+
+IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer));
+ return static_cast<IndexBuffer9*>(indexBuffer);
+}
+
+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/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h
index 6801867532..d0970d6ac5 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h
@@ -9,7 +9,7 @@
#ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_
#define LIBGLESV2_RENDERER_INDEXBUFFER9_H_
-#include "libGLESv2/renderer/IndexBuffer.h"
+#include "libGLESv2/renderer/d3d/IndexBuffer.h"
namespace rx
{
@@ -21,18 +21,18 @@ class IndexBuffer9 : public IndexBuffer
explicit IndexBuffer9(Renderer9 *const renderer);
virtual ~IndexBuffer9();
- virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
+ virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
static IndexBuffer9 *makeIndexBuffer9(IndexBuffer *indexBuffer);
- virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory);
- virtual bool unmapBuffer();
+ 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 bool setSize(unsigned int bufferSize, GLenum indexType);
+ virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType);
- virtual bool discard();
+ virtual gl::Error discard();
D3DFORMAT getIndexFormat() const;
IDirect3DIndexBuffer9 *getBuffer() const;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp
new file mode 100644
index 0000000000..815fc01a9b
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.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.
+//
+
+// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl.
+
+#include "libGLESv2/renderer/d3d/d3d9/Query9.h"
+#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+#include "libGLESv2/main.h"
+
+#include <GLES2/gl2ext.h>
+
+namespace rx
+{
+Query9::Query9(rx::Renderer9 *renderer, GLenum type)
+ : QueryImpl(type),
+ mResult(GL_FALSE),
+ mQueryFinished(false),
+ mRenderer(renderer),
+ mQuery(NULL)
+{
+}
+
+Query9::~Query9()
+{
+ SafeRelease(mQuery);
+}
+
+gl::Error Query9::begin()
+{
+ if (mQuery == NULL)
+ {
+ HRESULT result = mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result);
+ }
+ }
+
+ 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::getResult(GLuint *params)
+{
+ while (!mQueryFinished)
+ {
+ gl::Error error = testQuery();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!mQueryFinished)
+ {
+ Sleep(0);
+ }
+ }
+
+ ASSERT(mQueryFinished);
+ *params = mResult;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Query9::isResultAvailable(GLuint *available)
+{
+ gl::Error error = testQuery();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *available = (mQueryFinished ? GL_TRUE : GL_FALSE);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Query9::testQuery()
+{
+ if (!mQueryFinished)
+ {
+ ASSERT(mQuery);
+
+ DWORD numPixels = 0;
+
+ HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH);
+ if (hres == S_OK)
+ {
+ mQueryFinished = true;
+
+ switch (getType())
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ else if (d3d9::isDeviceLostError(hres))
+ {
+ mRenderer->notifyDeviceLost();
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
+ }
+ else if (mRenderer->testDeviceLost(true))
+ {
+ 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/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h
index 47eef89336..513e0ba6fd 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h
@@ -21,15 +21,18 @@ class Query9 : public QueryImpl
Query9(rx::Renderer9 *renderer, GLenum type);
virtual ~Query9();
- void begin();
- void end();
- GLuint getResult();
- GLboolean isResultAvailable();
+ virtual gl::Error begin();
+ virtual gl::Error end();
+ virtual gl::Error getResult(GLuint *params);
+ virtual gl::Error isResultAvailable(GLuint *available);
private:
DISALLOW_COPY_AND_ASSIGN(Query9);
- GLboolean testQuery();
+ gl::Error testQuery();
+
+ GLuint mResult;
+ bool mQueryFinished;
rx::Renderer9 *mRenderer;
IDirect3DQuery9 *mQuery;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp
new file mode 100644
index 0000000000..13321ac8cd
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp
@@ -0,0 +1,133 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given.
+RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface)
+{
+ mRenderer = Renderer9::makeRenderer9(renderer);
+ mRenderTarget = surface;
+
+ if (mRenderTarget)
+ {
+ D3DSURFACE_DESC description;
+ mRenderTarget->GetDesc(&description);
+
+ mWidth = description.Width;
+ mHeight = description.Height;
+ mDepth = 1;
+
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(description.Format);
+ mInternalFormat = d3dFormatInfo.internalFormat;
+ mActualFormat = d3dFormatInfo.internalFormat;
+ mSamples = d3d9_gl::GetSamplesCount(description.MultiSampleType);
+ }
+}
+
+RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples)
+{
+ mRenderer = Renderer9::makeRenderer9(renderer);
+ mRenderTarget = NULL;
+
+ const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalFormat);
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(d3d9FormatInfo.renderFormat);
+
+ const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat);
+ GLuint supportedSamples = textureCaps.getNearestSamples(samples);
+
+ HRESULT result = D3DERR_INVALIDCALL;
+
+ if (width > 0 && height > 0)
+ {
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ bool requiresInitialization = false;
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+ {
+ result = device->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat,
+ gl_d3d9::GetMultisampleType(supportedSamples),
+ 0, FALSE, &mRenderTarget, NULL);
+ }
+ else
+ {
+ requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != NULL);
+ result = device->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat,
+ gl_d3d9::GetMultisampleType(supportedSamples),
+ 0, FALSE, &mRenderTarget, NULL);
+ }
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ {
+ gl::error(GL_OUT_OF_MEMORY);
+
+ return;
+ }
+
+ ASSERT(SUCCEEDED(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;
+ device->GetRenderTarget(0, &prevRenderTarget);
+ device->SetRenderTarget(0, mRenderTarget);
+ device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0);
+ device->SetRenderTarget(0, prevRenderTarget);
+ }
+ }
+
+ mWidth = width;
+ mHeight = height;
+ mDepth = 1;
+ mInternalFormat = internalFormat;
+ mSamples = supportedSamples;
+ mActualFormat = d3dFormatInfo.internalFormat;
+}
+
+RenderTarget9::~RenderTarget9()
+{
+ SafeRelease(mRenderTarget);
+}
+
+RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target));
+ return static_cast<rx::RenderTarget9*>(target);
+}
+
+void RenderTarget9::invalidate(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ // Currently a no-op
+}
+
+IDirect3DSurface9 *RenderTarget9::getSurface()
+{
+ // Caller is responsible for releasing the returned surface reference.
+ // TODO: remove the AddRef to match RenderTarget11
+ if (mRenderTarget)
+ {
+ mRenderTarget->AddRef();
+ }
+
+ return mRenderTarget;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h
index faf8ad1c6d..68d7adb49e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h
@@ -21,10 +21,13 @@ class RenderTarget9 : public RenderTarget
{
public:
RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface);
- RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples);
+ RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples);
virtual ~RenderTarget9();
static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget);
+
+ virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height);
+
IDirect3DSurface9 *getSurface();
private:
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
index 97a10d64bf..d63f9b8582 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
@@ -1,36 +1,45 @@
-#include "precompiled.h"
//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// 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 "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
+#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h"
+#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h"
+#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Image9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Blit9.h"
+#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Query9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Fence9.h"
+#include "libGLESv2/renderer/d3d/d3d9/VertexArray9.h"
+#include "libGLESv2/renderer/d3d/IndexDataManager.h"
+#include "libGLESv2/renderer/d3d/ProgramD3D.h"
+#include "libGLESv2/renderer/d3d/ShaderD3D.h"
+#include "libGLESv2/renderer/d3d/TextureD3D.h"
+#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h"
#include "libGLESv2/main.h"
#include "libGLESv2/Buffer.h"
#include "libGLESv2/Texture.h"
#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
#include "libGLESv2/Renderbuffer.h"
#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/renderer/IndexDataManager.h"
-#include "libGLESv2/renderer/d3d9/Renderer9.h"
-#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h"
-#include "libGLESv2/renderer/d3d9/SwapChain9.h"
-#include "libGLESv2/renderer/d3d9/TextureStorage9.h"
-#include "libGLESv2/renderer/d3d9/Image9.h"
-#include "libGLESv2/renderer/d3d9/Blit.h"
-#include "libGLESv2/renderer/d3d9/RenderTarget9.h"
-#include "libGLESv2/renderer/d3d9/VertexBuffer9.h"
-#include "libGLESv2/renderer/d3d9/IndexBuffer9.h"
-#include "libGLESv2/renderer/d3d9/BufferStorage9.h"
-#include "libGLESv2/renderer/d3d9/Query9.h"
-#include "libGLESv2/renderer/d3d9/Fence9.h"
+#include "libGLESv2/angletypes.h"
#include "libEGL/Display.h"
-#include "third_party/trace_event/trace_event.h"
+#include "common/utilities.h"
+
+#include <sstream>
// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
#define REF_RAST 0
@@ -43,6 +52,13 @@
#define ANGLE_ENABLE_D3D9EX 1
#endif // !defined(ANGLE_ENABLE_D3D9EX)
+#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
+#endif
+
+const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')));
+const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')));
+
namespace rx
{
static const D3DFORMAT RenderTargetFormats[] =
@@ -80,7 +96,9 @@ enum
MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
};
-Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice)
+Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay)
+ : Renderer(display),
+ mDc(hDc)
{
mD3d9Module = NULL;
@@ -101,13 +119,12 @@ Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Rend
mDeviceLost = false;
- mMaxSupportedSamples = 0;
-
mMaskedClearSavedState = NULL;
mVertexDataManager = NULL;
mIndexDataManager = NULL;
mLineLoopIB = NULL;
+ mCountingIB = NULL;
mMaxNullColorbufferLRU = 0;
for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
@@ -117,6 +134,10 @@ Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Rend
mNullColorbufferCache[i].height = 0;
mNullColorbufferCache[i].buffer = NULL;
}
+
+ mAppliedVertexShader = NULL;
+ mAppliedPixelShader = NULL;
+ mAppliedProgramSerial = 0;
}
Renderer9::~Renderer9()
@@ -130,11 +151,12 @@ Renderer9::~Renderer9()
}
}
- deinitialize();
+ release();
}
-void Renderer9::deinitialize()
+void Renderer9::release()
{
+ releaseShaderCompiler();
releaseDeviceResources();
SafeRelease(mDevice);
@@ -142,22 +164,15 @@ void Renderer9::deinitialize()
SafeRelease(mD3d9);
SafeRelease(mD3d9Ex);
+ mCompiler.release();
+
if (mDeviceWindow)
{
DestroyWindow(mDeviceWindow);
mDeviceWindow = NULL;
}
- if (mD3d9Module)
- {
- mD3d9Module = NULL;
- }
-
- while (!mMultiSampleSupport.empty())
- {
- delete [] mMultiSampleSupport.begin()->second;
- mMultiSampleSupport.erase(mMultiSampleSupport.begin());
- }
+ mD3d9Module = NULL;
}
Renderer9 *Renderer9::makeRenderer9(Renderer *renderer)
@@ -168,21 +183,12 @@ Renderer9 *Renderer9::makeRenderer9(Renderer *renderer)
EGLint Renderer9::initialize()
{
- if (!initializeCompiler())
+ if (!mCompiler.initialize())
{
return EGL_NOT_INITIALIZED;
}
- if (mSoftwareDevice)
- {
- TRACE_EVENT0("gpu", "GetModuleHandle_swiftshader");
- mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
- }
- else
- {
- TRACE_EVENT0("gpu", "GetModuleHandle_d3d9");
- mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
- }
+ mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
if (mD3d9Module == NULL)
{
@@ -198,14 +204,12 @@ EGLint Renderer9::initialize()
// desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
{
- TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface");
ASSERT(mD3d9Ex);
mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
ASSERT(mD3d9);
}
else
{
- TRACE_EVENT0("gpu", "Direct3DCreate9");
mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
}
@@ -224,7 +228,6 @@ EGLint Renderer9::initialize()
// Give up on getting device caps after about one second.
{
- TRACE_EVENT0("gpu", "GetDeviceCaps");
for (int i = 0; i < 10; ++i)
{
result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
@@ -251,7 +254,7 @@ EGLint Renderer9::initialize()
}
// 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::convertToRenderTarget.
+ // This is required by Texture2D::ensureRenderTarget.
if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
{
ERR("Renderer does not support stretctrect from textures!\n");
@@ -259,19 +262,9 @@ EGLint Renderer9::initialize()
}
{
- TRACE_EVENT0("gpu", "GetAdapterIdentifier");
mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
}
- // ATI cards on XP have problems with non-power-of-two textures.
- mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
- !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
- !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
- !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);
-
- // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
- mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2));
-
mMinSwapInterval = 4;
mMaxSwapInterval = 0;
@@ -301,61 +294,21 @@ EGLint Renderer9::initialize()
mMaxSwapInterval = std::max(mMaxSwapInterval, 4);
}
- int max = 0;
- {
- TRACE_EVENT0("gpu", "getMultiSampleSupport");
- for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i)
- {
- bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
- getMultiSampleSupport(RenderTargetFormats[i], multisampleArray);
- mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray;
-
- for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
- {
- if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
- {
- max = j;
- }
- }
- }
- }
-
- {
- TRACE_EVENT0("gpu", "getMultiSampleSupport2");
- for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i)
- {
- if (DepthStencilFormats[i] == D3DFMT_UNKNOWN)
- continue;
-
- bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
- getMultiSampleSupport(DepthStencilFormats[i], multisampleArray);
- mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray;
-
- for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
- {
- if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
- {
- max = j;
- }
- }
- }
- }
-
- mMaxSupportedSamples = max;
-
static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
static const TCHAR className[] = TEXT("STATIC");
{
- TRACE_EVENT0("gpu", "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;
+ static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
+ if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
+ behaviorFlags |= D3DCREATE_MULTITHREADED;
+
{
- TRACE_EVENT0("gpu", "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)
@@ -365,7 +318,6 @@ EGLint Renderer9::initialize()
if (FAILED(result))
{
- TRACE_EVENT0("gpu", "D3d9_CreateDevice2");
result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
if (FAILED(result))
@@ -377,47 +329,15 @@ EGLint Renderer9::initialize()
if (mD3d9Ex)
{
- TRACE_EVENT0("gpu", "mDevice_QueryInterface");
- result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
+ result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx);
ASSERT(SUCCEEDED(result));
}
{
- TRACE_EVENT0("gpu", "ShaderCache initialize");
mVertexShaderCache.initialize(mDevice);
mPixelShaderCache.initialize(mDevice);
}
- // Check occlusion query support
- IDirect3DQuery9 *occlusionQuery = NULL;
- {
- TRACE_EVENT0("gpu", "device_CreateQuery");
- if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery)
- {
- occlusionQuery->Release();
- mOcclusionQuerySupport = true;
- }
- else
- {
- mOcclusionQuerySupport = false;
- }
- }
-
- // Check event query support
- IDirect3DQuery9 *eventQuery = NULL;
- {
- TRACE_EVENT0("gpu", "device_CreateQuery2");
- if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery)
- {
- eventQuery->Release();
- mEventQuerySupport = true;
- }
- else
- {
- mEventQuerySupport = false;
- }
- }
-
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
@@ -428,70 +348,6 @@ EGLint Renderer9::initialize()
SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F));
- // Check depth texture support
- // we use INTZ for depth textures in Direct3D9
- // we also want NULL texture support to ensure the we can make depth-only FBOs
- // see http://aras-p.info/texts/D3D9GPUHacks.html
- mDepthTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
- D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)) &&
- SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
- D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
-
- // Check 32 bit floating point texture support
- mFloat32FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
- D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
- SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
- D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
-
- mFloat32RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
- D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
- SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
- D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
-
- if (!mFloat32FilterSupport && !mFloat32RenderSupport)
- {
- mFloat32TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
- D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
- SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
- D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
- }
- else
- {
- mFloat32TextureSupport = true;
- }
-
- // Check 16 bit floating point texture support
- mFloat16FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
- D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
- SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
- D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
-
- mFloat16RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
- D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
- SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
- D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
-
- if (!mFloat16FilterSupport && !mFloat16RenderSupport)
- {
- mFloat16TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
- D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
- SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
- D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
- }
- else
- {
- mFloat16TextureSupport = true;
- }
-
- // Check DXT texture support
- mDXT1TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
- mDXT3TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
- mDXT5TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
-
- // Check luminance[alpha] texture support
- mLuminanceTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
- mLuminanceAlphaTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
-
initializeDevice();
return EGL_SUCCESS;
@@ -515,12 +371,23 @@ void Renderer9::initializeDevice()
mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f
}
+ const gl::Caps &rendererCaps = getRendererCaps();
+
+ mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
+ mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
+
+ mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
+ mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
+
+ mCurVertexTextureSerials.resize(rendererCaps.maxVertexTextureImageUnits);
+ mCurPixelTextureSerials.resize(rendererCaps.maxTextureImageUnits);
+
markAllStateDirty();
mSceneStarted = false;
ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager);
- mBlit = new Blit(this);
+ mBlit = new Blit9(this);
mVertexDataManager = new rx::VertexDataManager(this);
mIndexDataManager = new rx::IndexDataManager(this);
}
@@ -559,39 +426,24 @@ int Renderer9::generateConfigs(ConfigDesc **configDescList)
for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
{
- D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
-
- HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
-
- if (SUCCEEDED(result))
+ const d3d9::D3DFormat &renderTargetFormatInfo = d3d9::GetD3DFormatInfo(RenderTargetFormats[formatIndex]);
+ const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat);
+ if (renderTargetFormatCaps.renderable)
{
for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
{
- D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
- HRESULT result = D3D_OK;
-
- if(depthStencilFormat != D3DFMT_UNKNOWN)
+ const d3d9::D3DFormat &depthStencilFormatInfo = d3d9::GetD3DFormatInfo(DepthStencilFormats[depthStencilIndex]);
+ const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat);
+ if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == D3DFMT_UNKNOWN)
{
- result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
- }
-
- if (SUCCEEDED(result))
- {
- if(depthStencilFormat != D3DFMT_UNKNOWN)
- {
- result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
- }
-
- if (SUCCEEDED(result))
- {
- ConfigDesc newConfig;
- newConfig.renderTargetFormat = d3d9_gl::ConvertBackBufferFormat(renderTargetFormat);
- newConfig.depthStencilFormat = d3d9_gl::ConvertDepthStencilFormat(depthStencilFormat);
- newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
- newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat);
-
- (*configDescList)[numConfigs++] = newConfig;
- }
+ ConfigDesc newConfig;
+ newConfig.renderTargetFormat = renderTargetFormatInfo.internalFormat;
+ newConfig.depthStencilFormat = depthStencilFormatInfo.internalFormat;
+ newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
+ newConfig.fastConfig = (currentDisplayMode.Format == RenderTargetFormats[formatIndex]);
+ newConfig.es3Capable = false;
+
+ (*configDescList)[numConfigs++] = newConfig;
}
}
}
@@ -681,6 +533,7 @@ IDirect3DQuery9* Renderer9::allocateEventQuery()
if (mEventQueryPool.empty())
{
HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
+ UNUSED_ASSERTION_VARIABLE(result);
ASSERT(SUCCEEDED(result));
}
else
@@ -696,7 +549,7 @@ void Renderer9::freeEventQuery(IDirect3DQuery9* query)
{
if (mEventQueryPool.size() > 1000)
{
- query->Release();
+ SafeRelease(query);
}
else
{
@@ -736,9 +589,14 @@ IndexBuffer *Renderer9::createIndexBuffer()
return new IndexBuffer9(this);
}
-BufferStorage *Renderer9::createBufferStorage()
+BufferImpl *Renderer9::createBuffer()
+{
+ return new Buffer9(this);
+}
+
+VertexArrayImpl *Renderer9::createVertexArray()
{
- return new BufferStorage9();
+ return new VertexArray9(this);
}
QueryImpl *Renderer9::createQuery(GLenum type)
@@ -751,10 +609,36 @@ FenceImpl *Renderer9::createFence()
return new Fence9(this);
}
-void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
+TransformFeedbackImpl* Renderer9::createTransformFeedback()
+{
+ return new TransformFeedbackD3D();
+}
+
+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;
+}
+
+bool Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *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 false;
+}
+
+gl::Error Renderer9::generateSwizzle(gl::Texture *texture)
{
- bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates;
- gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates;
+ // Swizzled textures are not available in ES2 or D3D9
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
+{
+ std::vector<bool> &forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates;
+ std::vector<gl::SamplerState> &appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates;
if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0)
{
@@ -769,8 +653,8 @@ void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::Sampl
gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy);
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
- mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset);
- if (mSupportsTextureFilterAnisotropy)
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.baseLevel);
+ if (getRendererExtensions().textureFilterAnisotropic)
{
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy);
}
@@ -778,9 +662,11 @@ void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::Sampl
forceSetSamplers[index] = false;
appliedSamplers[index] = samplerState;
+
+ return gl::Error(GL_NO_ERROR);
}
-void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
+gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
{
int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
int d3dSampler = index + d3dSamplerOffset;
@@ -788,14 +674,16 @@ void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture
unsigned int serial = 0;
bool forceSetTexture = false;
- unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials;
+ std::vector<unsigned int> &appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials;
if (texture)
{
- TextureStorageInterface *texStorage = texture->getNativeTexture();
+ TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation());
+
+ TextureStorage *texStorage = textureImpl->getNativeTexture();
if (texStorage)
{
- TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance());
+ TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage);
d3dTexture = storage9->getBaseTexture();
}
// If we get NULL back from getBaseTexture here, something went wrong
@@ -803,7 +691,8 @@ void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture
ASSERT(d3dTexture != NULL);
serial = texture->getTextureSerial();
- forceSetTexture = texture->hasDirtyImages();
+ forceSetTexture = textureImpl->hasDirtyImages();
+ textureImpl->resetDirty();
}
if (forceSetTexture || appliedSerials[index] != serial)
@@ -812,9 +701,17 @@ void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture
}
appliedSerials[index] = serial;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::setUniformBuffers(const gl::Buffer* /*vertexUniformBuffers*/[], const gl::Buffer* /*fragmentUniformBuffers*/[])
+{
+ // No effect in ES2/D3D9
+ return gl::Error(GL_NO_ERROR);
}
-void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState)
+gl::Error Renderer9::setRasterizerState(const gl::RasterizerState &rasterState)
{
bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0;
@@ -850,12 +747,15 @@ void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState)
}
mForceSetRasterState = false;
+
+ return gl::Error(GL_NO_ERROR);
}
-void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask)
+gl::Error Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
+ unsigned int sampleMask)
{
bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0;
- bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0;
+ bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0;
bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask;
if (blendStateChanged || blendColorChanged)
@@ -906,6 +806,9 @@ void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState
FIXME("Sample alpha to coverage is unimplemented.");
}
+ gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer();
+ GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE;
+
// Set the color mask
bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD;
// Apparently some ATI cards have a bug where a draw with a zero color
@@ -914,8 +817,11 @@ void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState
// drawing is done.
// http://code.google.com/p/angleproject/issues/detail?id=169
- DWORD colorMask = gl_d3d9::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
- blendState.colorMaskBlue, blendState.colorMaskAlpha);
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ DWORD colorMask = gl_d3d9::ConvertColorMask(formatInfo.redBits > 0 && blendState.colorMaskRed,
+ formatInfo.greenBits > 0 && blendState.colorMaskGreen,
+ formatInfo.blueBits > 0 && blendState.colorMaskBlue,
+ formatInfo.alphaBits > 0 && blendState.colorMaskAlpha);
if (colorMask == 0 && !zeroColorMaskAllowed)
{
// Enable green channel, but set blending so nothing will be drawn.
@@ -947,10 +853,12 @@ void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState
}
mForceSetBlendState = false;
+
+ return gl::Error(GL_NO_ERROR);
}
-void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
- int stencilBackRef, bool frontFaceCCW)
+gl::Error Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
+ int stencilBackRef, bool frontFaceCCW)
{
bool depthStencilStateChanged = mForceSetDepthStencilState ||
memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0;
@@ -984,13 +892,10 @@ void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilSt
const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
- if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
- stencilRef != stencilBackRef ||
- depthStencilState.stencilMask != depthStencilState.stencilBackMask)
- {
- ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
- return gl::error(GL_INVALID_OPERATION);
- }
+
+ ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask);
+ ASSERT(stencilRef == stencilBackRef);
+ ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask);
// get the maximum size of the stencil ref
unsigned int maxStencil = (1 << mCurStencilSize) - 1;
@@ -1042,6 +947,8 @@ void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilSt
}
mForceSetDepthStencilState = false;
+
+ return gl::Error(GL_NO_ERROR);
}
void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
@@ -1071,7 +978,7 @@ void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
mForceSetScissor = false;
}
-bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
+void Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
bool ignoreViewport)
{
gl::Rectangle actualViewport = viewport;
@@ -1095,11 +1002,6 @@ bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zF
dxViewport.MinZ = actualZNear;
dxViewport.MaxZ = actualZFar;
- if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
- {
- return false; // Nothing to render
- }
-
float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);
bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
@@ -1152,7 +1054,6 @@ bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zF
}
mForceSetViewport = false;
- return true;
}
bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count)
@@ -1188,14 +1089,15 @@ bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count)
mPrimitiveCount = count - 2;
break;
default:
- return gl::error(GL_INVALID_ENUM, false);
+ UNREACHABLE();
+ return false;
}
return mPrimitiveCount > 0;
}
-gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer)
+gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer)
{
if (!depthbuffer)
{
@@ -1218,7 +1120,8 @@ gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer)
}
}
- gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0));
+ gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(0, new gl::Colorbuffer(this, width, height, GL_NONE, 0));
+ gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(GL_NONE, nullRenderbuffer);
// add nullbuffer to the cache
NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0];
@@ -1239,75 +1142,56 @@ gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer)
return nullbuffer;
}
-bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
+gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
{
// 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.
- gl::Renderbuffer *renderbufferObject = NULL;
- if (framebuffer->getColorbufferType(0) != GL_NONE)
- {
- renderbufferObject = framebuffer->getColorbuffer(0);
- }
- else
+ gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0);
+ if (!attachment)
{
- renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer());
+ attachment = getNullColorbuffer(framebuffer->getDepthbuffer());
}
- if (!renderbufferObject)
+ if (!attachment)
{
- ERR("unable to locate renderbuffer for FBO.");
- return false;
+ return gl::Error(GL_OUT_OF_MEMORY, "Unable to locate renderbuffer for FBO.");
}
bool renderTargetChanged = false;
- unsigned int renderTargetSerial = renderbufferObject->getSerial();
+ unsigned int renderTargetSerial = GetAttachmentSerial(attachment);
if (renderTargetSerial != mAppliedRenderTargetSerial)
{
// Apply the render target on the device
IDirect3DSurface9 *renderTargetSurface = NULL;
- RenderTarget *renderTarget = renderbufferObject->getRenderTarget();
+ RenderTarget9 *renderTarget = d3d9::GetAttachmentRenderTarget(attachment);
if (renderTarget)
{
- renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface();
+ renderTargetSurface = renderTarget->getSurface();
}
if (!renderTargetSurface)
{
- ERR("render target pointer unexpectedly null.");
- return false; // Context must be lost
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal render target pointer unexpectedly null.");
}
mDevice->SetRenderTarget(0, renderTargetSurface);
- renderTargetSurface->Release();
+ SafeRelease(renderTargetSurface);
mAppliedRenderTargetSerial = renderTargetSerial;
renderTargetChanged = true;
}
- gl::Renderbuffer *depthStencil = NULL;
+ gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer();
unsigned int depthbufferSerial = 0;
unsigned int stencilbufferSerial = 0;
- if (framebuffer->getDepthbufferType() != GL_NONE)
+ if (depthStencil)
{
- depthStencil = framebuffer->getDepthbuffer();
- if (!depthStencil)
- {
- ERR("Depth stencil pointer unexpectedly null.");
- return false;
- }
-
- depthbufferSerial = depthStencil->getSerial();
+ depthbufferSerial = GetAttachmentSerial(depthStencil);
}
- else if (framebuffer->getStencilbufferType() != GL_NONE)
+ else if (framebuffer->getStencilbuffer())
{
depthStencil = framebuffer->getStencilbuffer();
- if (!depthStencil)
- {
- ERR("Depth stencil pointer unexpectedly null.");
- return false;
- }
-
- stencilbufferSerial = depthStencil->getSerial();
+ stencilbufferSerial = GetAttachmentSerial(depthStencil);
}
if (depthbufferSerial != mAppliedDepthbufferSerial ||
@@ -1321,21 +1205,20 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
if (depthStencil)
{
IDirect3DSurface9 *depthStencilSurface = NULL;
- RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil();
+ rx::RenderTarget9 *depthStencilRenderTarget = d3d9::GetAttachmentRenderTarget(depthStencil);
if (depthStencilRenderTarget)
{
- depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface();
+ depthStencilSurface = depthStencilRenderTarget->getSurface();
}
if (!depthStencilSurface)
{
- ERR("depth stencil pointer unexpectedly null.");
- return false; // Context must be lost
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil pointer unexpectedly null.");
}
mDevice->SetDepthStencilSurface(depthStencilSurface);
- depthStencilSurface->Release();
+ SafeRelease(depthStencilSurface);
depthSize = depthStencil->getDepthSize();
stencilSize = depthStencil->getStencilSize();
@@ -1366,160 +1249,172 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
{
mForceSetScissor = true;
mForceSetViewport = true;
+ mForceSetBlendState = true;
- mRenderTargetDesc.width = renderbufferObject->getWidth();
- mRenderTargetDesc.height = renderbufferObject->getHeight();
- mRenderTargetDesc.format = renderbufferObject->getActualFormat();
+ mRenderTargetDesc.width = attachment->getWidth();
+ mRenderTargetDesc.height = attachment->getHeight();
+ mRenderTargetDesc.format = attachment->getActualFormat();
mRenderTargetDescInitialized = true;
}
- return true;
+ return gl::Error(GL_NO_ERROR);
}
-GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
+gl::Error Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[],
+ GLint first, GLsizei count, GLsizei instances)
{
TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
- GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
- if (err != GL_NO_ERROR)
+ gl::Error error = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances);
+ if (error.isError())
{
- return err;
+ return error;
}
-
+
return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw);
}
// Applies the indices and element array bindings to the Direct3D 9 device
-GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
+gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
{
- GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
-
- if (err == GL_NO_ERROR)
+ gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
+ if (error.isError())
{
- // Directly binding the storage buffer is not supported for d3d9
- ASSERT(indexInfo->storage == NULL);
+ return error;
+ }
- if (indexInfo->serial != mAppliedIBSerial)
- {
- IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer);
+ // Directly binding the storage buffer is not supported for d3d9
+ ASSERT(indexInfo->storage == NULL);
- mDevice->SetIndices(indexBuffer->getBuffer());
- mAppliedIBSerial = indexInfo->serial;
- }
+ if (indexInfo->serial != mAppliedIBSerial)
+ {
+ IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer);
+
+ mDevice->SetIndices(indexBuffer->getBuffer());
+ mAppliedIBSerial = indexInfo->serial;
}
- return err;
+ return gl::Error(GL_NO_ERROR);
+}
+
+void Renderer9::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[])
+{
+ UNREACHABLE();
}
-void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
+gl::Error Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive)
{
+ ASSERT(!transformFeedbackActive);
+
startScene();
-
+
if (mode == GL_LINE_LOOP)
{
- drawLineLoop(count, GL_NONE, NULL, 0, NULL);
+ return drawLineLoop(count, GL_NONE, NULL, 0, NULL);
}
else if (instances > 0)
{
- StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count);
- if (countingIB)
+ StaticIndexBufferInterface *countingIB = NULL;
+ gl::Error error = getCountingIB(count, &countingIB);
+ if (error.isError())
{
- if (mAppliedIBSerial != countingIB->getSerial())
- {
- IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer());
+ return error;
+ }
- mDevice->SetIndices(indexBuffer->getBuffer());
- mAppliedIBSerial = countingIB->getSerial();
- }
+ if (mAppliedIBSerial != countingIB->getSerial())
+ {
+ IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer());
- for (int i = 0; i < mRepeatDraw; i++)
- {
- mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount);
- }
+ mDevice->SetIndices(indexBuffer->getBuffer());
+ mAppliedIBSerial = countingIB->getSerial();
}
- else
+
+ for (int i = 0; i < mRepeatDraw; i++)
{
- ERR("Could not create a counting index buffer for glDrawArraysInstanced.");
- return gl::error(GL_OUT_OF_MEMORY);
+ 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);
}
}
-void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/)
+gl::Error Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
+ gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/)
{
startScene();
+ int minIndex = static_cast<int>(indexInfo.indexRange.start);
+
if (mode == GL_POINTS)
{
- drawIndexedPoints(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
+ return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer);
}
else if (mode == GL_LINE_LOOP)
{
- drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
+ return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer);
}
else
{
for (int i = 0; i < mRepeatDraw; i++)
{
- GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
- mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount);
+ GLsizei vertexCount = static_cast<int>(indexInfo.indexRange.length()) + 1;
+ mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount);
}
+ return gl::Error(GL_NO_ERROR);
}
}
-void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
+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)
{
gl::Buffer *indexBuffer = elementArrayBuffer;
- BufferStorage *storage = indexBuffer->getStorage();
+ BufferImpl *storage = indexBuffer->getImplementation();
intptr_t offset = reinterpret_cast<intptr_t>(indices);
indices = static_cast<const GLubyte*>(storage->getData()) + offset;
}
unsigned int startIndex = 0;
- if (get32BitIndexSupport())
+ if (getRendererExtensions().elementIndexUint)
{
if (!mLineLoopIB)
{
mLineLoopIB = new StreamingIndexBufferInterface(this);
- if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
+ gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+ if (error.isError())
{
- delete mLineLoopIB;
- mLineLoopIB = NULL;
-
- ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
- return gl::error(GL_OUT_OF_MEMORY);
+ 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)))
{
- ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
- return gl::error(GL_OUT_OF_MEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
}
- // Checked by Renderer9::applyPrimitiveType
- ASSERT(count >= 0);
-
- const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
- if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
+ 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())
{
- ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
- return gl::error(GL_OUT_OF_MEMORY);
+ return error;
}
void* mappedMemory = NULL;
unsigned int offset = 0;
- if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
+ error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
+ if (error.isError())
{
- ERR("Could not map index buffer for GL_LINE_LOOP.");
- return gl::error(GL_OUT_OF_MEMORY);
+ return error;
}
startIndex = static_cast<unsigned int>(offset) / 4;
@@ -1558,10 +1453,10 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
default: UNREACHABLE();
}
- if (!mLineLoopIB->unmapBuffer())
+ error = mLineLoopIB->unmapBuffer();
+ if (error.isError())
{
- ERR("Could not unmap index buffer for GL_LINE_LOOP.");
- return gl::error(GL_OUT_OF_MEMORY);
+ return error;
}
}
else
@@ -1569,13 +1464,11 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
if (!mLineLoopIB)
{
mLineLoopIB = new StreamingIndexBufferInterface(this);
- if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
+ gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT);
+ if (error.isError())
{
- delete mLineLoopIB;
- mLineLoopIB = NULL;
-
- ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP.");
- return gl::error(GL_OUT_OF_MEMORY);
+ SafeDelete(mLineLoopIB);
+ return error;
}
}
@@ -1584,23 +1477,22 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)))
{
- ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
- return gl::error(GL_OUT_OF_MEMORY);
+ 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);
- if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT))
+ gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+ if (error.isError())
{
- ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
- return gl::error(GL_OUT_OF_MEMORY);
+ return error;
}
void* mappedMemory = NULL;
unsigned int offset;
- if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
+ error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
+ if (error.isError())
{
- ERR("Could not map index buffer for GL_LINE_LOOP.");
- return gl::error(GL_OUT_OF_MEMORY);
+ return error;
}
startIndex = static_cast<unsigned int>(offset) / 2;
@@ -1639,10 +1531,10 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
default: UNREACHABLE();
}
- if (!mLineLoopIB->unmapBuffer())
+ error = mLineLoopIB->unmapBuffer();
+ if (error.isError())
{
- ERR("Could not unmap index buffer for GL_LINE_LOOP.");
- return gl::error(GL_OUT_OF_MEMORY);
+ return error;
}
}
@@ -1655,67 +1547,162 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
}
mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
+
+ return gl::Error(GL_NO_ERROR);
}
template <typename T>
-static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex)
+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);
}
-void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
+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)
{
- BufferStorage *storage = elementArrayBuffer->getStorage();
+ BufferImpl *storage = elementArrayBuffer->getImplementation();
intptr_t offset = reinterpret_cast<intptr_t>(indices);
indices = static_cast<const GLubyte*>(storage->getData()) + offset;
}
switch (type)
{
- case GL_UNSIGNED_BYTE: drawPoints<GLubyte>(mDevice, count, indices, minIndex); break;
- case GL_UNSIGNED_SHORT: drawPoints<GLushort>(mDevice, count, indices, minIndex); break;
- case GL_UNSIGNED_INT: drawPoints<GLuint>(mDevice, count, indices, minIndex); break;
- default: UNREACHABLE();
+ 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);
}
}
-void Renderer9::applyShaders(gl::ProgramBinary *programBinary)
+gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **outIB)
{
- unsigned int programBinarySerial = programBinary->getSerial();
- if (programBinarySerial != mAppliedProgramBinarySerial)
+ // Update the counting index buffer if it is not large enough or has not been created yet.
+ if (count <= 65536) // 16-bit indices
{
- ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
- ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
+ const unsigned int spaceNeeded = count * sizeof(unsigned short);
- IDirect3DVertexShader9 *vertexShader = NULL;
- if (vertexExe) vertexShader = ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader();
+ if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded)
+ {
+ SafeDelete(mCountingIB);
+ mCountingIB = new StaticIndexBufferInterface(this);
+ mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
- IDirect3DPixelShader9 *pixelShader = NULL;
- if (pixelExe) pixelShader = ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader();
+ void *mappedMemory = NULL;
+ gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL);
+ if (error.isError())
+ {
+ return error;
+ }
- mDevice->SetPixelShader(pixelShader);
+ unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
+ for (size_t i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+
+ error = mCountingIB->unmapBuffer();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+ else if (getRendererExtensions().elementIndexUint)
+ {
+ const unsigned int spaceNeeded = 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 (size_t 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(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
+ bool rasterizerDiscard, bool transformFeedbackActive)
+{
+ ASSERT(!transformFeedbackActive);
+ ASSERT(!rasterizerDiscard);
+
+ ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout);
+ ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer);
+
+ IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL);
+ IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL);
+
+ 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 = programBinary->getSerial();
+ if (programSerial != mAppliedProgramSerial)
+ {
programBinary->dirtyAllUniforms();
mDxUniformsDirty = true;
-
- mAppliedProgramBinarySerial = programBinarySerial;
+ mAppliedProgramSerial = programSerial;
}
+
+ return gl::Error(GL_NO_ERROR);
}
-void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray)
+gl::Error Renderer9::applyUniforms(const gl::ProgramBinary &programBinary)
{
- for (std::vector<gl::Uniform*>::const_iterator ub = uniformArray->begin(), ue = uniformArray->end(); ub != ue; ++ub)
+ const std::vector<gl::LinkedUniform*> &uniformArray = programBinary.getUniforms();
+
+ for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++)
{
- gl::Uniform *targetUniform = *ub;
+ gl::LinkedUniform *targetUniform = uniformArray[uniformIndex];
if (targetUniform->dirty)
{
@@ -1751,8 +1738,6 @@ void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray
default:
UNREACHABLE();
}
-
- targetUniform->dirty = false;
}
}
@@ -1763,22 +1748,24 @@ void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray
mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4]));
mDxUniformsDirty = false;
}
+
+ return gl::Error(GL_NO_ERROR);
}
-void Renderer9::applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v)
+void Renderer9::applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v)
{
- if (targetUniform->psRegisterIndex >= 0)
+ if (targetUniform->isReferencedByFragmentShader())
{
mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount);
}
- if (targetUniform->vsRegisterIndex >= 0)
+ if (targetUniform->isReferencedByVertexShader())
{
mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount);
}
}
-void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v)
+void Renderer9::applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v)
{
ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
@@ -1794,7 +1781,7 @@ void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v)
applyUniformnfv(targetUniform, (GLfloat*)vector);
}
-void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v)
+void Renderer9::applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v)
{
ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
@@ -1810,29 +1797,60 @@ void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v)
applyUniformnfv(targetUniform, (GLfloat*)vector);
}
-void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
+gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
{
- D3DCOLOR color = D3DCOLOR_ARGB(gl::unorm<8>(clearParams.colorClearValue.alpha),
- gl::unorm<8>(clearParams.colorClearValue.red),
- gl::unorm<8>(clearParams.colorClearValue.green),
- gl::unorm<8>(clearParams.colorClearValue.blue));
+ 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);
- int stencil = clearParams.stencilClearValue & 0x000000FF;
+ DWORD stencil = clearParams.stencilClearValue & 0x000000FF;
unsigned int stencilUnmasked = 0x0;
- if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil())
+ if (clearParams.clearStencil && frameBuffer->hasStencil())
{
- unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
+ unsigned int stencilSize = gl::GetInternalFormatInfo((frameBuffer->getStencilbuffer()->getActualFormat())).stencilBits;
stencilUnmasked = (0x1 << stencilSize) - 1;
}
- bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha;
-
- const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
+ const bool needMaskedStencilClear = clearParams.clearStencil &&
(clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
- const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
- !(clearParams.colorMaskRed && clearParams.colorMaskGreen &&
- clearParams.colorMaskBlue && alphaUnmasked);
+
+ bool needMaskedColorClear = false;
+ D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0);
+ if (clearColor)
+ {
+ const gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer();
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat());
+ const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
+
+ color = D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
+ gl::unorm<8>((formatInfo.redBits == 0 && actualFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red),
+ gl::unorm<8>((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
+ gl::unorm<8>((formatInfo.blueBits == 0 && actualFormatInfo.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)
{
@@ -1893,7 +1911,7 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
- if (clearParams.mask & GL_COLOR_BUFFER_BIT)
+ if (clearColor)
{
mDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
gl_d3d9::ConvertColorMask(clearParams.colorMaskRed,
@@ -1906,7 +1924,7 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f
mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
}
- if (stencilUnmasked != 0x0 && (clearParams.mask & GL_STENCIL_BUFFER_BIT))
+ if (stencilUnmasked != 0x0 && clearParams.clearStencil)
{
mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
@@ -1962,7 +1980,7 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f
startScene();
mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
- if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
+ if (clearParams.clearDepth)
{
mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
@@ -1974,24 +1992,26 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f
mMaskedClearSavedState->Apply();
}
}
- else if (clearParams.mask)
+ else if (clearColor || clearParams.clearDepth || clearParams.clearStencil)
{
DWORD dxClearFlags = 0;
- if (clearParams.mask & GL_COLOR_BUFFER_BIT)
+ if (clearColor)
{
dxClearFlags |= D3DCLEAR_TARGET;
}
- if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
+ if (clearParams.clearDepth)
{
dxClearFlags |= D3DCLEAR_ZBUFFER;
}
- if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
+ if (clearParams.clearStencil)
{
dxClearFlags |= D3DCLEAR_STENCIL;
}
mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil);
}
+
+ return gl::Error(GL_NO_ERROR);
}
void Renderer9::markAllStateDirty()
@@ -2008,19 +2028,24 @@ void Renderer9::markAllStateDirty()
mForceSetViewport = true;
mForceSetBlendState = true;
- for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
+ ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexTextureSerials.size());
+ for (unsigned int i = 0; i < mForceSetVertexSamplerStates.size(); i++)
{
mForceSetVertexSamplerStates[i] = true;
mCurVertexTextureSerials[i] = 0;
}
- for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++)
+
+ ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelTextureSerials.size());
+ for (unsigned int i = 0; i < mForceSetPixelSamplerStates.size(); i++)
{
mForceSetPixelSamplerStates[i] = true;
mCurPixelTextureSerials[i] = 0;
}
mAppliedIBSerial = 0;
- mAppliedProgramBinarySerial = 0;
+ mAppliedVertexShader = NULL;
+ mAppliedPixelShader = NULL;
+ mAppliedProgramSerial = 0;
mDxUniformsDirty = true;
mVertexDeclarationCache.markStateDirty();
@@ -2028,11 +2053,11 @@ void Renderer9::markAllStateDirty()
void Renderer9::releaseDeviceResources()
{
- while (!mEventQueryPool.empty())
+ for (size_t i = 0; i < mEventQueryPool.size(); i++)
{
- mEventQueryPool.back()->Release();
- mEventQueryPool.pop_back();
+ SafeRelease(mEventQueryPool[i]);
}
+ mEventQueryPool.clear();
SafeRelease(mMaskedClearSavedState);
@@ -2043,15 +2068,14 @@ void Renderer9::releaseDeviceResources()
SafeDelete(mVertexDataManager);
SafeDelete(mIndexDataManager);
SafeDelete(mLineLoopIB);
+ SafeDelete(mCountingIB);
for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
{
SafeDelete(mNullColorbufferCache[i].buffer);
}
-
}
-
void Renderer9::notifyDeviceLost()
{
mDeviceLost = true;
@@ -2221,7 +2245,7 @@ bool Renderer9::resetRemovedDevice()
// 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.
- deinitialize();
+ release();
return (initialize() == EGL_SUCCESS);
}
@@ -2255,97 +2279,6 @@ GUID Renderer9::getAdapterIdentifier() const
return mAdapterIdentifier.DeviceIdentifier;
}
-void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
-{
- for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
- {
- HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
- TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
-
- multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
- }
-}
-
-bool Renderer9::getBGRATextureSupport() const
-{
- // DirectX 9 always supports BGRA
- return true;
-}
-
-bool Renderer9::getDXT1TextureSupport()
-{
- return mDXT1TextureSupport;
-}
-
-bool Renderer9::getDXT3TextureSupport()
-{
- return mDXT3TextureSupport;
-}
-
-bool Renderer9::getDXT5TextureSupport()
-{
- return mDXT5TextureSupport;
-}
-
-bool Renderer9::getDepthTextureSupport() const
-{
- return mDepthTextureSupport;
-}
-
-bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable)
-{
- *filtering = mFloat32FilterSupport;
- *renderable = mFloat32RenderSupport;
- return mFloat32TextureSupport;
-}
-
-bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable)
-{
- *filtering = mFloat16FilterSupport;
- *renderable = mFloat16RenderSupport;
- return mFloat16TextureSupport;
-}
-
-bool Renderer9::getLuminanceTextureSupport()
-{
- return mLuminanceTextureSupport;
-}
-
-bool Renderer9::getLuminanceAlphaTextureSupport()
-{
- return mLuminanceAlphaTextureSupport;
-}
-
-bool Renderer9::getTextureFilterAnisotropySupport() const
-{
- return mSupportsTextureFilterAnisotropy;
-}
-
-float Renderer9::getTextureMaxAnisotropy() const
-{
- if (mSupportsTextureFilterAnisotropy)
- {
- return static_cast<float>(mDeviceCaps.MaxAnisotropy);
- }
- return 1.0f;
-}
-
-bool Renderer9::getEventQuerySupport()
-{
- return mEventQuerySupport;
-}
-
-unsigned int Renderer9::getMaxVertexTextureImageUnits() const
-{
- META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
- return mVertexTextureSupport ? MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 : 0;
-}
-
-unsigned int Renderer9::getMaxCombinedTextureImageUnits() const
-{
- return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
-}
-
unsigned int Renderer9::getReservedVertexUniformVectors() const
{
return 2; // dx_ViewAdjust and dx_DepthRange.
@@ -2356,36 +2289,14 @@ unsigned int Renderer9::getReservedFragmentUniformVectors() const
return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange.
}
-unsigned int Renderer9::getMaxVertexUniformVectors() const
-{
- return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors();
-}
-
-unsigned int Renderer9::getMaxFragmentUniformVectors() const
-{
- const int maxPixelConstantVectors = (getMajorShaderModel() >= 3) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 : MAX_PIXEL_CONSTANT_VECTORS_SM2;
-
- return maxPixelConstantVectors - getReservedFragmentUniformVectors();
-}
-
-unsigned int Renderer9::getMaxVaryingVectors() const
+unsigned int Renderer9::getReservedVertexUniformBuffers() const
{
- return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
+ return 0;
}
-bool Renderer9::getNonPower2TextureSupport() const
+unsigned int Renderer9::getReservedFragmentUniformBuffers() const
{
- return mSupportsNonPower2Textures;
-}
-
-bool Renderer9::getOcclusionQuerySupport() const
-{
- return mOcclusionQuerySupport;
-}
-
-bool Renderer9::getInstancingSupport() const
-{
- return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
+ return 0;
}
bool Renderer9::getShareHandleSupport() const
@@ -2394,11 +2305,6 @@ bool Renderer9::getShareHandleSupport() const
return (mD3d9Ex != NULL) && !gl::perfActive();
}
-bool Renderer9::getDerivativeInstructionSupport() const
-{
- return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
-}
-
bool Renderer9::getPostSubBufferSupport() const
{
return true;
@@ -2409,34 +2315,6 @@ int Renderer9::getMajorShaderModel() const
return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
}
-float Renderer9::getMaxPointSize() const
-{
- // Point size clamped at 1.0f for SM2
- return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f;
-}
-
-int Renderer9::getMaxViewportDimension() const
-{
- int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()),
- (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
- return maxTextureDimension;
-}
-
-int Renderer9::getMaxTextureWidth() const
-{
- return (int)mDeviceCaps.MaxTextureWidth;
-}
-
-int Renderer9::getMaxTextureHeight() const
-{
- return (int)mDeviceCaps.MaxTextureHeight;
-}
-
-bool Renderer9::get32BitIndexSupport() const
-{
- return mDeviceCaps.MaxVertexIndex >= (1 << 16);
-}
-
DWORD Renderer9::getCapsDeclTypes() const
{
return mDeviceCaps.DeclTypes;
@@ -2452,127 +2330,45 @@ int Renderer9::getMaxSwapInterval() const
return mMaxSwapInterval;
}
-int Renderer9::getMaxSupportedSamples() const
-{
- return mMaxSupportedSamples;
-}
-
-int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const
-{
- if (requested == 0)
- {
- return requested;
- }
-
- std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format);
- if (itr == mMultiSampleSupport.end())
- {
- if (format == D3DFMT_UNKNOWN)
- return 0;
- return -1;
- }
-
- for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i)
- {
- if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE)
- {
- return i;
- }
- }
-
- return -1;
-}
-
-unsigned int Renderer9::getMaxRenderTargets() const
-{
- // we do not support MRT in d3d9
- return 1;
-}
-
-D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat)
-{
- switch (internalformat)
- {
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT32_OES:
- case GL_DEPTH24_STENCIL8_OES:
- return D3DFMT_INTZ;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- return D3DFMT_DXT1;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- return D3DFMT_DXT3;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- return D3DFMT_DXT5;
- case GL_RGBA32F_EXT:
- case GL_RGB32F_EXT:
- case GL_ALPHA32F_EXT:
- case GL_LUMINANCE32F_EXT:
- case GL_LUMINANCE_ALPHA32F_EXT:
- return D3DFMT_A32B32G32R32F;
- case GL_RGBA16F_EXT:
- case GL_RGB16F_EXT:
- case GL_ALPHA16F_EXT:
- case GL_LUMINANCE16F_EXT:
- case GL_LUMINANCE_ALPHA16F_EXT:
- return D3DFMT_A16B16G16R16F;
- case GL_LUMINANCE8_EXT:
- if (getLuminanceTextureSupport())
- {
- return D3DFMT_L8;
- }
- break;
- case GL_LUMINANCE8_ALPHA8_EXT:
- if (getLuminanceAlphaTextureSupport())
- {
- return D3DFMT_A8L8;
- }
- break;
- case GL_RGB8_OES:
- case GL_RGB565:
- return D3DFMT_X8R8G8B8;
- }
-
- return D3DFMT_A8R8G8B8;
-}
-
-bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
+bool Renderer9::copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source)
{
bool result = false;
if (source && dest)
{
- TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance());
- TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance());
+ TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source);
+ TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest);
- int levels = source9->levelCount();
+ int levels = source9->getLevelCount();
for (int i = 0; i < levels; ++i)
{
IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false);
IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false);
-
+
result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
- if (srcSurf) srcSurf->Release();
- if (dstSurf) dstSurf->Release();
+ SafeRelease(srcSurf);
+ SafeRelease(dstSurf);
if (!result)
+ {
return false;
+ }
}
}
return result;
}
-bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source)
+bool Renderer9::copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source)
{
bool result = false;
if (source && dest)
{
- TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance());
- TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance());
- int levels = source9->levelCount();
+ TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source);
+ TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest);
+ int levels = source9->getLevelCount();
for (int f = 0; f < 6; f++)
{
for (int i = 0; i < levels; i++)
@@ -2582,11 +2378,13 @@ bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureSto
result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
- if (srcSurf) srcSurf->Release();
- if (dstSurf) dstSurf->Release();
+ SafeRelease(srcSurf);
+ SafeRelease(dstSurf);
if (!result)
+ {
return false;
+ }
}
}
}
@@ -2594,6 +2392,20 @@ bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureSto
return result;
}
+bool Renderer9::copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source)
+{
+ // 3D textures are not available in the D3D9 backend.
+ UNREACHABLE();
+ return false;
+}
+
+bool Renderer9::copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source)
+{
+ // 2D array textures are not supported by the D3D9 backend.
+ UNREACHABLE();
+ return false;
+}
+
D3DPOOL Renderer9::getBufferPool(DWORD usage) const
{
if (mD3d9Ex != NULL)
@@ -2611,8 +2423,8 @@ D3DPOOL Renderer9::getBufferPool(DWORD usage) const
return D3DPOOL_DEFAULT;
}
-bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
+bool Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
{
RECT rect;
rect.left = sourceRect.x;
@@ -2620,11 +2432,11 @@ bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sou
rect.right = sourceRect.x + sourceRect.width;
rect.bottom = sourceRect.y + sourceRect.height;
- return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level);
+ return mBlit->copy2D(framebuffer, rect, destFormat, xoffset, yoffset, storage, level);
}
-bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
+bool Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
{
RECT rect;
rect.left = sourceRect.x;
@@ -2632,18 +2444,36 @@ bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sou
rect.right = sourceRect.x + sourceRect.width;
rect.bottom = sourceRect.y + sourceRect.height;
- return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level);
+ return mBlit->copyCube(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level);
+}
+
+bool Renderer9::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+{
+ // 3D textures are not available in the D3D9 backend.
+ UNREACHABLE();
+ return false;
+}
+
+bool Renderer9::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+{
+ // 2D array textures are not available in the D3D9 backend.
+ UNREACHABLE();
+ return false;
}
bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect,
- bool blitRenderTarget, bool blitDepthStencil)
+ const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter)
{
+ ASSERT(filter == GL_NEAREST);
+
endScene();
if (blitRenderTarget)
{
- gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0);
- gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0);
+ gl::FramebufferAttachment *readBuffer = readFramebuffer->getColorbuffer(0);
+ gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getColorbuffer(0);
RenderTarget9 *readRenderTarget = NULL;
RenderTarget9 *drawRenderTarget = NULL;
IDirect3DSurface9* readSurface = NULL;
@@ -2651,11 +2481,11 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
if (readBuffer)
{
- readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget());
+ readRenderTarget = d3d9::GetAttachmentRenderTarget(readBuffer);
}
if (drawBuffer)
{
- drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget());
+ drawRenderTarget = d3d9::GetAttachmentRenderTarget(drawBuffer);
}
if (readRenderTarget)
@@ -2673,6 +2503,9 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
return gl::error(GL_OUT_OF_MEMORY, false);
}
+ gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
+ gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
+
RECT srcRect;
srcRect.left = readRect.x;
srcRect.right = readRect.x + readRect.width;
@@ -2685,10 +2518,79 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
dstRect.top = drawRect.y;
dstRect.bottom = drawRect.y + drawRect.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 = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
- readSurface->Release();
- drawSurface->Release();
+ SafeRelease(readSurface);
+ SafeRelease(drawSurface);
if (FAILED(result))
{
@@ -2697,10 +2599,10 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
}
}
- if (blitDepthStencil)
+ if (blitDepth || blitStencil)
{
- gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer();
- gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer();
+ gl::FramebufferAttachment *readBuffer = readFramebuffer->getDepthOrStencilbuffer();
+ gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer();
RenderTarget9 *readDepthStencil = NULL;
RenderTarget9 *drawDepthStencil = NULL;
IDirect3DSurface9* readSurface = NULL;
@@ -2708,11 +2610,11 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
if (readBuffer)
{
- readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil());
+ readDepthStencil = d3d9::GetAttachmentRenderTarget(readBuffer);
}
if (drawBuffer)
{
- drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil());
+ drawDepthStencil = d3d9::GetAttachmentRenderTarget(drawBuffer);
}
if (readDepthStencil)
@@ -2732,8 +2634,8 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE);
- readSurface->Release();
- drawSurface->Release();
+ SafeRelease(readSurface);
+ SafeRelease(drawSurface);
if (FAILED(result))
{
@@ -2745,18 +2647,20 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
return true;
}
-void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
- GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
+gl::Error Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+ GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels)
{
+ ASSERT(pack.pixelBuffer.get() == NULL);
+
RenderTarget9 *renderTarget = NULL;
IDirect3DSurface9 *surface = NULL;
- gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
+ gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
if (colorbuffer)
{
- renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
+ renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer);
}
-
+
if (renderTarget)
{
surface = renderTarget->getSurface();
@@ -2765,7 +2669,7 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz
if (!surface)
{
// context must be lost
- return;
+ return gl::Error(GL_NO_ERROR);
}
D3DSURFACE_DESC desc;
@@ -2774,20 +2678,20 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz
if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
{
UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
- surface->Release();
- return gl::error(GL_OUT_OF_MEMORY);
+ SafeRelease(surface);
+ return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments.");
}
HRESULT result;
IDirect3DSurface9 *systemSurface = NULL;
- bool directToPixels = !packReverseRowOrder && packAlignment <= 4 && getShareHandleSupport() &&
+ bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && getShareHandleSupport() &&
x == 0 && y == 0 && UINT(width) == desc.Width && UINT(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 = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
- D3DPOOL_SYSTEMMEM, &systemSurface, &pixels);
+ D3DPOOL_SYSTEMMEM, &systemSurface, reinterpret_cast<void**>(&pixels));
if (FAILED(result))
{
// Try again without the shared handle
@@ -2802,38 +2706,36 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- surface->Release();
- return gl::error(GL_OUT_OF_MEMORY);
+ SafeRelease(surface);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels.");
}
}
result = mDevice->GetRenderTargetData(surface, systemSurface);
- surface->Release();
- surface = NULL;
+ SafeRelease(surface);
if (FAILED(result))
{
- systemSurface->Release();
+ SafeRelease(systemSurface);
// It turns out that D3D will sometimes produce more error
// codes than those documented.
if (d3d9::isDeviceLostError(result))
{
notifyDeviceLost();
- return gl::error(GL_OUT_OF_MEMORY);
}
else
{
UNREACHABLE();
- return;
}
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data.");
}
if (directToPixels)
{
- systemSurface->Release();
- return;
+ SafeRelease(systemSurface);
+ return gl::Error(GL_NO_ERROR);
}
RECT rect;
@@ -2848,252 +2750,79 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz
if (FAILED(result))
{
UNREACHABLE();
- systemSurface->Release();
+ SafeRelease(systemSurface);
- return; // No sensible error to generate
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target.");
}
- unsigned char *dest = (unsigned char*)pixels;
- unsigned short *dest16 = (unsigned short*)pixels;
-
- unsigned char *source;
+ uint8_t *source;
int inputPitch;
- if (packReverseRowOrder)
+ if (pack.reverseRowOrder)
{
- source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
+ source = reinterpret_cast<uint8_t*>(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
inputPitch = -lock.Pitch;
}
else
{
- source = (unsigned char*)lock.pBits;
+ source = reinterpret_cast<uint8_t*>(lock.pBits);
inputPitch = lock.Pitch;
}
- unsigned int fastPixelSize = 0;
-
- if (desc.Format == D3DFMT_A8R8G8B8 &&
- format == GL_BGRA_EXT &&
- type == GL_UNSIGNED_BYTE)
- {
- fastPixelSize = 4;
- }
- else if ((desc.Format == D3DFMT_A4R4G4B4 &&
- format == GL_BGRA_EXT &&
- type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) ||
- (desc.Format == D3DFMT_A1R5G5B5 &&
- format == GL_BGRA_EXT &&
- type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT))
- {
- fastPixelSize = 2;
- }
- else if (desc.Format == D3DFMT_A16B16G16R16F &&
- format == GL_RGBA &&
- type == GL_HALF_FLOAT_OES)
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+ const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3dFormatInfo.internalFormat);
+ if (sourceFormatInfo.format == format && sourceFormatInfo.type == type)
{
- fastPixelSize = 8;
+ // Direct copy possible
+ for (int y = 0; y < rect.bottom - rect.top; y++)
+ {
+ memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes);
+ }
}
- else if (desc.Format == D3DFMT_A32B32G32R32F &&
- format == GL_RGBA &&
- type == GL_FLOAT)
+ else
{
- fastPixelSize = 16;
- }
+ const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+ ColorCopyFunction fastCopyFunc = sourceD3DFormatInfo.getFastCopyFunction(format, type);
- for (int j = 0; j < rect.bottom - rect.top; j++)
- {
- if (fastPixelSize != 0)
- {
- // Fast path for formats which require no translation:
- // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE
- // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT
- // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT
- // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES
- // D3DFMT_A32B32G32R32F to RGBA/FLOAT
- //
- // Note that buffers with no alpha go through the slow path below.
- memcpy(dest + j * outputPitch,
- source + j * inputPitch,
- (rect.right - rect.left) * fastPixelSize);
- continue;
- }
- else if (desc.Format == D3DFMT_A8R8G8B8 &&
- format == GL_RGBA &&
- type == GL_UNSIGNED_BYTE)
- {
- // Fast path for swapping red with blue
- for (int i = 0; i < rect.right - rect.left; i++)
- {
- unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
- *(unsigned int*)(dest + 4 * i + j * outputPitch) =
- (argb & 0xFF00FF00) | // Keep alpha and green
- (argb & 0x00FF0000) >> 16 | // Move red to blue
- (argb & 0x000000FF) << 16; // Move blue to red
- }
- continue;
- }
+ const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(format, type);
+ const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat);
- for (int i = 0; i < rect.right - rect.left; i++)
+ if (fastCopyFunc)
{
- float r;
- float g;
- float b;
- float a;
-
- switch (desc.Format)
+ // Fast copy is possible through some special function
+ for (int y = 0; y < rect.bottom - rect.top; y++)
{
- case D3DFMT_R5G6B5:
+ for (int x = 0; x < rect.right - rect.left; x++)
{
- unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);
+ uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes;
+ const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
- a = 1.0f;
- b = (rgb & 0x001F) * (1.0f / 0x001F);
- g = (rgb & 0x07E0) * (1.0f / 0x07E0);
- r = (rgb & 0xF800) * (1.0f / 0xF800);
+ fastCopyFunc(src, dest);
}
- break;
- case D3DFMT_A1R5G5B5:
- {
- unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);
-
- a = (argb & 0x8000) ? 1.0f : 0.0f;
- b = (argb & 0x001F) * (1.0f / 0x001F);
- g = (argb & 0x03E0) * (1.0f / 0x03E0);
- r = (argb & 0x7C00) * (1.0f / 0x7C00);
- }
- break;
- case D3DFMT_A8R8G8B8:
- {
- unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
-
- a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
- b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
- g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
- r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
- }
- break;
- case D3DFMT_X8R8G8B8:
- {
- unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);
-
- a = 1.0f;
- b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
- g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
- r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
- }
- break;
- case D3DFMT_A2R10G10B10:
- {
- unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
-
- a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
- b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
- g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
- r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
- }
- break;
- case D3DFMT_A32B32G32R32F:
- {
- // float formats in D3D are stored rgba, rather than the other way round
- r = *((float*)(source + 16 * i + j * inputPitch) + 0);
- g = *((float*)(source + 16 * i + j * inputPitch) + 1);
- b = *((float*)(source + 16 * i + j * inputPitch) + 2);
- a = *((float*)(source + 16 * i + j * inputPitch) + 3);
- }
- break;
- case D3DFMT_A16B16G16R16F:
- {
- // float formats in D3D are stored rgba, rather than the other way round
- r = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0));
- g = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1));
- b = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2));
- a = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3));
- }
- break;
- default:
- UNIMPLEMENTED(); // FIXME
- UNREACHABLE();
- return;
}
-
- switch (format)
+ }
+ else
+ {
+ uint8_t temp[sizeof(gl::ColorF)];
+ for (int y = 0; y < rect.bottom - rect.top; y++)
{
- case GL_RGBA:
- switch (type)
+ for (int x = 0; x < rect.right - rect.left; x++)
{
- case GL_UNSIGNED_BYTE:
- dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
- dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
- dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
- dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
- break;
- default: UNREACHABLE();
- }
- break;
- case GL_BGRA_EXT:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
- dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
- dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
- dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
- break;
- case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
- // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
- // this type is packed as follows:
- // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------
- // | 4th | 3rd | 2nd | 1st component |
- // --------------------------------------------------------------------------------
- // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
- dest16[i + j * outputPitch / sizeof(unsigned short)] =
- ((unsigned short)(15 * a + 0.5f) << 12)|
- ((unsigned short)(15 * r + 0.5f) << 8) |
- ((unsigned short)(15 * g + 0.5f) << 4) |
- ((unsigned short)(15 * b + 0.5f) << 0);
- break;
- case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
- // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
- // this type is packed as follows:
- // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------
- // | 4th | 3rd | 2nd | 1st component |
- // --------------------------------------------------------------------------------
- // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
- dest16[i + j * outputPitch / sizeof(unsigned short)] =
- ((unsigned short)( a + 0.5f) << 15) |
- ((unsigned short)(31 * r + 0.5f) << 10) |
- ((unsigned short)(31 * g + 0.5f) << 5) |
- ((unsigned short)(31 * b + 0.5f) << 0);
- break;
- default: UNREACHABLE();
- }
- break;
- case GL_RGB:
- switch (type)
- {
- case GL_UNSIGNED_SHORT_5_6_5:
- dest16[i + j * outputPitch / sizeof(unsigned short)] =
- ((unsigned short)(31 * b + 0.5f) << 0) |
- ((unsigned short)(63 * g + 0.5f) << 5) |
- ((unsigned short)(31 * r + 0.5f) << 11);
- break;
- case GL_UNSIGNED_BYTE:
- dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
- dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
- dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
- break;
- default: UNREACHABLE();
+ uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes;
+ const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
+
+ // readFunc and writeFunc will be using the same type of color, CopyTexImage
+ // will not allow the copy otherwise.
+ sourceD3DFormatInfo.colorReadFunction(src, temp);
+ destFormatTypeInfo.colorWriteFunction(temp, dest);
}
- break;
- default: UNREACHABLE();
}
}
}
systemSurface->UnlockRect();
+ SafeRelease(systemSurface);
- systemSurface->Release();
+ return gl::Error(GL_NO_ERROR);
}
RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth)
@@ -3114,14 +2843,34 @@ RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth)
return renderTarget;
}
-RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
+RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples)
{
RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples);
return renderTarget;
}
-ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type)
+ShaderImpl *Renderer9::createShader(GLenum type)
+{
+ return new ShaderD3D(type, this);
+}
+
+ProgramImpl *Renderer9::createProgram()
+{
+ return new ProgramD3D(this);
+}
+
+void Renderer9::releaseShaderCompiler()
+{
+ ShaderD3D::releaseCompiler();
+}
+
+ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type,
+ const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+ bool separatedOutputBuffers)
{
+ // Transform feedback is not supported in ES2 or D3D9
+ ASSERT(transformFeedbackVaryings.size() == 0);
+
ShaderExecutable9 *executable = NULL;
switch (type)
@@ -3152,8 +2901,13 @@ ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length,
return executable;
}
-ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround)
+ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
+ const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+ bool separatedOutputBuffers, D3DWorkaroundType workaround)
{
+ // Transform feedback is not supported in ES2 or D3D9
+ ASSERT(transformFeedbackVaryings.size() == 0);
+
const char *profile = NULL;
switch (type)
@@ -3169,20 +2923,67 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const cha
return NULL;
}
- // ANGLE issue 486:
- // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
- UINT optimizationFlags = (workaround == ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER ? D3DCOMPILE_SKIP_OPTIMIZATION : ANGLE_COMPILE_OPTIMIZATION_LEVEL);
+ UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL;
+
+ if (workaround == ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION)
+ {
+ flags = D3DCOMPILE_SKIP_OPTIMIZATION;
+ }
+ else if (workaround == ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION)
+ {
+ flags = D3DCOMPILE_OPTIMIZATION_LEVEL3;
+ }
+ else ASSERT(workaround == ANGLE_D3D_WORKAROUND_NONE);
+
+ if (gl::perfActive())
+ {
+#ifndef NDEBUG
+ flags = D3DCOMPILE_SKIP_OPTIMIZATION;
+#endif
+
+ flags |= D3DCOMPILE_DEBUG;
+
+ std::string sourcePath = getTempPath();
+ std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL);
+ writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
+ }
+
+ // 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.
+ const UINT extraFlags[] =
+ {
+ flags,
+ flags | D3DCOMPILE_AVOID_FLOW_CONTROL,
+ flags | D3DCOMPILE_PREFER_FLOW_CONTROL
+ };
- ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, optimizationFlags, true);
+ const static char *extraFlagNames[] =
+ {
+ "default",
+ "avoid flow control",
+ "prefer flow control"
+ };
+
+ int attempts = ArraySize(extraFlags);
+
+ ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts);
if (!binary)
+ {
return NULL;
+ }
- ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type);
- binary->Release();
+ ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
+ transformFeedbackVaryings, separatedOutputBuffers);
+ SafeRelease(binary);
return executable;
}
+rx::UniformStorage *Renderer9::createUniformStorage(size_t storageSize)
+{
+ return new UniformStorage(storageSize);
+}
+
bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
{
return mBlit->boxFilter(source, dest);
@@ -3223,7 +3024,7 @@ bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *s
{
Image9::copyLockableSurfaces(surf, source);
result = mDevice->UpdateSurface(surf, NULL, dest, NULL);
- surf->Release();
+ SafeRelease(surf);
}
}
else
@@ -3260,14 +3061,42 @@ TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain)
return new TextureStorage9_2D(this, swapChain9);
}
-TextureStorage *Renderer9::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
+TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
+{
+ return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels);
+}
+
+TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels)
+{
+ return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels);
+}
+
+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)
{
- return new TextureStorage9_2D(this, levels, internalformat, usage, forceRenderable, width, height);
+ // 2D array textures are not supported by the D3D9 backend.
+ UNREACHABLE();
+
+ return NULL;
}
-TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
+TextureImpl *Renderer9::createTexture(GLenum target)
{
- return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size);
+ switch(target)
+ {
+ case GL_TEXTURE_2D: return new TextureD3D_2D(this);
+ case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this);
+ default: UNREACHABLE();
+ }
+
+ return NULL;
}
bool Renderer9::getLUID(LUID *adapterLuid) const
@@ -3284,4 +3113,19 @@ bool Renderer9::getLUID(LUID *adapterLuid) const
return false;
}
+rx::VertexConversionType Renderer9::getVertexConversionType(const gl::VertexFormat &vertexFormat) const
+{
+ return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).conversionType;
+}
+
+GLenum Renderer9::getVertexComponentType(const gl::VertexFormat &vertexFormat) const
+{
+ return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).componentType;
+}
+
+void Renderer9::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const
+{
+ d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, outExtensions);
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
new file mode 100644
index 0000000000..dd5f30268a
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
@@ -0,0 +1,342 @@
+//
+// 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 LIBGLESV2_RENDERER_RENDERER9_H_
+#define LIBGLESV2_RENDERER_RENDERER9_H_
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
+#include "libGLESv2/renderer/d3d/d3d9/ShaderCache.h"
+#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/RenderTarget.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace rx
+{
+class VertexDataManager;
+class IndexDataManager;
+class StreamingIndexBufferInterface;
+class StaticIndexBufferInterface;
+struct TranslatedAttribute;
+class Blit9;
+
+class Renderer9 : public Renderer
+{
+ public:
+ Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay);
+ virtual ~Renderer9();
+
+ static Renderer9 *makeRenderer9(Renderer *renderer);
+
+ virtual EGLint initialize();
+ virtual bool resetDevice();
+
+ virtual int generateConfigs(ConfigDesc **configDescList);
+ virtual void deleteConfigs(ConfigDesc *configDescList);
+
+ void startScene();
+ void endScene();
+
+ virtual void sync(bool block);
+
+ virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
+
+ IDirect3DQuery9* allocateEventQuery();
+ void freeEventQuery(IDirect3DQuery9* query);
+
+ // resource creation
+ IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length);
+ IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length);
+ HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer);
+ HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer);
+ virtual gl::Error generateSwizzle(gl::Texture *texture);
+ virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
+ virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture);
+
+ virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]);
+
+ virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
+ virtual gl::Error setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
+ unsigned int sampleMask);
+ virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
+ int stencilBackRef, bool frontFaceCCW);
+
+ virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+ virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
+ bool ignoreViewport);
+
+ virtual gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer);
+ virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
+ bool rasterizerDiscard, bool transformFeedbackActive);
+ virtual gl::Error applyUniforms(const gl::ProgramBinary &programBinary);
+ virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount);
+ virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[],
+ GLint first, GLsizei count, GLsizei instances);
+ virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
+
+ virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]);
+
+ virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive);
+ virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
+ gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
+
+ virtual gl::Error clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
+
+ virtual void markAllStateDirty();
+
+ // lost device
+ void notifyDeviceLost();
+ virtual bool isDeviceLost();
+ virtual bool testDeviceLost(bool notify);
+ virtual bool testDeviceResettable();
+
+ IDirect3DDevice9 *getDevice() { return mDevice; }
+ virtual DWORD getAdapterVendor() const;
+ virtual std::string getRendererDescription() const;
+ virtual GUID getAdapterIdentifier() const;
+
+ virtual unsigned int getReservedVertexUniformVectors() const;
+ virtual unsigned int getReservedFragmentUniformVectors() const;
+ virtual unsigned int getReservedVertexUniformBuffers() const;
+ virtual unsigned int getReservedFragmentUniformBuffers() const;
+ virtual bool getShareHandleSupport() const;
+ virtual bool getPostSubBufferSupport() const;
+
+ virtual int getMajorShaderModel() const;
+ DWORD getCapsDeclTypes() const;
+ virtual int getMinSwapInterval() const;
+ virtual int getMaxSwapInterval() const;
+
+ // Pixel operations
+ virtual bool copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source);
+ virtual bool copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source);
+ virtual bool copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source);
+ virtual bool copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source);
+
+ virtual bool copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level);
+ virtual bool copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level);
+ virtual bool copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
+ virtual bool copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
+
+ virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
+ const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter);
+
+ virtual gl::Error readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+ GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
+
+ // RenderTarget creation
+ virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth);
+ virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples);
+
+ // Shader creation
+ virtual ShaderImpl *createShader(GLenum type);
+ virtual ProgramImpl *createProgram();
+
+ // Shader operations
+ virtual void releaseShaderCompiler();
+ virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
+ const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+ bool separatedOutputBuffers);
+ virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
+ const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+ bool separatedOutputBuffers, D3DWorkaroundType workaround);
+ virtual UniformStorage *createUniformStorage(size_t storageSize);
+
+ // Image operations
+ virtual Image *createImage();
+ virtual void generateMipmap(Image *dest, Image *source);
+ virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
+ virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
+ virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels);
+ virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
+ virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
+
+ // Texture creation
+ virtual TextureImpl *createTexture(GLenum target);
+
+ // Buffer creation
+ virtual BufferImpl *createBuffer();
+ virtual VertexBuffer *createVertexBuffer();
+ virtual IndexBuffer *createIndexBuffer();
+
+ // Vertex Array creation
+ virtual VertexArrayImpl *createVertexArray();
+
+ // Query and Fence creation
+ virtual QueryImpl *createQuery(GLenum type);
+ virtual FenceImpl *createFence();
+
+ // Transform Feedback creation
+ virtual TransformFeedbackImpl* createTransformFeedback();
+
+ // Buffer-to-texture and Texture-to-buffer copies
+ virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const;
+ virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+ GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
+
+ // D3D9-renderer specific methods
+ bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
+
+ D3DPOOL getTexturePool(DWORD usage) const;
+
+ virtual bool getLUID(LUID *adapterLuid) const;
+ virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const;
+ virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Renderer9);
+
+ virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const;
+
+ void release();
+
+ void applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v);
+ void applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v);
+ void applyUniformnbv(gl::LinkedUniform *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);
+
+ bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
+ gl::FramebufferAttachment *getNullColorbuffer(gl::FramebufferAttachment *depthbuffer);
+
+ D3DPOOL getBufferPool(DWORD usage) const;
+
+ HMODULE mD3d9Module;
+ HDC mDc;
+
+ 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;
+
+ bool mDeviceLost;
+ D3DCAPS9 mDeviceCaps;
+ D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
+
+ D3DPRIMITIVETYPE mPrimitiveType;
+ int mPrimitiveCount;
+ GLsizei mRepeatDraw;
+
+ bool mSceneStarted;
+ int mMinSwapInterval;
+ int mMaxSwapInterval;
+
+ bool mVertexTextureSupport;
+
+ // current render target states
+ unsigned int mAppliedRenderTargetSerial;
+ unsigned int mAppliedDepthbufferSerial;
+ unsigned int mAppliedStencilbufferSerial;
+ bool mDepthStencilInitialized;
+ bool mRenderTargetDescInitialized;
+ rx::RenderTarget::Desc mRenderTargetDesc;
+ unsigned int mCurStencilSize;
+ unsigned int mCurDepthSize;
+
+ IDirect3DStateBlock9 *mMaskedClearSavedState;
+
+ // previously set render states
+ bool mForceSetDepthStencilState;
+ gl::DepthStencilState mCurDepthStencilState;
+ int mCurStencilRef;
+ int mCurStencilBackRef;
+ bool mCurFrontFaceCCW;
+
+ bool mForceSetRasterState;
+ gl::RasterizerState mCurRasterState;
+
+ bool mForceSetScissor;
+ gl::Rectangle mCurScissor;
+ bool mScissorEnabled;
+
+ bool mForceSetViewport;
+ gl::Rectangle mCurViewport;
+ float mCurNear;
+ float mCurFar;
+ float mCurDepthFront;
+
+ bool mForceSetBlendState;
+ gl::BlendState mCurBlendState;
+ gl::ColorF mCurBlendColor;
+ GLuint mCurSampleMask;
+
+ // Currently applied sampler states
+ std::vector<bool> mForceSetVertexSamplerStates;
+ std::vector<gl::SamplerState> mCurVertexSamplerStates;
+
+ std::vector<bool> mForceSetPixelSamplerStates;
+ std::vector<gl::SamplerState> mCurPixelSamplerStates;
+
+ // Currently applied textures
+ std::vector<unsigned int> mCurVertexTextureSerials;
+ std::vector<unsigned int> mCurPixelTextureSerials;
+
+ unsigned int mAppliedIBSerial;
+ IDirect3DVertexShader9 *mAppliedVertexShader;
+ IDirect3DPixelShader9 *mAppliedPixelShader;
+ unsigned int mAppliedProgramSerial;
+
+ rx::dx_VertexConstants mVertexConstants;
+ rx::dx_PixelConstants mPixelConstants;
+ bool mDxUniformsDirty;
+
+ // 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;
+
+};
+
+}
+#endif // LIBGLESV2_RENDERER_RENDERER9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h
index 4391ac271a..2ad3022839 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderCache.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h
@@ -12,6 +12,10 @@
#include "common/debug.h"
+#include <cstddef>
+#include <unordered_map>
+#include <string>
+
namespace rx
{
template <typename ShaderObject>
@@ -53,7 +57,7 @@ class ShaderCache
// Random eviction policy.
if (mMap.size() >= kMaxMapSize)
{
- mMap.begin()->second->Release();
+ SafeRelease(mMap.begin()->second);
mMap.erase(mMap.begin());
}
@@ -67,7 +71,7 @@ class ShaderCache
{
for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it)
{
- it->second->Release();
+ SafeRelease(it->second);
}
mMap.clear();
@@ -88,15 +92,7 @@ class ShaderCache
return mDevice->CreatePixelShader(function, shader);
}
-#ifndef HASH_MAP
-# ifdef _MSC_VER
-# define HASH_MAP stdext::hash_map
-# else
-# define HASH_MAP std::unordered_map
-# endif
-#endif
-
- typedef HASH_MAP<std::string, ShaderObject*> Map;
+ typedef std::unordered_map<std::string, ShaderObject*> Map;
Map mMap;
IDirect3DDevice9 *mDevice;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp
index 5decf9664d..bc7120461b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -8,7 +7,7 @@
// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader
// executable implementation details.
-#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h"
+#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h"
#include "common/debug.h"
@@ -31,14 +30,8 @@ ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirec
ShaderExecutable9::~ShaderExecutable9()
{
- if (mVertexExecutable)
- {
- mVertexExecutable->Release();
- }
- if (mPixelExecutable)
- {
- mPixelExecutable->Release();
- }
+ SafeRelease(mVertexExecutable);
+ SafeRelease(mPixelExecutable);
}
ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutable *executable)
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h
index fa1e6c2844..fa1e6c2844 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp
index dd8895d18d..0aeaabb1ca 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp
@@ -1,15 +1,15 @@
-#include "precompiled.h"
//
-// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
+// 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 "libGLESv2/renderer/d3d9/SwapChain9.h"
-#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d9/Renderer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h"
+#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
namespace rx
{
@@ -35,43 +35,21 @@ SwapChain9::~SwapChain9()
void SwapChain9::release()
{
- if (mSwapChain)
- {
- mSwapChain->Release();
- mSwapChain = NULL;
- }
-
- if (mBackBuffer)
- {
- mBackBuffer->Release();
- mBackBuffer = NULL;
- }
-
- if (mDepthStencil)
- {
- mDepthStencil->Release();
- mDepthStencil = NULL;
- }
-
- if (mRenderTarget)
- {
- mRenderTarget->Release();
- mRenderTarget = NULL;
- }
-
- if (mOffscreenTexture)
- {
- mOffscreenTexture->Release();
- mOffscreenTexture = NULL;
- }
+ SafeRelease(mSwapChain);
+ SafeRelease(mBackBuffer);
+ SafeRelease(mDepthStencil);
+ SafeRelease(mRenderTarget);
+ SafeRelease(mOffscreenTexture);
if (mWindow)
+ {
mShareHandle = NULL;
+ }
}
static DWORD convertInterval(EGLint interval)
{
-#if ANGLE_FORCE_VSYNC_OFF
+#ifdef ANGLE_FORCE_VSYNC_OFF
return D3DPRESENT_INTERVAL_IMMEDIATE;
#else
switch(interval)
@@ -111,29 +89,10 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
// 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.
- if (mSwapChain)
- {
- mSwapChain->Release();
- mSwapChain = NULL;
- }
-
- if (mBackBuffer)
- {
- mBackBuffer->Release();
- mBackBuffer = NULL;
- }
-
- if (mOffscreenTexture)
- {
- mOffscreenTexture->Release();
- mOffscreenTexture = NULL;
- }
-
- if (mDepthStencil)
- {
- mDepthStencil->Release();
- mDepthStencil = NULL;
- }
+ SafeRelease(mSwapChain);
+ SafeRelease(mBackBuffer);
+ SafeRelease(mOffscreenTexture);
+ SafeRelease(mDepthStencil);
HANDLE *pShareHandle = NULL;
if (!mWindow && mRenderer->getShareHandleSupport())
@@ -141,9 +100,10 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
pShareHandle = &mShareHandle;
}
+ const d3d9::TextureFormat &backBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mBackBufferFormat);
result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
- gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat), D3DPOOL_DEFAULT,
- &mOffscreenTexture, pShareHandle);
+ backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT, &mOffscreenTexture,
+ pShareHandle);
if (FAILED(result))
{
ERR("Could not create offscreen texture: %08lX", result);
@@ -187,15 +147,17 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
ASSERT(SUCCEEDED(result));
- oldRenderTarget->Release();
+ SafeRelease(oldRenderTarget);
}
+ const d3d9::TextureFormat &depthBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mDepthBufferFormat);
+
if (mWindow)
{
D3DPRESENT_PARAMETERS presentParameters = {0};
- presentParameters.AutoDepthStencilFormat = gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat);
+ presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat;
presentParameters.BackBufferCount = 1;
- presentParameters.BackBufferFormat = gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat);
+ presentParameters.BackBufferFormat = backBufferd3dFormatInfo.renderFormat;
presentParameters.EnableAutoDepthStencil = FALSE;
presentParameters.Flags = 0;
presentParameters.hDeviceWindow = mWindow;
@@ -247,7 +209,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
if (mDepthBufferFormat != GL_NONE)
{
result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight,
- gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat),
+ depthBufferd3dFormatInfo.renderFormat,
D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL);
if (FAILED(result))
@@ -276,7 +238,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
}
// parameters should be validated/clamped by caller
-EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint)
{
if (!mSwapChain)
{
@@ -356,6 +318,14 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
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 == 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.
@@ -370,6 +340,7 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
// Increments refcount on surface.
// caller must Release() the returned surface
+// TODO: remove the AddRef to match SwapChain11
IDirect3DSurface9 *SwapChain9::getRenderTarget()
{
if (mRenderTarget)
@@ -382,6 +353,7 @@ IDirect3DSurface9 *SwapChain9::getRenderTarget()
// Increments refcount on surface.
// caller must Release() the returned surface
+// TODO: remove the AddRef to match SwapChain11
IDirect3DSurface9 *SwapChain9::getDepthStencil()
{
if (mDepthStencil)
@@ -394,6 +366,7 @@ IDirect3DSurface9 *SwapChain9::getDepthStencil()
// Increments refcount on texture.
// caller must Release() the returned texture
+// TODO: remove the AddRef to match SwapChain11
IDirect3DTexture9 *SwapChain9::getOffscreenTexture()
{
if (mOffscreenTexture)
@@ -434,10 +407,10 @@ void SwapChain9::recreate()
return;
}
- mSwapChain->Release();
+ SafeRelease(mSwapChain);
mSwapChain = newSwapChain;
- mBackBuffer->Release();
+ SafeRelease(mBackBuffer);
result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
ASSERT(SUCCEEDED(result));
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h
index 16a62bd86f..4d756f80d1 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h
@@ -25,7 +25,7 @@ class SwapChain9 : public SwapChain
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 EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint);
virtual void recreate();
virtual IDirect3DSurface9 *getRenderTarget();
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp
index 2486a9a5bf..f44e33db18 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp
@@ -1,6 +1,5 @@
-#include "precompiled.h"
//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -9,18 +8,20 @@
// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
// D3D9 texture.
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/d3d9/Renderer9.h"
-#include "libGLESv2/renderer/d3d9/TextureStorage9.h"
-#include "libGLESv2/renderer/d3d9/SwapChain9.h"
-#include "libGLESv2/renderer/d3d9/RenderTarget9.h"
-#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h"
+#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
+#include "libGLESv2/renderer/d3d/TextureD3D.h"
#include "libGLESv2/Texture.h"
+#include "libGLESv2/main.h"
namespace rx
{
TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage)
- : mLodOffset(0),
+ : mTopLevel(0),
mRenderer(Renderer9::makeRenderer9(renderer)),
mD3DUsage(usage),
mD3DPool(mRenderer->getTexturePool(usage))
@@ -37,46 +38,24 @@ TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage)
return static_cast<TextureStorage9*>(storage);
}
-DWORD TextureStorage9::GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable)
+DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget)
{
DWORD d3dusage = 0;
- if (d3dfmt == D3DFMT_INTZ)
+ 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(forceRenderable || (TextureStorage9::IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
+ else if (renderTarget && (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN))
{
d3dusage |= D3DUSAGE_RENDERTARGET;
}
+
return d3dusage;
}
-bool TextureStorage9::IsTextureFormatRenderable(D3DFORMAT format)
-{
- if (format == D3DFMT_INTZ)
- {
- return true;
- }
- switch(format)
- {
- case D3DFMT_L8:
- case D3DFMT_A8L8:
- case D3DFMT_DXT1:
- case D3DFMT_DXT3:
- case D3DFMT_DXT5:
- return false;
- case D3DFMT_A8R8G8B8:
- case D3DFMT_X8R8G8B8:
- case D3DFMT_A16B16G16R16F:
- case D3DFMT_A32B32G32R32F:
- return true;
- default:
- UNREACHABLE();
- }
-
- return false;
-}
bool TextureStorage9::isRenderTarget() const
{
@@ -98,27 +77,29 @@ DWORD TextureStorage9::getUsage() const
return mD3DUsage;
}
-int TextureStorage9::getLodOffset() const
+int TextureStorage9::getTopLevel() const
{
- return mLodOffset;
+ return mTopLevel;
}
-int TextureStorage9::levelCount()
+int TextureStorage9::getLevelCount() const
{
- return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0;
+ return getBaseTexture() ? (getBaseTexture()->GetLevelCount() - getTopLevel()) : 0;
}
-TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET)
+TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain)
+ : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET)
{
IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture();
mTexture = surfaceTexture;
mRenderTarget = NULL;
initializeRenderTarget();
+ initializeSerials(1, 1);
}
-TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
- : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable))
+TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
+ : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
{
mTexture = NULL;
mRenderTarget = NULL;
@@ -127,9 +108,11 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum in
if (width > 0 && height > 0)
{
IDirect3DDevice9 *device = mRenderer->getDevice();
- gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
- HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(),
- mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL);
+ const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+ d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel);
+ UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels;
+
+ HRESULT result = device->CreateTexture(width, height, creationLevels, getUsage(), d3dFormatInfo.texFormat, getPool(), &mTexture, NULL);
if (FAILED(result))
{
@@ -139,16 +122,13 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum in
}
initializeRenderTarget();
+ initializeSerials(getLevelCount(), 1);
}
TextureStorage9_2D::~TextureStorage9_2D()
{
- if (mTexture)
- {
- mTexture->Release();
- }
-
- delete mRenderTarget;
+ SafeRelease(mTexture);
+ SafeDelete(mRenderTarget);
}
TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage)
@@ -165,11 +145,12 @@ IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty)
if (mTexture)
{
- HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface);
+ HRESULT result = mTexture->GetSurfaceLevel(level + mTopLevel, &surface);
+ UNUSED_ASSERTION_VARIABLE(result);
ASSERT(SUCCEEDED(result));
// With managed textures the driver needs to be informed of updates to the lower mipmap levels
- if (level + mLodOffset != 0 && isManaged() && dirty)
+ if (level + mTopLevel != 0 && isManaged() && dirty)
{
mTexture->AddDirtyRect(NULL);
}
@@ -178,23 +159,28 @@ IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty)
return surface;
}
-RenderTarget *TextureStorage9_2D::getRenderTarget()
+RenderTarget *TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/)
{
return mRenderTarget;
}
-void TextureStorage9_2D::generateMipmap(int level)
+void TextureStorage9_2D::generateMipmaps()
{
- IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false);
- IDirect3DSurface9 *lower = getSurfaceLevel(level, true);
+ // Base level must already be defined
- if (upper != NULL && lower != NULL)
+ for (int level = 1; level < getLevelCount(); level++)
{
- mRenderer->boxFilter(upper, lower);
- }
+ IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false);
+ IDirect3DSurface9 *lower = getSurfaceLevel(level, true);
+
+ if (upper != NULL && lower != NULL)
+ {
+ mRenderer->boxFilter(upper, lower);
+ }
- if (upper != NULL) upper->Release();
- if (lower != NULL) lower->Release();
+ SafeRelease(upper);
+ SafeRelease(lower);
+ }
}
IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const
@@ -214,8 +200,8 @@ void TextureStorage9_2D::initializeRenderTarget()
}
}
-TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
- : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable))
+TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
+ : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
{
mTexture = NULL;
for (int i = 0; i < 6; ++i)
@@ -229,9 +215,11 @@ TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenu
{
IDirect3DDevice9 *device = mRenderer->getDevice();
int height = size;
- gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
- HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(),
- mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL);
+ const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+ d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel);
+ UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels;
+
+ HRESULT result = device->CreateCubeTexture(size, creationLevels, getUsage(), d3dFormatInfo.texFormat, getPool(), &mTexture, NULL);
if (FAILED(result))
{
@@ -241,18 +229,16 @@ TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenu
}
initializeRenderTarget();
+ initializeSerials(getLevelCount() * 6, 6);
}
TextureStorage9_Cube::~TextureStorage9_Cube()
{
- if (mTexture)
- {
- mTexture->Release();
- }
+ SafeRelease(mTexture);
for (int i = 0; i < 6; ++i)
{
- delete mRenderTarget[i];
+ SafeDelete(mRenderTarget[i]);
}
}
@@ -271,7 +257,8 @@ IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, in
if (mTexture)
{
D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget);
- HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface);
+ HRESULT result = mTexture->GetCubeMapSurface(face, level + mTopLevel, &surface);
+ UNUSED_ASSERTION_VARIABLE(result);
ASSERT(SUCCEEDED(result));
// With managed textures the driver needs to be informed of updates to the lower mipmap levels
@@ -284,23 +271,31 @@ IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, in
return surface;
}
-RenderTarget *TextureStorage9_Cube::getRenderTarget(GLenum faceTarget)
+RenderTarget *TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index)
{
- return mRenderTarget[gl::TextureCubeMap::faceIndex(faceTarget)];
+ return mRenderTarget[index.layerIndex];
}
-void TextureStorage9_Cube::generateMipmap(int face, int level)
+void TextureStorage9_Cube::generateMipmaps()
{
- IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1, false);
- IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true);
+ // Base level must already be defined
- if (upper != NULL && lower != NULL)
+ for (int faceIndex = 0; faceIndex < 6; faceIndex++)
{
- mRenderer->boxFilter(upper, lower);
- }
+ for (int level = 1; level < getLevelCount(); level++)
+ {
+ IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1, false);
+ IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, true);
- if (upper != NULL) upper->Release();
- if (lower != NULL) lower->Release();
+ if (upper != NULL && lower != NULL)
+ {
+ mRenderer->boxFilter(upper, lower);
+ }
+
+ SafeRelease(upper);
+ SafeRelease(lower);
+ }
+ }
}
IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h
index 86f551a131..e698c7dd56 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -11,7 +11,7 @@
#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_
#define LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_
-#include "libGLESv2/renderer/TextureStorage.h"
+#include "libGLESv2/renderer/d3d/TextureStorage.h"
#include "common/debug.h"
namespace rx
@@ -20,37 +20,34 @@ class Renderer9;
class SwapChain9;
class RenderTarget;
class RenderTarget9;
-class Blit;
class TextureStorage9 : public TextureStorage
{
public:
- TextureStorage9(Renderer *renderer, DWORD usage);
virtual ~TextureStorage9();
static TextureStorage9 *makeTextureStorage9(TextureStorage *storage);
- static DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable);
- static bool IsTextureFormatRenderable(D3DFORMAT format);
+ static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget);
D3DPOOL getPool() const;
DWORD getUsage() const;
virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0;
- virtual RenderTarget *getRenderTarget() { return NULL; }
- virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return NULL; }
- virtual void generateMipmap(int level) {};
- virtual void generateMipmap(int face, int level) {};
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0;
+ virtual void generateMipmaps() = 0;
- virtual int getLodOffset() const;
+ virtual int getTopLevel() const;
virtual bool isRenderTarget() const;
virtual bool isManaged() const;
- virtual int levelCount();
+ virtual int getLevelCount() const;
protected:
- int mLodOffset;
+ int mTopLevel;
Renderer9 *mRenderer;
+ TextureStorage9(Renderer *renderer, DWORD usage);
+
private:
DISALLOW_COPY_AND_ASSIGN(TextureStorage9);
@@ -62,15 +59,15 @@ class TextureStorage9_2D : public TextureStorage9
{
public:
TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain);
- TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
+ TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
virtual ~TextureStorage9_2D();
static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage);
IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty);
- virtual RenderTarget *getRenderTarget();
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
virtual IDirect3DBaseTexture9 *getBaseTexture() const;
- virtual void generateMipmap(int level);
+ virtual void generateMipmaps();
private:
DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D);
@@ -84,15 +81,15 @@ class TextureStorage9_2D : public TextureStorage9
class TextureStorage9_Cube : public TextureStorage9
{
public:
- TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
+ TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels);
virtual ~TextureStorage9_Cube();
static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage);
IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty);
- virtual RenderTarget *getRenderTarget(GLenum faceTarget);
+ virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
virtual IDirect3DBaseTexture9 *getBaseTexture() const;
- virtual void generateMipmap(int face, int level);
+ virtual void generateMipmaps();
private:
DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h
new file mode 100644
index 0000000000..66a6c64d81
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h
@@ -0,0 +1,43 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexArray9.h: Defines the rx::VertexArray9 class which implements rx::VertexArrayImpl.
+
+#ifndef LIBGLESV2_RENDERER_VERTEXARRAY9_H_
+#define LIBGLESV2_RENDERER_VERTEXARRAY9_H_
+
+#include "libGLESv2/renderer/VertexArrayImpl.h"
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+class Renderer9;
+
+class VertexArray9 : public VertexArrayImpl
+{
+ public:
+ VertexArray9(rx::Renderer9 *renderer)
+ : VertexArrayImpl(),
+ mRenderer(renderer)
+ {
+ }
+
+ virtual ~VertexArray9() { }
+
+ virtual void setElementArrayBuffer(const gl::Buffer *buffer) { }
+ virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { }
+ virtual void setAttributeDivisor(size_t idx, GLuint divisor) { }
+ virtual void enableAttribute(size_t idx, bool enabledState) { }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VertexArray9);
+
+ rx::Renderer9 *mRenderer;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_VERTEXARRAY9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp
new file mode 100644
index 0000000000..4cf7779118
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp
@@ -0,0 +1,233 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
+#include "libGLESv2/renderer/vertexconversion.h"
+#include "libGLESv2/renderer/BufferImpl.h"
+#include "libGLESv2/VertexAttribute.h"
+#include "libGLESv2/Buffer.h"
+
+namespace rx
+{
+
+VertexBuffer9::VertexBuffer9(rx::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);
+}
+
+VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer));
+ return static_cast<VertexBuffer9*>(vertexBuffer);
+}
+
+gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+ GLint start, GLsizei count, GLsizei instances, unsigned int offset)
+{
+ if (!mVertexBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+ }
+
+ gl::Buffer *buffer = attrib.buffer.get();
+
+ int inputStride = gl::ComputeVertexAttributeStride(attrib);
+ int elementSize = gl::ComputeVertexAttributeTypeSize(attrib);
+
+ DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
+
+ uint8_t *mapPtr = NULL;
+
+ unsigned int mapSize;
+ gl::Error error = spaceRequired(attrib, count, instances, &mapSize);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ 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 = NULL;
+ if (attrib.enabled)
+ {
+ if (buffer)
+ {
+ BufferImpl *storage = buffer->getImplementation();
+ input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset);
+ }
+ else
+ {
+ input = static_cast<const uint8_t*>(attrib.pointer);
+ }
+ }
+ else
+ {
+ input = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
+ }
+
+ if (instances == 0 || attrib.divisor == 0)
+ {
+ input += inputStride * start;
+ }
+
+ gl::VertexFormat vertexFormat(attrib, currentValue.Type);
+ const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat);
+ 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);
+}
+
+gl::Error VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
+ unsigned int *outSpaceRequired) const
+{
+ return spaceRequired(attrib, count, instances, outSpaceRequired);
+}
+
+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;
+}
+
+gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
+ unsigned int *outSpaceRequired) const
+{
+ gl::VertexFormat vertexFormat(attrib, GL_FLOAT);
+ const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat);
+
+ if (attrib.enabled)
+ {
+ unsigned int elementCount = 0;
+ if (instances == 0 || attrib.divisor == 0)
+ {
+ elementCount = count;
+ }
+ else
+ {
+ // Round up to divisor, if possible
+ elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
+ }
+
+ if (d3d9VertexInfo.outputElementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
+ {
+ if (outSpaceRequired)
+ {
+ *outSpaceRequired = d3d9VertexInfo.outputElementSize * elementCount;
+ }
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
+ }
+ }
+ else
+ {
+ const unsigned int elementSize = 4;
+ if (outSpaceRequired)
+ {
+ *outSpaceRequired = elementSize * 4;
+ }
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h
new file mode 100644
index 0000000000..bdcf4bb64a
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h
@@ -0,0 +1,54 @@
+//
+// 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 LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
+#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
+
+#include "libGLESv2/renderer/d3d/VertexBuffer.h"
+
+namespace rx
+{
+class Renderer9;
+
+class VertexBuffer9 : public VertexBuffer
+{
+ public:
+ explicit VertexBuffer9(rx::Renderer9 *renderer);
+ virtual ~VertexBuffer9();
+
+ virtual gl::Error initialize(unsigned int size, bool dynamicUsage);
+
+ static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer);
+
+ virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+ GLint start, GLsizei count, GLsizei instances, unsigned int offset);
+
+ virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const;
+
+ virtual unsigned int getBufferSize() const;
+ virtual gl::Error setBufferSize(unsigned int size);
+ virtual gl::Error discard();
+
+ IDirect3DVertexBuffer9 *getBuffer() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VertexBuffer9);
+
+ rx::Renderer9 *mRenderer;
+
+ IDirect3DVertexBuffer9 *mVertexBuffer;
+ unsigned int mBufferSize;
+ bool mDynamicUsage;
+
+ gl::Error spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
+ unsigned int *outSpaceRequired) const;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp
index e5c8a14232..cefd786f11 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp
@@ -1,4 +1,3 @@
-#include "precompiled.h"
//
// 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
@@ -7,10 +6,11 @@
// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations.
+#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h"
+#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
+#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/renderer/d3d9/VertexBuffer9.h"
-#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h"
+#include "libGLESv2/VertexAttribute.h"
namespace rx
{
@@ -36,20 +36,31 @@ VertexDeclarationCache::~VertexDeclarationCache()
{
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
- if (mVertexDeclCache[i].vertexDeclaration)
- {
- mVertexDeclCache[i].vertexDeclaration->Release();
- }
+ SafeRelease(mVertexDeclCache[i].vertexDeclaration);
}
}
-GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw)
+gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw)
{
*repeatDraw = 1;
int indexedAttribute = gl::MAX_VERTEX_ATTRIBS;
int instancedAttribute = gl::MAX_VERTEX_ATTRIBS;
+ if (instances == 0)
+ {
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++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
@@ -70,12 +81,14 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl
}
}
- if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS)
- {
- return GL_INVALID_OPERATION;
- }
+ // 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 != gl::MAX_VERTEX_ATTRIBS);
}
+ D3DCAPS9 caps;
+ device->GetDeviceCaps(&caps);
+
D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1];
D3DVERTEXELEMENT9 *element = &elements[0];
@@ -134,9 +147,12 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl
mAppliedVBs[stream].offset = attributes[i].offset;
}
+ gl::VertexFormat vertexFormat(*attributes[i].attribute, GL_FLOAT);
+ const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexFormat);
+
element->Stream = stream;
element->Offset = 0;
- element->Type = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDeclType(*attributes[i].attribute) : D3DDECLTYPE_FLOAT4;
+ element->Type = d3d9VertexInfo.nativeFormat;
element->Method = D3DDECLMETHOD_DEFAULT;
element->Usage = D3DDECLUSAGE_TEXCOORD;
element->UsageIndex = programBinary->getSemanticIndex(i);
@@ -172,7 +188,7 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl
mLastSetVDecl = entry->vertexDeclaration;
}
- return GL_NO_ERROR;
+ return gl::Error(GL_NO_ERROR);
}
}
@@ -188,19 +204,23 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl
if (lastCache->vertexDeclaration != NULL)
{
- lastCache->vertexDeclaration->Release();
- 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));
- device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
+ 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_NO_ERROR;
+ return gl::Error(GL_NO_ERROR);
}
void VertexDeclarationCache::markStateDirty()
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h
index 3fc024a9ba..9af36e0d7a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h
@@ -9,7 +9,8 @@
#ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_
#define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_
-#include "libGLESv2/renderer/VertexDataManager.h"
+#include "libGLESv2/Error.h"
+#include "libGLESv2/renderer/d3d/VertexDataManager.h"
namespace gl
{
@@ -25,7 +26,7 @@ class VertexDeclarationCache
VertexDeclarationCache();
~VertexDeclarationCache();
- GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw);
+ gl::Error applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw);
void markStateDirty();
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp
new file mode 100644
index 0000000000..f3acaf7987
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp
@@ -0,0 +1,588 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+#include "libGLESv2/renderer/generatemip.h"
+#include "libGLESv2/renderer/loadimage.h"
+#include "libGLESv2/renderer/copyimage.h"
+#include "libGLESv2/renderer/vertexconversion.h"
+
+namespace rx
+{
+
+namespace d3d9
+{
+
+const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z')));
+const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L')));
+
+struct D3D9FastCopyFormat
+{
+ GLenum destFormat;
+ GLenum destType;
+ ColorCopyFunction copyFunction;
+
+ D3D9FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction)
+ : destFormat(destFormat), destType(destType), copyFunction(copyFunction)
+ { }
+
+ bool operator<(const D3D9FastCopyFormat& other) const
+ {
+ return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0;
+ }
+};
+
+typedef std::multimap<D3DFORMAT, D3D9FastCopyFormat> D3D9FastCopyMap;
+
+static D3D9FastCopyMap BuildFastCopyMap()
+{
+ D3D9FastCopyMap map;
+
+ map.insert(std::make_pair(D3DFMT_A8R8G8B8, D3D9FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8)));
+
+ return map;
+}
+
+// A map to determine the pixel size and mip generation function of a given D3D format
+typedef std::map<D3DFORMAT, D3DFormat> D3D9FormatInfoMap;
+
+D3DFormat::D3DFormat()
+ : pixelBytes(0),
+ blockWidth(0),
+ blockHeight(0),
+ internalFormat(GL_NONE),
+ mipGenerationFunction(NULL),
+ colorReadFunction(NULL),
+ fastCopyFunctions()
+{
+}
+
+ColorCopyFunction D3DFormat::getFastCopyFunction(GLenum format, GLenum type) const
+{
+ FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type));
+ return (iter != fastCopyFunctions.end()) ? iter->second : NULL;
+}
+
+static inline void InsertD3DFormatInfo(D3D9FormatInfoMap *map, D3DFORMAT format, GLuint bits, GLuint blockWidth,
+ GLuint blockHeight, GLenum internalFormat, MipGenerationFunction mipFunc,
+ ColorReadFunction colorReadFunc)
+{
+ D3DFormat info;
+ info.pixelBytes = bits / 8;
+ info.blockWidth = blockWidth;
+ info.blockHeight = blockHeight;
+ info.internalFormat = internalFormat;
+ info.mipGenerationFunction = mipFunc;
+ info.colorReadFunction = colorReadFunc;
+
+ static const D3D9FastCopyMap fastCopyMap = BuildFastCopyMap();
+ std::pair<D3D9FastCopyMap::const_iterator, D3D9FastCopyMap::const_iterator> fastCopyIter = fastCopyMap.equal_range(format);
+ for (D3D9FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++)
+ {
+ info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction));
+ }
+
+ map->insert(std::make_pair(format, info));
+}
+
+static D3D9FormatInfoMap BuildD3D9FormatInfoMap()
+{
+ D3D9FormatInfoMap map;
+
+ // | D3DFORMAT | S |W |H | Internal format | Mip generation function | Color read function |
+ InsertD3DFormatInfo(&map, D3DFMT_NULL, 0, 0, 0, GL_NONE, NULL, NULL );
+ InsertD3DFormatInfo(&map, D3DFMT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL );
+
+ InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, GL_LUMINANCE8_EXT, GenerateMip<L8>, ReadColor<L8, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, GL_ALPHA8_EXT, GenerateMip<A8>, ReadColor<A8, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<A8L8>, ReadColor<A8L8, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, GL_BGRA4_ANGLEX, GenerateMip<B4G4R4A4>, ReadColor<B4G4R4A4, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, GL_BGR5_A1_ANGLEX, GenerateMip<B5G5R5A1>, ReadColor<B5G5R5A1, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, GL_RGB565, GenerateMip<R5G6B5>, ReadColor<R5G6B5, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, ReadColor<B8G8R8X8, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_R16F, 16, 1, 1, GL_R16F_EXT, GenerateMip<R16F>, ReadColor<R16F, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_G16R16F, 32, 1, 1, GL_RG16F_EXT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A16B16G16R16F, 64, 1, 1, GL_RGBA16F_EXT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>);
+ InsertD3DFormatInfo(&map, D3DFMT_R32F, 32, 1, 1, GL_R32F_EXT, GenerateMip<R32F>, ReadColor<R32F, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_G32R32F, 64, 1, 1, GL_RG32F_EXT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A32B32G32R32F, 128, 1, 1, GL_RGBA32F_EXT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>);
+
+ InsertD3DFormatInfo(&map, D3DFMT_D16, 16, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL );
+ InsertD3DFormatInfo(&map, D3DFMT_D24S8, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL );
+ InsertD3DFormatInfo(&map, D3DFMT_D24X8, 32, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL );
+ InsertD3DFormatInfo(&map, D3DFMT_D32, 32, 1, 1, GL_DEPTH_COMPONENT32_OES, NULL, NULL );
+
+ InsertD3DFormatInfo(&map, D3DFMT_INTZ, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL );
+
+ InsertD3DFormatInfo(&map, D3DFMT_DXT1, 64, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL );
+ InsertD3DFormatInfo(&map, D3DFMT_DXT3, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL );
+ InsertD3DFormatInfo(&map, D3DFMT_DXT5, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL );
+
+ return map;
+}
+
+const D3DFormat &GetD3DFormatInfo(D3DFORMAT format)
+{
+ static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap();
+ D3D9FormatInfoMap::const_iterator iter = infoMap.find(format);
+ if (iter != infoMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ static const D3DFormat defaultInfo;
+ return defaultInfo;
+ }
+}
+
+
+
+typedef std::pair<GLint, InitializeTextureDataFunction> InternalFormatInitialzerPair;
+typedef std::map<GLint, InitializeTextureDataFunction> InternalFormatInitialzerMap;
+
+static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap()
+{
+ 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;
+}
+
+// Each GL internal format corresponds to one D3D format and data loading function.
+// Due to not all formats being available all the time, some of the function/format types are wrapped
+// in templates that perform format support queries on a Renderer9 object which is supplied
+// when requesting the function or format.
+
+typedef bool(*FallbackPredicateFunction)();
+
+template <FallbackPredicateFunction pred, LoadImageFunction prefered, LoadImageFunction fallback>
+static void FallbackLoad(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)
+{
+ if (pred())
+ {
+ prefered(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch);
+ }
+ else
+ {
+ fallback(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch);
+ }
+}
+
+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_NULL),
+ renderFormat(D3DFMT_NULL),
+ 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()
+{
+ D3D9FormatMap map;
+
+ // | 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, FallbackLoad<gl::supportsSSE2, LoadA8ToBGRA8_SSE2, 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, FallbackLoad<gl::supportsSSE2, LoadRGBA8ToBGRA8_SSE2, 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_UNKNOWN, LoadToNative<GLubyte, 1> );
+ InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, D3DFMT_A8L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 2> );
+
+ 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, const gl::VertexFormat &vertexFormat)
+{
+ static bool initialized = false;
+ static DWORD intializedDeclTypes = 0;
+ static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
+ if (!initialized)
+ {
+ 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;
+ intializedDeclTypes = supportedDeclTypes;
+ }
+
+ ASSERT(intializedDeclTypes == supportedDeclTypes);
+
+ // Pure integer attributes only supported in ES3.0
+ ASSERT(!vertexFormat.mPureInteger);
+ return formatConverters[ComputeTypeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1];
+}
+
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h
new file mode 100644
index 0000000000..f26fe43b36
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h
@@ -0,0 +1,74 @@
+//
+// 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 LIBGLESV2_RENDERER_FORMATUTILS9_H_
+#define LIBGLESV2_RENDERER_FORMATUTILS9_H_
+
+#include "libGLESv2/formatutils.h"
+
+#include <map>
+
+namespace rx
+{
+
+class Renderer9;
+
+namespace d3d9
+{
+
+typedef std::map<std::pair<GLenum, GLenum>, ColorCopyFunction> FastCopyFunctionMap;
+
+struct D3DFormat
+{
+ D3DFormat();
+
+ GLuint pixelBytes;
+ GLuint blockWidth;
+ GLuint blockHeight;
+
+ GLenum internalFormat;
+
+ MipGenerationFunction mipGenerationFunction;
+ ColorReadFunction colorReadFunction;
+
+ FastCopyFunctionMap fastCopyFunctions;
+ ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const;
+};
+const D3DFormat &GetD3DFormatInfo(D3DFORMAT format);
+
+struct VertexFormat
+{
+ VertexFormat();
+
+ VertexConversionType conversionType;
+ size_t outputElementSize;
+ VertexCopyFunction copyFunction;
+ D3DDECLTYPE nativeFormat;
+ GLenum componentType;
+};
+const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::VertexFormat &vertexFormat);
+
+struct TextureFormat
+{
+ TextureFormat();
+
+ D3DFORMAT texFormat;
+ D3DFORMAT renderFormat;
+
+ InitializeTextureDataFunction dataInitializerFunction;
+
+ LoadImageFunction loadFunction;
+};
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat);
+
+}
+
+}
+
+#endif // LIBGLESV2_RENDERER_FORMATUTILS9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
new file mode 100644
index 0000000000..e7a91e62d6
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -0,0 +1,542 @@
+//
+// 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 "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
+#include "libGLESv2/formatutils.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
+
+#include "common/mathutil.h"
+#include "common/debug.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 maxAnisotropy)
+{
+ 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();
+ }
+
+ if (maxAnisotropy > 1.0f)
+ {
+ *d3dMinFilter = D3DTEXF_ANISOTROPIC;
+ }
+}
+
+D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples)
+{
+ return (samples > 1) ? static_cast<D3DMULTISAMPLE_TYPE>(samples) : D3DMULTISAMPLE_NONE;
+}
+
+}
+
+namespace d3d9_gl
+{
+
+GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type)
+{
+ return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0;
+}
+
+bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
+{
+ GLenum internalFormat = d3d9::GetD3DFormatInfo(d3dformat).internalFormat;
+ 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 (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));
+ textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)) ||
+ SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
+
+ textureCaps.sampleCounts.insert(1);
+ for (size_t 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)
+{
+ 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);
+
+ // WaitSync is ES3-only, set to zero
+ caps->maxServerWaitTimeout = 0;
+
+ // Vertex shader limits
+ caps->maxVertexAttributes = 16;
+
+ const size_t reservedVertexUniformVectors = 2; // dx_ViewAdjust and dx_DepthRange.
+ const size_t MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256;
+ caps->maxVertexUniformVectors = MAX_VERTEX_CONSTANT_VECTORS_D3D9 - reservedVertexUniformVectors;
+ caps->maxVertexUniformComponents = caps->maxVertexUniformVectors * 4;
+
+ caps->maxVertexUniformBlocks = 0;
+
+ const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 10;
+ const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 8;
+ 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 reservedPixelUniformVectors = 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange.
+
+ 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) - reservedPixelUniformVectors;
+ 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;
+
+ // GL extension support
+ extensions->setTextureExtensionSupport(*textureCapsMap);
+ extensions->elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16);
+ extensions->packedDepthStencil = true;
+ extensions->getProgramBinary = true;
+ extensions->rgb8rgba8 = true;
+ extensions->readFormatBGRA = true;
+ extensions->pixelBufferObject = false;
+ extensions->mapBuffer = false;
+ extensions->mapBufferRange = false;
+
+ // ATI cards on XP have problems with non-power-of-two textures.
+ D3DADAPTER_IDENTIFIER9 adapterId = { 0 };
+ if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId)))
+ {
+ extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
+ !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
+ !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
+ !(isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD);
+ }
+ 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->robustness = true;
+ extensions->blendMinMax = true;
+ extensions->framebufferBlit = true;
+ extensions->framebufferMultisample = true;
+ extensions->maxSamples = maxSamples;
+ 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->colorBufferFloat = false;
+}
+
+}
+
+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;
+}
+
+RenderTarget9 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
+{
+ RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
+ return RenderTarget9::makeRenderTarget9(renderTarget);
+}
+
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h
index bf6cdf1ea6..b0a940e60a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h
@@ -1,25 +1,32 @@
//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// 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
+// renderer9_utils.h: Conversion functions and other utility routines
// specific to the D3D9 renderer
#ifndef LIBGLESV2_RENDERER_RENDERER9_UTILS_H
#define LIBGLESV2_RENDERER_RENDERER9_UTILS_H
-#include "libGLESv2/utilities.h"
+#include "libGLESv2/angletypes.h"
+#include "libGLESv2/Caps.h"
-const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')));
-const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')));
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace rx
+{
+class RenderTarget9;
namespace gl_d3d9
{
D3DCMPFUNC ConvertComparison(GLenum comparison);
-D3DCOLOR ConvertColor(gl::Color color);
+D3DCOLOR ConvertColor(gl::ColorF color);
D3DBLEND ConvertBlendFunc(GLenum blend);
D3DBLENDOP ConvertBlendOp(GLenum blendOp);
D3DSTENCILOP ConvertStencilOp(GLenum stencilOp);
@@ -29,31 +36,29 @@ 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 maxAnisotropy);
-D3DFORMAT ConvertRenderbufferFormat(GLenum format);
-D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples);
+
+D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples);
}
namespace d3d9_gl
{
-GLuint GetAlphaSize(D3DFORMAT colorFormat);
-GLuint GetStencilSize(D3DFORMAT stencilFormat);
-
-GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
+GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type);
bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format);
-GLenum ConvertBackBufferFormat(D3DFORMAT format);
-GLenum ConvertDepthStencilFormat(D3DFORMAT format);
-GLenum ConvertRenderTargetFormat(D3DFORMAT format);
-GLenum GetEquivalentFormat(D3DFORMAT format);
+
+void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps,
+ gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions);
}
namespace d3d9
{
-bool IsCompressedFormat(D3DFORMAT format);
-size_t ComputeRowSize(D3DFORMAT format, unsigned int width);
+
+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)
{
@@ -69,6 +74,10 @@ inline bool isDeviceLostError(HRESULT errorCode)
}
}
+RenderTarget9 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment);
+
+}
+
}
#endif // LIBGLESV2_RENDERER_RENDERER9_UTILS_H
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps
new file mode 100644
index 0000000000..eb43eb3e7a
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/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 PS_passthrough(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 PS_luminance(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 PS_componentmask(float4 texcoord : TEXCOORD0) : COLOR
+{
+ return tex2D(tex, texcoord.xy) * mult + add;
+};
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs
index 3a36980b93..3bd611ba5d 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs
@@ -17,7 +17,7 @@ uniform float4 halfPixelSize : c0;
// 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 VS_standard(in float4 position : POSITION)
{
VS_OUTPUT Out;
@@ -32,7 +32,7 @@ VS_OUTPUT standardvs(in float4 position : 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 VS_flipy(in float4 position : POSITION)
{
VS_OUTPUT Out;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp
deleted file mode 100644
index 31d5b8b886..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp
+++ /dev/null
@@ -1,366 +0,0 @@
-#include "precompiled.h"
-//
-// 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.
-//
-
-// BufferStorage11.cpp Defines the BufferStorage11 class.
-
-#include "libGLESv2/renderer/d3d11/BufferStorage11.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/d3d11/Renderer11.h"
-
-namespace rx
-{
-
-BufferStorage11::BufferStorage11(Renderer11 *renderer)
-{
- mRenderer = renderer;
-
- mStagingBuffer = NULL;
- mStagingBufferSize = 0;
-
- mSize = 0;
-
- mResolvedData = NULL;
- mResolvedDataSize = 0;
- mResolvedDataValid = false;
-
- mReadUsageCount = 0;
- mWriteUsageCount = 0;
-}
-
-BufferStorage11::~BufferStorage11()
-{
- SafeRelease(mStagingBuffer);
-
- if (mResolvedData)
- {
- free(mResolvedData);
- mResolvedData = NULL;
- }
-
- for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++)
- {
- SafeDelete(it->second);
- }
-}
-
-BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage)
-{
- ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage));
- return static_cast<BufferStorage11*>(bufferStorage);
-}
-
-void *BufferStorage11::getData()
-{
- ASSERT(mStagingBuffer);
-
- if (!mResolvedDataValid)
- {
- ID3D11Device *device = mRenderer->getDevice();
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
- HRESULT result;
-
- if (!mResolvedData || mResolvedDataSize < mStagingBufferSize)
- {
- free(mResolvedData);
- mResolvedData = malloc(mSize);
- mResolvedDataSize = mSize;
- }
-
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource);
- if (FAILED(result))
- {
- return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
- }
-
- memcpy(mResolvedData, mappedResource.pData, mSize);
-
- context->Unmap(mStagingBuffer, 0);
-
- mResolvedDataValid = true;
- }
-
- mReadUsageCount = 0;
-
- return mResolvedData;
-}
-
-void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset)
-{
- ID3D11Device *device = mRenderer->getDevice();
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
- HRESULT result;
-
- const unsigned int requiredStagingBufferSize = size + offset;
- const bool createStagingBuffer = !mStagingBuffer || mStagingBufferSize < requiredStagingBufferSize;
-
- if (createStagingBuffer)
- {
- D3D11_BUFFER_DESC bufferDesc;
- bufferDesc.ByteWidth = requiredStagingBufferSize;
- bufferDesc.Usage = D3D11_USAGE_STAGING;
- bufferDesc.BindFlags = 0;
- bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
- bufferDesc.MiscFlags = 0;
- bufferDesc.StructureByteStride = 0;
-
- HRESULT result;
- ID3D11Device *device = mRenderer->getDevice();
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
- ID3D11Buffer *newStagingBuffer;
-
- if (data && offset == 0)
- {
- D3D11_SUBRESOURCE_DATA initialData;
- initialData.pSysMem = data;
- initialData.SysMemPitch = requiredStagingBufferSize;
- initialData.SysMemSlicePitch = 0;
-
- result = device->CreateBuffer(&bufferDesc, &initialData, &newStagingBuffer);
- }
- else
- {
- result = device->CreateBuffer(&bufferDesc, NULL, &newStagingBuffer);
- }
-
- if (FAILED(result))
- {
- mStagingBufferSize = 0;
- return gl::error(GL_OUT_OF_MEMORY);
- }
-
- mStagingBufferSize = requiredStagingBufferSize;
-
- if (mStagingBuffer && offset > 0)
- {
- // If offset is greater than zero and the buffer is non-null, need to preserve the data from
- // the old buffer up to offset
- D3D11_BOX srcBox;
- srcBox.left = 0;
- srcBox.right = std::min(offset, requiredStagingBufferSize);
- srcBox.top = 0;
- srcBox.bottom = 1;
- srcBox.front = 0;
- srcBox.back = 1;
-
- context->CopySubresourceRegion(newStagingBuffer, 0, 0, 0, 0, mStagingBuffer, 0, &srcBox);
- }
-
- SafeRelease(mStagingBuffer);
- mStagingBuffer = newStagingBuffer;
- }
-
- if (data && (offset != 0 || !createStagingBuffer))
- {
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
- if (FAILED(result))
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
-
- unsigned char *offsetBufferPointer = reinterpret_cast<unsigned char *>(mappedResource.pData) + offset;
- memcpy(offsetBufferPointer, data, size);
-
- context->Unmap(mStagingBuffer, 0);
- }
-
- for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++)
- {
- it->second->markDirty();
- }
-
- mSize = std::max(mSize, requiredStagingBufferSize);
- mWriteUsageCount = 0;
-
- mResolvedDataValid = false;
-}
-
-void BufferStorage11::copyData(BufferStorage* sourceStorage, unsigned int size,
- unsigned int sourceOffset, unsigned int destOffset)
-{
- BufferStorage11* source = makeBufferStorage11(sourceStorage);
- if (source)
- {
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-
- D3D11_BOX srcBox;
- srcBox.left = sourceOffset;
- srcBox.right = sourceOffset + size;
- srcBox.top = 0;
- srcBox.bottom = 1;
- srcBox.front = 0;
- srcBox.back = 1;
-
- ASSERT(mStagingBuffer && source->mStagingBuffer);
- context->CopySubresourceRegion(mStagingBuffer, 0, destOffset, 0, 0, source->mStagingBuffer, 0, &srcBox);
- }
-}
-
-void BufferStorage11::clear()
-{
- mResolvedDataValid = false;
- mSize = 0;
-}
-
-unsigned int BufferStorage11::getSize() const
-{
- return mSize;
-}
-
-bool BufferStorage11::supportsDirectBinding() const
-{
- return true;
-}
-
-void BufferStorage11::markBufferUsage()
-{
- mReadUsageCount++;
- mWriteUsageCount++;
-
- const unsigned int usageLimit = 5;
-
- if (mReadUsageCount > usageLimit && mResolvedData)
- {
- free(mResolvedData);
- mResolvedData = NULL;
- mResolvedDataSize = 0;
- mResolvedDataValid = false;
- }
-}
-
-ID3D11Buffer *BufferStorage11::getBuffer(BufferUsage usage)
-{
- markBufferUsage();
-
- DirectBufferStorage11 *directBuffer = NULL;
-
- auto directBufferIt = mDirectBuffers.find(usage);
- if (directBufferIt != mDirectBuffers.end())
- {
- directBuffer = directBufferIt->second;
- }
-
- if (directBuffer)
- {
- if (directBuffer->isDirty())
- {
- // if updateFromStagingBuffer returns true, the D3D buffer has been recreated
- // and we should update our serial
- if (directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0))
- {
- updateSerial();
- }
- }
- }
- else
- {
- // buffer is not allocated, create it
- directBuffer = new DirectBufferStorage11(mRenderer, usage);
- directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0);
-
- mDirectBuffers.insert(std::make_pair(usage, directBuffer));
- updateSerial();
- }
-
- return directBuffer->getD3DBuffer();
-}
-
-DirectBufferStorage11::DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage)
- : mRenderer(renderer),
- mUsage(usage),
- mDirectBuffer(NULL),
- mBufferSize(0),
- mDirty(false)
-{
-}
-
-DirectBufferStorage11::~DirectBufferStorage11()
-{
- SafeRelease(mDirectBuffer);
-}
-
-BufferUsage DirectBufferStorage11::getUsage() const
-{
- return mUsage;
-}
-
-// Returns true if it recreates the direct buffer
-bool DirectBufferStorage11::updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset)
-{
- ID3D11Device *device = mRenderer->getDevice();
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-
- // unused for now
- ASSERT(offset == 0);
-
- unsigned int requiredBufferSize = size + offset;
- bool createBuffer = !mDirectBuffer || mBufferSize < requiredBufferSize;
-
- // (Re)initialize D3D buffer if needed
- if (createBuffer)
- {
- D3D11_BUFFER_DESC bufferDesc;
- fillBufferDesc(&bufferDesc, mRenderer, mUsage, requiredBufferSize);
-
- ID3D11Buffer *newBuffer;
- HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);
-
- if (FAILED(result))
- {
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- // No longer need the old buffer
- SafeRelease(mDirectBuffer);
- mDirectBuffer = newBuffer;
-
- mBufferSize = bufferDesc.ByteWidth;
- }
-
- // Copy data via staging buffer
- D3D11_BOX srcBox;
- srcBox.left = 0;
- srcBox.right = size;
- srcBox.top = 0;
- srcBox.bottom = 1;
- srcBox.front = 0;
- srcBox.back = 1;
-
- context->CopySubresourceRegion(mDirectBuffer, 0, offset, 0, 0, stagingBuffer, 0, &srcBox);
-
- mDirty = false;
-
- return createBuffer;
-}
-
-void DirectBufferStorage11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize)
-{
- bufferDesc->ByteWidth = bufferSize;
- bufferDesc->MiscFlags = 0;
- bufferDesc->StructureByteStride = 0;
-
- switch (usage)
- {
- case BUFFER_USAGE_VERTEX:
- bufferDesc->Usage = D3D11_USAGE_DEFAULT;
- bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER;
- bufferDesc->CPUAccessFlags = 0;
- break;
-
- case BUFFER_USAGE_INDEX:
- bufferDesc->Usage = D3D11_USAGE_DEFAULT;
- bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER;
- bufferDesc->CPUAccessFlags = 0;
- break;
-
- default:
- UNREACHABLE();
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h
deleted file mode 100644
index a6afafe1b4..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h
+++ /dev/null
@@ -1,92 +0,0 @@
-//
-// 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.
-//
-
-// BufferStorage11.h Defines the BufferStorage11 class.
-
-#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_
-#define LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_
-
-#include "libGLESv2/renderer/BufferStorage.h"
-
-namespace rx
-{
-class Renderer;
-class Renderer11;
-class DirectBufferStorage11;
-
-enum BufferUsage
-{
- BUFFER_USAGE_VERTEX,
- BUFFER_USAGE_INDEX,
-};
-
-class BufferStorage11 : public BufferStorage
-{
- public:
- explicit BufferStorage11(Renderer11 *renderer);
- virtual ~BufferStorage11();
-
- static BufferStorage11 *makeBufferStorage11(BufferStorage *bufferStorage);
-
- virtual void *getData();
- virtual void setData(const void* data, unsigned int size, unsigned int offset);
- virtual void copyData(BufferStorage* sourceStorage, unsigned int size,
- unsigned int sourceOffset, unsigned int destOffset);
- virtual void clear();
- virtual unsigned int getSize() const;
- virtual bool supportsDirectBinding() const;
-
- ID3D11Buffer *getBuffer(BufferUsage usage);
-
- private:
- Renderer11 *mRenderer;
-
- ID3D11Buffer *mStagingBuffer;
- unsigned int mStagingBufferSize;
-
- std::map<BufferUsage, DirectBufferStorage11*> mDirectBuffers;
-
- unsigned int mSize;
-
- void *mResolvedData;
- unsigned int mResolvedDataSize;
- bool mResolvedDataValid;
-
- unsigned int mReadUsageCount;
- unsigned int mWriteUsageCount;
-
- void markBufferUsage();
-};
-
-// Each instance of BufferStorageD3DBuffer11 is specialized for a class of D3D binding points
-// - vertex buffers
-// - index buffers
-class DirectBufferStorage11
-{
- public:
- DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage);
- ~DirectBufferStorage11();
-
- BufferUsage getUsage() const;
- bool updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset);
-
- ID3D11Buffer *getD3DBuffer() { return mDirectBuffer; }
- bool isDirty() const { return mDirty; }
- void markDirty() { mDirty = true; }
-
- private:
- Renderer11 *mRenderer;
- const BufferUsage mUsage;
- ID3D11Buffer *mDirectBuffer;
- size_t mBufferSize;
- bool mDirty;
-
- static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize);
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp
deleted file mode 100644
index 2a7d4d43ef..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-#include "precompiled.h"
-//
-// 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::Fence11 class which implements rx::FenceImpl.
-
-#include "libGLESv2/renderer/d3d11/Fence11.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/d3d11/Renderer11.h"
-
-namespace rx
-{
-
-Fence11::Fence11(rx::Renderer11 *renderer)
-{
- mRenderer = renderer;
- mQuery = NULL;
-}
-
-Fence11::~Fence11()
-{
- if (mQuery)
- {
- mQuery->Release();
- mQuery = NULL;
- }
-}
-
-GLboolean Fence11::isFence()
-{
- // GL_NV_fence spec:
- // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
- return mQuery != NULL;
-}
-
-void Fence11::setFence(GLenum condition)
-{
- if (!mQuery)
- {
- D3D11_QUERY_DESC queryDesc;
- queryDesc.Query = D3D11_QUERY_EVENT;
- queryDesc.MiscFlags = 0;
-
- if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
- }
-
- mRenderer->getDeviceContext()->End(mQuery);
-
- setCondition(condition);
- setStatus(GL_FALSE);
-}
-
-GLboolean Fence11::testFence()
-{
- if (mQuery == NULL)
- {
- return gl::error(GL_INVALID_OPERATION, GL_TRUE);
- }
-
- HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, 0);
-
- if (mRenderer->isDeviceLost())
- {
- return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
- }
-
- ASSERT(result == S_OK || result == S_FALSE);
- setStatus(result == S_OK);
- return getStatus();
-}
-
-void Fence11::finishFence()
-{
- if (mQuery == NULL)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- while (!testFence())
- {
- Sleep(0);
- }
-}
-
-void Fence11::getFenceiv(GLenum pname, GLint *params)
-{
- if (mQuery == NULL)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- switch (pname)
- {
- case GL_FENCE_STATUS_NV:
- {
- // GL_NV_fence spec:
- // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
- // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
- if (getStatus())
- {
- params[0] = GL_TRUE;
- return;
- }
-
- HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
-
- if (mRenderer->isDeviceLost())
- {
- params[0] = GL_TRUE;
- return gl::error(GL_OUT_OF_MEMORY);
- }
-
- ASSERT(result == S_OK || result == S_FALSE);
- setStatus(result == S_OK);
- params[0] = getStatus();
-
- break;
- }
- case GL_FENCE_CONDITION_NV:
- params[0] = getCondition();
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- break;
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp
deleted file mode 100644
index 5d039a35e8..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp
+++ /dev/null
@@ -1,498 +0,0 @@
-#include "precompiled.h"
-//
-// 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 "libGLESv2/renderer/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d11/Image11.h"
-#include "libGLESv2/renderer/d3d11/TextureStorage11.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/Renderbuffer.h"
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
-#include "libGLESv2/renderer/generatemip.h"
-
-namespace rx
-{
-
-Image11::Image11()
-{
- mStagingTexture = NULL;
- mRenderer = NULL;
- mDXGIFormat = DXGI_FORMAT_UNKNOWN;
-}
-
-Image11::~Image11()
-{
- if (mStagingTexture)
- {
- mStagingTexture->Release();
- }
-}
-
-Image11 *Image11::makeImage11(Image *img)
-{
- ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img));
- return static_cast<rx::Image11*>(img);
-}
-
-void Image11::generateMipmap(Image11 *dest, Image11 *src)
-{
- 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, srcMapped;
- dest->map(D3D11_MAP_WRITE, &destMapped);
- src->map(D3D11_MAP_READ, &srcMapped);
-
- const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(srcMapped.pData);
- unsigned char *destData = reinterpret_cast<unsigned char*>(destMapped.pData);
-
- if (sourceData && destData)
- {
- switch (src->getDXGIFormat())
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- case DXGI_FORMAT_B8G8R8A8_UNORM:
- GenerateMip<R8G8B8A8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
- break;
- case DXGI_FORMAT_A8_UNORM:
- GenerateMip<A8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
- break;
- case DXGI_FORMAT_R8_UNORM:
- GenerateMip<R8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
- break;
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- GenerateMip<A32B32G32R32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
- break;
- case DXGI_FORMAT_R32G32B32_FLOAT:
- GenerateMip<R32G32B32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
- break;
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- GenerateMip<A16B16G16R16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
- break;
- case DXGI_FORMAT_R8G8_UNORM:
- GenerateMip<R8G8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
- break;
- case DXGI_FORMAT_R16_FLOAT:
- GenerateMip<R16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
- break;
- case DXGI_FORMAT_R16G16_FLOAT:
- GenerateMip<R16G16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
- break;
- case DXGI_FORMAT_R32_FLOAT:
- GenerateMip<R32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
- break;
- case DXGI_FORMAT_R32G32_FLOAT:
- GenerateMip<R32G32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
- break;
- default:
- UNREACHABLE();
- break;
- }
-
- dest->unmap();
- src->unmap();
- }
-
- dest->markDirty();
-}
-
-static bool FormatRequiresInitialization(DXGI_FORMAT dxgiFormat, GLenum internalFormat)
-{
- return (dxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM && gl::GetAlphaSize(internalFormat) == 0) ||
- (dxgiFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && gl::GetAlphaSize(internalFormat) == 0);
-}
-
-bool Image11::isDirty() const
-{
- return ((mStagingTexture || FormatRequiresInitialization(mDXGIFormat, mInternalFormat)) && mDirty);
-}
-
-bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
-{
- TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance());
- return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, width, height);
-}
-
-bool Image11::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
-{
- TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance());
- return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, width, height);
-}
-
-bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
-{
- if (mWidth != width ||
- mHeight != height ||
- mInternalFormat != internalformat ||
- forceRelease)
- {
- mRenderer = Renderer11::makeRenderer11(renderer);
-
- mWidth = width;
- mHeight = height;
- mInternalFormat = internalformat;
- // compute the d3d format that will be used
- mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel());
- mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat);
-
- if (mStagingTexture)
- {
- mStagingTexture->Release();
- mStagingTexture = NULL;
- }
-
- return true;
- }
-
- return false;
-}
-
-bool Image11::isRenderableFormat() const
-{
- return TextureStorage11::IsTextureFormatRenderable(mDXGIFormat);
-}
-
-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.
-void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLint unpackAlignment, const void *input)
-{
- D3D11_MAPPED_SUBRESOURCE mappedImage;
- HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
- if (FAILED(result))
- {
- ERR("Could not map image for loading.");
- return;
- }
-
- GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
- size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8;
- void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize));
-
- switch (mInternalFormat)
- {
- case GL_ALPHA8_EXT:
- if (mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0)
- loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- else
- loadAlphaDataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_LUMINANCE8_EXT:
- loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
- break;
- case GL_ALPHA32F_EXT:
- loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_LUMINANCE32F_EXT:
- loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_ALPHA16F_EXT:
- loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_LUMINANCE16F_EXT:
- loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_LUMINANCE8_ALPHA8_EXT:
- loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
- break;
- case GL_LUMINANCE_ALPHA32F_EXT:
- loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_LUMINANCE_ALPHA16F_EXT:
- loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_RGB8_OES:
- loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_RGB565:
- loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_RGBA8_OES:
- loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_RGBA4:
- loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_RGB5_A1:
- loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_BGRA8_EXT:
- loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_RGB32F_EXT:
- loadRGBFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_RGB16F_EXT:
- loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_RGBA32F_EXT:
- loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- case GL_RGBA16F_EXT:
- loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
- break;
- default: UNREACHABLE();
- }
-
- unmap();
-}
-
-void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- const void *input)
-{
- ASSERT(xoffset % 4 == 0);
- ASSERT(yoffset % 4 == 0);
-
- D3D11_MAPPED_SUBRESOURCE mappedImage;
- HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
- if (FAILED(result))
- {
- ERR("Could not map image for loading.");
- return;
- }
-
- // Size computation assumes a 4x4 block compressed texture format
- size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8;
- void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize));
-
- GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
- GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
- int rows = inputSize / inputPitch;
- for (int i = 0; i < rows; ++i)
- {
- memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
- }
-
- unmap();
-}
-
-void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
-{
- gl::Renderbuffer *colorbuffer = source->getReadColorbuffer();
-
- if (colorbuffer && colorbuffer->getActualFormat() == (GLuint)mActualFormat)
- {
- // No conversion needed-- use copyback fastpath
- ID3D11Texture2D *colorBufferTexture = NULL;
- unsigned int subresourceIndex = 0;
-
- if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
- {
- D3D11_TEXTURE2D_DESC textureDesc;
- colorBufferTexture->GetDesc(&textureDesc);
-
- ID3D11Device *device = mRenderer->getDevice();
- ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
-
- ID3D11Texture2D* srcTex = NULL;
- if (textureDesc.SampleDesc.Count > 1)
- {
- D3D11_TEXTURE2D_DESC resolveDesc;
- resolveDesc.Width = textureDesc.Width;
- resolveDesc.Height = textureDesc.Height;
- resolveDesc.MipLevels = 1;
- resolveDesc.ArraySize = 1;
- resolveDesc.Format = textureDesc.Format;
- resolveDesc.SampleDesc.Count = 1;
- resolveDesc.SampleDesc.Quality = 0;
- resolveDesc.Usage = D3D11_USAGE_DEFAULT;
- resolveDesc.BindFlags = 0;
- resolveDesc.CPUAccessFlags = 0;
- resolveDesc.MiscFlags = 0;
-
- HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex);
- if (FAILED(result))
- {
- ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
- return;
- }
-
- deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format);
- subresourceIndex = 0;
- }
- else
- {
- srcTex = colorBufferTexture;
- srcTex->AddRef();
- }
-
- D3D11_BOX srcBox;
- srcBox.left = x;
- srcBox.right = x + width;
- srcBox.top = y;
- srcBox.bottom = y + height;
- srcBox.front = 0;
- srcBox.back = 1;
-
- deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, 0, srcTex, subresourceIndex, &srcBox);
-
- srcTex->Release();
- colorBufferTexture->Release();
- }
- }
- else
- {
- // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
- D3D11_MAPPED_SUBRESOURCE mappedImage;
- HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
-
- // determine the offset coordinate into the destination buffer
- GLsizei rowOffset = gl::ComputePixelSize(mActualFormat) * xoffset;
- void *dataOffset = static_cast<unsigned char*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset;
-
- mRenderer->readPixels(source, x, y, width, height, gl::ExtractFormat(mInternalFormat),
- gl::ExtractType(mInternalFormat), mappedImage.RowPitch, false, 4, dataOffset);
-
- unmap();
- }
-}
-
-ID3D11Texture2D *Image11::getStagingTexture()
-{
- createStagingTexture();
-
- return mStagingTexture;
-}
-
-unsigned int Image11::getStagingSubresource()
-{
- createStagingTexture();
-
- return mStagingSubresource;
-}
-
-template <typename T, size_t N>
-static void setDefaultData(ID3D11DeviceContext *deviceContext, ID3D11Texture2D *texture, UINT subresource,
- GLsizei width, GLsizei height, const T (&defaultData)[N])
-{
- D3D11_MAPPED_SUBRESOURCE map;
- deviceContext->Map(texture, subresource, D3D11_MAP_WRITE, 0, &map);
-
- unsigned char* ptr = reinterpret_cast<unsigned char*>(map.pData);
- size_t pixelSize = sizeof(T) * N;
-
- for (GLsizei y = 0; y < height; y++)
- {
- for (GLsizei x = 0; x < width; x++)
- {
- memcpy(ptr + (y * map.RowPitch) + (x * pixelSize), defaultData, pixelSize);
- }
- }
-
- deviceContext->Unmap(texture, subresource);
-}
-
-void Image11::createStagingTexture()
-{
- if (mStagingTexture)
- {
- return;
- }
-
- ID3D11Texture2D *newTexture = NULL;
- int lodOffset = 1;
- const DXGI_FORMAT dxgiFormat = getDXGIFormat();
- ASSERT(!d3d11::IsDepthStencilFormat(dxgiFormat)); // We should never get here for depth textures
-
- if (mWidth != 0 && mHeight != 0)
- {
- GLsizei width = mWidth;
- GLsizei height = mHeight;
-
- // adjust size if needed for compressed textures
- gl::MakeValidSize(false, d3d11::IsCompressed(dxgiFormat), &width, &height, &lodOffset);
- ID3D11Device *device = mRenderer->getDevice();
-
- 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;
-
- HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture);
-
- if (FAILED(result))
- {
- ASSERT(result == E_OUTOFMEMORY);
- ERR("Creating image failed.");
- return gl::error(GL_OUT_OF_MEMORY);
- }
- }
-
- mStagingTexture = newTexture;
- mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
- mDirty = false;
-
- if (mDXGIFormat == DXGI_FORMAT_R8G8B8A8_UNORM && gl::GetAlphaSize(mInternalFormat) == 0)
- {
- unsigned char defaultPixel[4] = { 0, 0, 0, 255 };
- setDefaultData(mRenderer->getDeviceContext(), mStagingTexture, mStagingSubresource, mWidth, mHeight, defaultPixel);
- }
- else if (mDXGIFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && gl::GetAlphaSize(mInternalFormat) == 0)
- {
- float defaultPixel[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
- setDefaultData(mRenderer->getDeviceContext(), mStagingTexture, mStagingSubresource, mWidth, mHeight, defaultPixel);
- }
-}
-
-HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
-{
- createStagingTexture();
-
- HRESULT result = E_FAIL;
-
- if (mStagingTexture)
- {
- ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
- result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map);
-
- // this can fail if the device is removed (from TDR)
- if (d3d11::isDeviceLostError(result))
- {
- mRenderer->notifyDeviceLost();
- }
- else if (SUCCEEDED(result))
- {
- mDirty = true;
- }
- }
-
- return result;
-}
-
-void Image11::unmap()
-{
- if (mStagingTexture)
- {
- ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
- deviceContext->Unmap(mStagingTexture, mStagingSubresource);
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h
deleted file mode 100644
index 11a6492dc8..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// 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 LIBGLESV2_RENDERER_IMAGE11_H_
-#define LIBGLESV2_RENDERER_IMAGE11_H_
-
-#include "libGLESv2/renderer/Image.h"
-
-#include "common/debug.h"
-
-namespace gl
-{
-class Framebuffer;
-}
-
-namespace rx
-{
-class Renderer;
-class Renderer11;
-class TextureStorageInterface2D;
-class TextureStorageInterfaceCube;
-
-class Image11 : public Image
-{
- public:
- Image11();
- virtual ~Image11();
-
- static Image11 *makeImage11(Image *img);
-
- static void generateMipmap(Image11 *dest, Image11 *src);
-
- virtual bool isDirty() const;
-
- virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
- virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-
- virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease);
-
- virtual bool isRenderableFormat() const;
- DXGI_FORMAT getDXGIFormat() const;
-
- virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLint unpackAlignment, const void *input);
- virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- const void *input);
-
- virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
-
- protected:
- HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
- void unmap();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Image11);
-
- ID3D11Texture2D *getStagingTexture();
- unsigned int getStagingSubresource();
- void createStagingTexture();
-
- Renderer11 *mRenderer;
-
- DXGI_FORMAT mDXGIFormat;
- ID3D11Texture2D *mStagingTexture;
- unsigned int mStagingSubresource;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_IMAGE11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp
deleted file mode 100644
index 44f9976d43..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-#include "precompiled.h"
-//
-// 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 "libGLESv2/renderer/d3d11/IndexBuffer11.h"
-#include "libGLESv2/renderer/d3d11/Renderer11.h"
-
-namespace rx
-{
-
-IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
-{
- mBuffer = NULL;
- mBufferSize = 0;
- mDynamicUsage = false;
-}
-
-IndexBuffer11::~IndexBuffer11()
-{
- if (mBuffer)
- {
- mBuffer->Release();
- mBuffer = NULL;
- }
-}
-
-bool IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
-{
- if (mBuffer)
- {
- mBuffer->Release();
- mBuffer = NULL;
- }
-
- 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 false;
- }
- }
-
- mBufferSize = bufferSize;
- mIndexType = indexType;
- mDynamicUsage = dynamic;
-
- return true;
-}
-
-IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer)
-{
- ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer));
- return static_cast<IndexBuffer11*>(indexBuffer);
-}
-
-bool IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
-{
- if (mBuffer)
- {
- // Check for integer overflows and out-out-bounds map requests
- if (offset + size < offset || offset + size > mBufferSize)
- {
- ERR("Index buffer map range is not inside the buffer.");
- return false;
- }
-
- ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
-
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
- if (FAILED(result))
- {
- ERR("Index buffer map failed with error 0x%08x", result);
- return false;
- }
-
- *outMappedMemory = reinterpret_cast<char*>(mappedResource.pData) + offset;
- return true;
- }
- else
- {
- ERR("Index buffer not initialized.");
- return false;
- }
-}
-
-bool IndexBuffer11::unmapBuffer()
-{
- if (mBuffer)
- {
- ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
- dxContext->Unmap(mBuffer, 0);
- return true;
- }
- else
- {
- ERR("Index buffer not initialized.");
- return false;
- }
-}
-
-GLenum IndexBuffer11::getIndexType() const
-{
- return mIndexType;
-}
-
-unsigned int IndexBuffer11::getBufferSize() const
-{
- return mBufferSize;
-}
-
-bool IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType)
-{
- if (bufferSize > mBufferSize || indexType != mIndexType)
- {
- return initialize(bufferSize, indexType, mDynamicUsage);
- }
- else
- {
- return true;
- }
-}
-
-bool IndexBuffer11::discard()
-{
- if (mBuffer)
- {
- ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
-
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
- if (FAILED(result))
- {
- ERR("Index buffer map failed with error 0x%08x", result);
- return false;
- }
-
- dxContext->Unmap(mBuffer, 0);
-
- return true;
- }
- else
- {
- ERR("Index buffer not initialized.");
- return false;
- }
-}
-
-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;
-}
-
-} \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp
deleted file mode 100644
index 24c0330a1e..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-#include "precompiled.h"
-//
-// 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 "libGLESv2/renderer/d3d11/Query11.h"
-#include "libGLESv2/renderer/d3d11/Renderer11.h"
-#include "libGLESv2/main.h"
-
-namespace rx
-{
-
-Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type)
-{
- mRenderer = renderer;
- mQuery = NULL;
-}
-
-Query11::~Query11()
-{
- if (mQuery)
- {
- mQuery->Release();
- mQuery = NULL;
- }
-}
-
-void Query11::begin()
-{
- if (mQuery == NULL)
- {
- D3D11_QUERY_DESC queryDesc;
- queryDesc.Query = D3D11_QUERY_OCCLUSION;
- queryDesc.MiscFlags = 0;
-
- if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
- }
-
- mRenderer->getDeviceContext()->Begin(mQuery);
-}
-
-void Query11::end()
-{
- if (mQuery == NULL)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- mRenderer->getDeviceContext()->End(mQuery);
-
- mStatus = GL_FALSE;
- mResult = GL_FALSE;
-}
-
-GLuint Query11::getResult()
-{
- if (mQuery != NULL)
- {
- while (!testQuery())
- {
- Sleep(0);
- // explicitly check for device loss, some drivers seem to return S_FALSE
- // if the device is lost
- if (mRenderer->testDeviceLost(true))
- {
- return gl::error(GL_OUT_OF_MEMORY, 0);
- }
- }
- }
-
- return mResult;
-}
-
-GLboolean Query11::isResultAvailable()
-{
- if (mQuery != NULL)
- {
- testQuery();
- }
-
- return mStatus;
-}
-
-GLboolean Query11::testQuery()
-{
- if (mQuery != NULL && mStatus != GL_TRUE)
- {
- UINT64 numPixels = 0;
- HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, &numPixels, sizeof(UINT64), 0);
- if (result == S_OK)
- {
- mStatus = GL_TRUE;
-
- switch (getType())
- {
- case GL_ANY_SAMPLES_PASSED_EXT:
- case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
- mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
- break;
- default:
- UNREACHABLE();
- }
- }
- else if (mRenderer->testDeviceLost(true))
- {
- return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
- }
-
- return mStatus;
- }
-
- return GL_TRUE; // prevent blocking when query is null
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp
deleted file mode 100644
index e70727c65e..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp
+++ /dev/null
@@ -1,3736 +0,0 @@
-#include "precompiled.h"
-//
-// 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.
-//
-
-// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/renderer/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d11/RenderTarget11.h"
-#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
-#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h"
-#include "libGLESv2/renderer/d3d11/SwapChain11.h"
-#include "libGLESv2/renderer/d3d11/Image11.h"
-#include "libGLESv2/renderer/d3d11/VertexBuffer11.h"
-#include "libGLESv2/renderer/d3d11/IndexBuffer11.h"
-#include "libGLESv2/renderer/d3d11/BufferStorage11.h"
-#include "libGLESv2/renderer/VertexDataManager.h"
-#include "libGLESv2/renderer/IndexDataManager.h"
-#include "libGLESv2/renderer/d3d11/TextureStorage11.h"
-#include "libGLESv2/renderer/d3d11/Query11.h"
-#include "libGLESv2/renderer/d3d11/Fence11.h"
-
-#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h"
-#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h"
-#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h"
-#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h"
-#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h"
-
-#include "libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h"
-#include "libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h"
-#include "libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h"
-
-#include "libEGL/Display.h"
-
-#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
-# include <dxgi1_3.h>
-# include <wrl.h>
-# include <windows.applicationmodel.core.h>
-typedef ABI::Windows::Foundation::IEventHandler<ABI::Windows::ApplicationModel::SuspendingEventArgs *> SuspendEventHandler;
-#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
-{
-static const DXGI_FORMAT RenderTargetFormats[] =
- {
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM
- };
-
-static const DXGI_FORMAT DepthStencilFormats[] =
- {
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D24_UNORM_S8_UINT,
- DXGI_FORMAT_D16_UNORM
- };
-
-enum
-{
- MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
-};
-
-Renderer11::Renderer11(egl::Display *display) : Renderer(display)
-{
- mVertexDataManager = NULL;
- mIndexDataManager = NULL;
-
- mLineLoopIB = NULL;
- mTriangleFanIB = NULL;
-
- mCopyResourcesInitialized = false;
- mCopyVB = NULL;
- mCopySampler = NULL;
- mCopyIL = NULL;
- mCopyVS = NULL;
- mCopyRGBAPS = NULL;
- mCopyRGBPS = NULL;
- mCopyLumPS = NULL;
- mCopyLumAlphaPS = NULL;
-
- mClearResourcesInitialized = false;
- mClearVB = NULL;
- mClearIL = NULL;
- mClearVS = NULL;
- mClearSinglePS = NULL;
- mClearMultiplePS = NULL;
- mClearScissorRS = NULL;
- mClearNoScissorRS = NULL;
-
- mSyncQuery = NULL;
-
- mD3d11Module = NULL;
- mDxgiModule = NULL;
-
- mDeviceLost = false;
-
- mMaxSupportedSamples = 0;
-
- mDevice = NULL;
- mDeviceContext = NULL;
- mDxgiAdapter = NULL;
- mDxgiFactory = NULL;
-
- mDriverConstantBufferVS = NULL;
- mDriverConstantBufferPS = NULL;
-
- mBGRATextureSupport = false;
-
- mIsGeometryShaderActive = false;
-}
-
-Renderer11::~Renderer11()
-{
- release();
-}
-
-Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
-{
- ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer));
- return static_cast<rx::Renderer11*>(renderer);
-}
-
-#ifndef __d3d11_1_h__
-#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
-#endif
-
-EGLint Renderer11::initialize()
-{
- if (!initializeCompiler())
- {
- return EGL_NOT_INITIALIZED;
- }
-
-#if !defined(ANGLE_OS_WINRT)
- mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
- mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
-
- if (mD3d11Module == NULL || mDxgiModule == NULL)
- {
- ERR("Could not load D3D11 or DXGI library - aborting!\n");
- return EGL_NOT_INITIALIZED;
- }
-
-
- // create the D3D11 device
- ASSERT(mDevice == NULL);
- PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
-
- if (D3D11CreateDevice == NULL)
- {
- ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
- return EGL_NOT_INITIALIZED;
- }
-#endif
-
- D3D_FEATURE_LEVEL featureLevels[] =
- {
- D3D_FEATURE_LEVEL_11_0,
- D3D_FEATURE_LEVEL_10_1,
- D3D_FEATURE_LEVEL_10_0,
-#if !defined(ANGLE_ENABLE_D3D9)
- D3D_FEATURE_LEVEL_9_3,
- D3D_FEATURE_LEVEL_9_2,
- D3D_FEATURE_LEVEL_9_1,
-#endif
- };
-
- HRESULT result = S_OK;
-
-#ifdef _DEBUG
- result = D3D11CreateDevice(NULL,
- D3D_DRIVER_TYPE_HARDWARE,
- NULL,
- D3D11_CREATE_DEVICE_DEBUG,
- featureLevels,
- ArraySize(featureLevels),
- D3D11_SDK_VERSION,
- &mDevice,
- &mFeatureLevel,
- &mDeviceContext);
-
- if (!mDevice || FAILED(result))
- {
- ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
- }
-
- if (!mDevice || FAILED(result))
-#endif
- {
- result = D3D11CreateDevice(NULL,
- D3D_DRIVER_TYPE_HARDWARE,
- NULL,
- 0,
- featureLevels,
- ArraySize(featureLevels),
- D3D11_SDK_VERSION,
- &mDevice,
- &mFeatureLevel,
- &mDeviceContext);
-
- if (!mDevice || FAILED(result))
- {
- ERR("Could not create D3D11 device - aborting!\n");
- return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer
- }
- }
-
-#if !defined(ANGLE_OS_WINRT)
- IDXGIDevice *dxgiDevice = NULL;
-#else
- IDXGIDevice1 *dxgiDevice = NULL;
-#endif
- result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice));
-
- if (FAILED(result))
- {
- ERR("Could not query DXGI device - aborting!\n");
- return EGL_NOT_INITIALIZED;
- }
-
- result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter);
-
- if (FAILED(result))
- {
- ERR("Could not retrieve DXGI adapter - aborting!\n");
- return EGL_NOT_INITIALIZED;
- }
-
- dxgiDevice->Release();
-
- mDxgiAdapter->GetDesc(&mAdapterDescription);
- memset(mDescription, 0, sizeof(mDescription));
- wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
-
- result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory);
-
- if (!mDxgiFactory || FAILED(result))
- {
- ERR("Could not create DXGI factory - aborting!\n");
- return EGL_NOT_INITIALIZED;
- }
-
- // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
-#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
- 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 = {0};
- filter.DenyList.NumIDs = ArraySize(hideMessages);
- filter.DenyList.pIDList = hideMessages;
-
- infoQueue->AddStorageFilterEntries(&filter);
-
- infoQueue->Release();
- }
-#endif
-
- unsigned int maxSupportedSamples = 0;
- unsigned int rtFormatCount = ArraySize(RenderTargetFormats);
- unsigned int dsFormatCount = ArraySize(DepthStencilFormats);
- for (unsigned int i = 0; i < rtFormatCount + dsFormatCount; ++i)
- {
- DXGI_FORMAT format = (i < rtFormatCount) ? RenderTargetFormats[i] : DepthStencilFormats[i - rtFormatCount];
- if (format != DXGI_FORMAT_UNKNOWN)
- {
- UINT formatSupport;
- result = mDevice->CheckFormatSupport(format, &formatSupport);
- if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET))
- {
- MultisampleSupportInfo supportInfo;
-
- for (unsigned int j = 1; j <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; j++)
- {
- result = mDevice->CheckMultisampleQualityLevels(format, j, &supportInfo.qualityLevels[j - 1]);
- if (SUCCEEDED(result) && supportInfo.qualityLevels[j - 1] > 0)
- {
- maxSupportedSamples = std::max(j, maxSupportedSamples);
- }
- else
- {
- supportInfo.qualityLevels[j - 1] = 0;
- }
- }
-
- mMultisampleSupportMap.insert(std::make_pair(format, supportInfo));
- }
- }
- }
- mMaxSupportedSamples = maxSupportedSamples;
-
- initializeDevice();
-
- // BGRA texture support is optional in feature levels 10 and 10_1
- UINT formatSupport;
- result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport);
- if (FAILED(result))
- {
- ERR("Error checking BGRA format support: 0x%08X", result);
- }
- else
- {
- const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET);
- mBGRATextureSupport = (formatSupport & flags) == flags;
- }
-
- // Check floating point texture support
- static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE;
- static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET;
- static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
-
- DXGI_FORMAT float16Formats[] =
- {
- DXGI_FORMAT_R16_FLOAT,
- DXGI_FORMAT_R16G16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- };
-
- DXGI_FORMAT float32Formats[] =
- {
- DXGI_FORMAT_R32_FLOAT,
- DXGI_FORMAT_R32G32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- };
-
- mFloat16TextureSupport = true;
- mFloat16FilterSupport = true;
- mFloat16RenderSupport = true;
- for (unsigned int i = 0; i < ArraySize(float16Formats); i++)
- {
- if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport)))
- {
- mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags;
- mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags;
- mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags;
- }
- else
- {
- mFloat16TextureSupport = false;
- mFloat16RenderSupport = false;
- mFloat16FilterSupport = false;
- }
- }
-
- mFloat32TextureSupport = true;
- mFloat32FilterSupport = true;
- mFloat32RenderSupport = true;
- for (unsigned int i = 0; i < ArraySize(float32Formats); i++)
- {
- if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport)))
- {
- mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags;
- mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags;
- mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags;
- }
- else
- {
- mFloat32TextureSupport = false;
- mFloat32FilterSupport = false;
- mFloat32RenderSupport = false;
- }
- }
-
- // Check compressed texture support
- const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D;
-
- if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport)))
- {
- mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
- }
- else
- {
- mDXT1TextureSupport = false;
- }
-
- if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport)))
- {
- mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
- }
- else
- {
- mDXT3TextureSupport = false;
- }
-
- if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport)))
- {
- mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
- }
- else
- {
- mDXT5TextureSupport = false;
- }
-
- // Check depth texture support
- DXGI_FORMAT depthTextureFormats[] =
- {
- DXGI_FORMAT_D16_UNORM,
- DXGI_FORMAT_D24_UNORM_S8_UINT,
- };
-
- static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL |
- D3D11_FORMAT_SUPPORT_TEXTURE2D;
-
- mDepthTextureSupport = true;
- for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++)
- {
- if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport)))
- {
- mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags);
- }
- else
- {
- mDepthTextureSupport = false;
- }
- }
-
-#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
- // Monitor when the application suspends so that Trim() can be called
- Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::Core::ICoreApplication> application;
- result = RoGetActivationFactory(Microsoft::WRL::Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
- IID_PPV_ARGS(&application));
- if (FAILED(result))
- {
- ERR("Error obtaining CoreApplication: 0x%08X", result);
- return EGL_NOT_INITIALIZED;
- }
-
- EventRegistrationToken cookie;
- result = application->add_Suspending(Microsoft::WRL::Callback<SuspendEventHandler>(this, &Renderer11::onSuspend).Get(), &cookie);
- if (FAILED(result))
- {
- ERR("Error setting suspend callback: 0x%08X", result);
- return EGL_NOT_INITIALIZED;
- }
-#endif
-
- return EGL_SUCCESS;
-}
-
-#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
-HRESULT Renderer11::onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *)
-{
- if (!mDevice)
- return S_OK;
-
- Microsoft::WRL::ComPtr<IDXGIDevice3> dxgiDevice;
- HRESULT result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice));
- if (FAILED(result))
- {
- ERR("Error obtaining DXGIDevice3 on suspend: 0x%08X", result);
- return S_OK;
- }
-
- dxgiDevice->Trim();
-
- return S_OK;
-}
-#endif
-
-// 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()
-{
- mStateCache.initialize(mDevice);
- mInputLayoutCache.initialize(mDevice, mDeviceContext);
-
- ASSERT(!mVertexDataManager && !mIndexDataManager);
- mVertexDataManager = new VertexDataManager(this);
- mIndexDataManager = new IndexDataManager(this);
-
- markAllStateDirty();
-}
-
-int Renderer11::generateConfigs(ConfigDesc **configDescList)
-{
- unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
- unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
- (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
- int numConfigs = 0;
-
- for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
- {
- for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
- {
- DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
-
- UINT formatSupport = 0;
- HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport);
-
- if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET))
- {
- DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
-
- bool depthStencilFormatOK = true;
-
- if (depthStencilFormat != DXGI_FORMAT_UNKNOWN)
- {
- UINT formatSupport = 0;
- result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport);
- depthStencilFormatOK = SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL);
- }
-
- if (depthStencilFormatOK)
- {
- ConfigDesc newConfig;
- newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat);
- newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat);
- newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
- newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast
-
- (*configDescList)[numConfigs++] = newConfig;
- }
- }
- }
- }
-
- return numConfigs;
-}
-
-void Renderer11::deleteConfigs(ConfigDesc *configDescList)
-{
- delete [] (configDescList);
-}
-
-void Renderer11::sync(bool block)
-{
- if (block)
- {
- HRESULT result;
-
- if (!mSyncQuery)
- {
- D3D11_QUERY_DESC queryDesc;
- queryDesc.Query = D3D11_QUERY_EVENT;
- queryDesc.MiscFlags = 0;
-
- result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
- ASSERT(SUCCEEDED(result));
- }
-
- mDeviceContext->End(mSyncQuery);
- mDeviceContext->Flush();
-
- do
- {
- result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
-
- // Keep polling, but allow other threads to do something useful first
- Sleep(0);
-
- if (testDeviceLost(true))
- {
- return;
- }
- }
- while (result == S_FALSE);
- }
- else
- {
- mDeviceContext->Flush();
- }
-}
-
-SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
-{
- return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat);
-}
-
-void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
-{
- if (type == gl::SAMPLER_PIXEL)
- {
- if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS)
- {
- ERR("Pixel shader sampler index %i is not valid.", index);
- return;
- }
-
- if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
- {
- ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState);
-
- if (!dxSamplerState)
- {
- ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
- "sampler state for pixel shaders at slot %i.", index);
- }
-
- mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
-
- mCurPixelSamplerStates[index] = samplerState;
- }
-
- mForceSetPixelSamplerStates[index] = false;
- }
- else if (type == gl::SAMPLER_VERTEX)
- {
- if (index < 0 || index >= (int)getMaxVertexTextureImageUnits())
- {
- ERR("Vertex shader sampler index %i is not valid.", index);
- return;
- }
-
- if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
- {
- ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState);
-
- if (!dxSamplerState)
- {
- ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
- "sampler state for vertex shaders at slot %i.", index);
- }
-
- mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
-
- mCurVertexSamplerStates[index] = samplerState;
- }
-
- mForceSetVertexSamplerStates[index] = false;
- }
- else UNREACHABLE();
-}
-
-void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
-{
- ID3D11ShaderResourceView *textureSRV = NULL;
- unsigned int serial = 0;
- bool forceSetTexture = false;
-
- if (texture)
- {
- TextureStorageInterface *texStorage = texture->getNativeTexture();
- if (texStorage)
- {
- TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance());
- textureSRV = storage11->getSRV();
- }
-
- // 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);
-
- serial = texture->getTextureSerial();
- forceSetTexture = texture->hasDirtyImages();
- }
-
- if (type == gl::SAMPLER_PIXEL)
- {
- if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS)
- {
- ERR("Pixel shader sampler index %i is not valid.", index);
- return;
- }
-
- if (forceSetTexture || mCurPixelTextureSerials[index] != serial)
- {
- mDeviceContext->PSSetShaderResources(index, 1, &textureSRV);
- }
-
- mCurPixelTextureSerials[index] = serial;
- }
- else if (type == gl::SAMPLER_VERTEX)
- {
- if (index < 0 || index >= (int)getMaxVertexTextureImageUnits())
- {
- ERR("Vertex shader sampler index %i is not valid.", index);
- return;
- }
-
- if (forceSetTexture || mCurVertexTextureSerials[index] != serial)
- {
- mDeviceContext->VSSetShaderResources(index, 1, &textureSRV);
- }
-
- mCurVertexTextureSerials[index] = serial;
- }
- else UNREACHABLE();
-}
-
-void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
-{
- if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
- {
- ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled,
- mCurDepthSize);
- if (!dxRasterState)
- {
- ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default"
- "rasterizer state.");
- }
-
- mDeviceContext->RSSetState(dxRasterState);
-
- mCurRasterState = rasterState;
- }
-
- mForceSetRasterState = false;
-}
-
-void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor,
- unsigned int sampleMask)
-{
- if (mForceSetBlendState ||
- memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 ||
- memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 ||
- sampleMask != mCurSampleMask)
- {
- ID3D11BlendState *dxBlendState = mStateCache.getBlendState(framebuffer, blendState);
- if (!dxBlendState)
- {
- ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default "
- "blend state.");
- }
-
- 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;
- }
-
- mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
-
- mCurBlendState = blendState;
- mCurBlendColor = blendColor;
- mCurSampleMask = sampleMask;
- }
-
- mForceSetBlendState = false;
-}
-
-void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
- int stencilBackRef, bool frontFaceCCW)
-{
- if (mForceSetDepthStencilState ||
- memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
- stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
- {
- if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
- stencilRef != stencilBackRef ||
- depthStencilState.stencilMask != depthStencilState.stencilBackMask)
- {
- ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are "
- "invalid under WebGL.");
- return gl::error(GL_INVALID_OPERATION);
- }
-
- ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState);
- if (!dxDepthStencilState)
- {
- ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, "
- "setting the default depth stencil state.");
- }
-
- mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast<UINT>(stencilRef));
-
- mCurDepthStencilState = depthStencilState;
- mCurStencilRef = stencilRef;
- mCurStencilBackRef = stencilBackRef;
- }
-
- mForceSetDepthStencilState = false;
-}
-
-void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
-{
- if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
- enabled != mScissorEnabled)
- {
- if (enabled)
- {
- D3D11_RECT rect;
- rect.left = std::max(0, scissor.x);
- rect.top = std::max(0, scissor.y);
- rect.right = scissor.x + std::max(0, scissor.width);
- rect.bottom = scissor.y + std::max(0, scissor.height);
-
- mDeviceContext->RSSetScissorRects(1, &rect);
- }
-
- if (enabled != mScissorEnabled)
- {
- mForceSetRasterState = true;
- }
-
- mCurScissor = scissor;
- mScissorEnabled = enabled;
- }
-
- mForceSetScissor = false;
-}
-
-bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
- bool ignoreViewport)
-{
- gl::Rectangle actualViewport = viewport;
- float actualZNear = gl::clamp01(zNear);
- float actualZFar = gl::clamp01(zFar);
- if (ignoreViewport)
- {
- actualViewport.x = 0;
- actualViewport.y = 0;
- actualViewport.width = mRenderTargetDesc.width;
- actualViewport.height = mRenderTargetDesc.height;
- actualZNear = 0.0f;
- actualZFar = 1.0f;
- }
-
- // Get D3D viewport bounds, which depends on the feature level
- const Range& viewportBounds = getViewportBounds();
-
- // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds
- D3D11_VIEWPORT dxViewport;
- dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end);
- dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end);
- dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension());
- dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension());
- dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast<int>(dxViewport.TopLeftX));
- dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast<int>(dxViewport.TopLeftY));
- dxViewport.MinDepth = actualZNear;
- dxViewport.MaxDepth = actualZFar;
-
- if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
- {
- return false; // Nothing to render
- }
-
- bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
- actualZNear != mCurNear || actualZFar != mCurFar;
-
- if (viewportChanged)
- {
- mDeviceContext->RSSetViewports(1, &dxViewport);
-
- mCurViewport = actualViewport;
- mCurNear = actualZNear;
- mCurFar = actualZFar;
-
- mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f;
- mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f;
- mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
- mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
-
- 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;
- }
-
- mForceSetViewport = false;
- return true;
-}
-
-bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
-{
- 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:
- return gl::error(GL_INVALID_ENUM, false);
- }
-
- if (primitiveTopology != mCurrentPrimitiveTopology)
- {
- mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
- mCurrentPrimitiveTopology = primitiveTopology;
- }
-
- return count >= minCount;
-}
-
-bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
-{
- // Get the color render buffer and serial
- // Also extract the render target dimensions and view
- unsigned int renderTargetWidth = 0;
- unsigned int renderTargetHeight = 0;
- GLenum renderTargetFormat = 0;
- unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0};
- ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
- bool missingColorRenderTarget = true;
-
- for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment);
-
- if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE)
- {
- // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order)
- ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
-
- gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment);
-
- if (!colorbuffer)
- {
- ERR("render target pointer unexpectedly null.");
- return 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 (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
- {
- return false;
- }
-
- renderTargetSerials[colorAttachment] = colorbuffer->getSerial();
-
- // Extract the render target dimensions and view
- RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
- if (!renderTarget)
- {
- ERR("render target pointer unexpectedly null.");
- return false;
- }
-
- framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
- if (!framebufferRTVs[colorAttachment])
- {
- ERR("render target view pointer unexpectedly null.");
- return false;
- }
-
- if (missingColorRenderTarget)
- {
- renderTargetWidth = colorbuffer->getWidth();
- renderTargetHeight = colorbuffer->getHeight();
- renderTargetFormat = colorbuffer->getActualFormat();
- missingColorRenderTarget = false;
- }
-
-#ifdef _DEBUG
- // Workaround for Debug SETSHADERRESOURCES_HAZARD D3D11 warnings
- for (unsigned int vertexSerialIndex = 0; vertexSerialIndex < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; vertexSerialIndex++)
- {
- if (colorbuffer->getTextureSerial() != 0 && mCurVertexTextureSerials[vertexSerialIndex] == colorbuffer->getTextureSerial())
- {
- setTexture(gl::SAMPLER_VERTEX, vertexSerialIndex, NULL);
- }
- }
-
- for (unsigned int pixelSerialIndex = 0; pixelSerialIndex < gl::MAX_TEXTURE_IMAGE_UNITS; pixelSerialIndex++)
- {
- if (colorbuffer->getTextureSerial() != 0 && mCurPixelTextureSerials[pixelSerialIndex] == colorbuffer->getTextureSerial())
- {
- setTexture(gl::SAMPLER_PIXEL, pixelSerialIndex, NULL);
- }
- }
-#endif
- }
- }
-
- // Get the depth stencil render buffer and serials
- gl::Renderbuffer *depthStencil = NULL;
- unsigned int depthbufferSerial = 0;
- unsigned int stencilbufferSerial = 0;
- if (framebuffer->getDepthbufferType() != GL_NONE)
- {
- depthStencil = framebuffer->getDepthbuffer();
- if (!depthStencil)
- {
- ERR("Depth stencil pointer unexpectedly null.");
- SafeRelease(framebufferRTVs);
- return false;
- }
-
- depthbufferSerial = depthStencil->getSerial();
- }
- else if (framebuffer->getStencilbufferType() != GL_NONE)
- {
- depthStencil = framebuffer->getStencilbuffer();
- if (!depthStencil)
- {
- ERR("Depth stencil pointer unexpectedly null.");
- SafeRelease(framebufferRTVs);
- return false;
- }
-
- stencilbufferSerial = depthStencil->getSerial();
- }
-
- // Extract the depth stencil sizes and view
- unsigned int depthSize = 0;
- unsigned int stencilSize = 0;
- ID3D11DepthStencilView* framebufferDSV = NULL;
- if (depthStencil)
- {
- RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil());
- if (!depthStencilRenderTarget)
- {
- ERR("render target pointer unexpectedly null.");
- SafeRelease(framebufferRTVs);
- return false;
- }
-
- framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
- if (!framebufferDSV)
- {
- ERR("depth stencil view pointer unexpectedly null.");
- SafeRelease(framebufferRTVs);
- return false;
- }
-
- // If there is no render buffer, the width, height and format values come from
- // the depth stencil
- if (missingColorRenderTarget)
- {
- renderTargetWidth = depthStencil->getWidth();
- renderTargetHeight = depthStencil->getHeight();
- renderTargetFormat = depthStencil->getActualFormat();
- }
-
- depthSize = depthStencil->getDepthSize();
- stencilSize = depthStencil->getStencilSize();
- }
-
- // Apply the render target and depth stencil
- if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
- memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 ||
- depthbufferSerial != mAppliedDepthbufferSerial ||
- stencilbufferSerial != mAppliedStencilbufferSerial)
- {
- mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV);
-
- mRenderTargetDesc.width = renderTargetWidth;
- mRenderTargetDesc.height = renderTargetHeight;
- mRenderTargetDesc.format = renderTargetFormat;
- mForceSetViewport = true;
- mForceSetScissor = true;
-
- if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
- {
- mCurDepthSize = depthSize;
- mForceSetRasterState = true;
- }
-
- mCurStencilSize = stencilSize;
-
- for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
- {
- mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex];
- }
- mAppliedDepthbufferSerial = depthbufferSerial;
- mAppliedStencilbufferSerial = stencilbufferSerial;
- mRenderTargetDescInitialized = true;
- mDepthStencilInitialized = true;
- }
-
- return true;
-}
-
-GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
-{
- TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
- GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
- if (err != GL_NO_ERROR)
- {
- return err;
- }
-
- return mInputLayoutCache.applyVertexBuffers(attributes, programBinary);
-}
-
-GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
-{
- GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
-
- if (err == GL_NO_ERROR)
- {
- if (indexInfo->storage)
- {
- if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset)
- {
- BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage);
- IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
-
- mDeviceContext->IASetIndexBuffer(storage->getBuffer(BUFFER_USAGE_INDEX), indexBuffer->getIndexFormat(), indexInfo->startOffset);
-
- mAppliedIBSerial = 0;
- mAppliedStorageIBSerial = storage->getSerial();
- mAppliedIBOffset = indexInfo->startOffset;
- }
- }
- else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset)
- {
- IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
-
- mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset);
-
- mAppliedIBSerial = indexInfo->serial;
- mAppliedStorageIBSerial = 0;
- mAppliedIBOffset = indexInfo->startOffset;
- }
- }
-
- return err;
-}
-
-void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
-{
- if (mode == GL_LINE_LOOP)
- {
- drawLineLoop(count, GL_NONE, NULL, 0, NULL);
- }
- else if (mode == GL_TRIANGLE_FAN)
- {
- drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances);
- }
- else if (instances > 0)
- {
- mDeviceContext->DrawInstanced(count, instances, 0, 0);
- }
- else
- {
- mDeviceContext->Draw(count, 0);
- }
-}
-
-void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances)
-{
- if (mode == GL_LINE_LOOP)
- {
- drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
- }
- else if (mode == GL_TRIANGLE_FAN)
- {
- drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances);
- }
- else if (instances > 0)
- {
- mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast<int>(indexInfo.minIndex), 0);
- }
- else
- {
- mDeviceContext->DrawIndexed(count, 0, -static_cast<int>(indexInfo.minIndex));
- }
-}
-
-template<typename T>
-static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data)
-{
- 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();
- }
-}
-
-template<typename T>
-static void fillTriangleFanIndices(GLenum type, unsigned int numTris, const GLvoid *indices, T *data)
-{
- switch (type)
- {
- case GL_NONE: // Non-indexed draw
- for (unsigned int i = 0; i < numTris; i++)
- {
- data[i*3 + 0] = 0;
- data[i*3 + 1] = i + 1;
- data[i*3 + 2] = i + 2;
- }
- break;
- case GL_UNSIGNED_BYTE:
- for (unsigned int i = 0; i < numTris; i++)
- {
- data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
- data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
- data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
- }
- break;
- case GL_UNSIGNED_SHORT:
- for (unsigned int i = 0; i < numTris; i++)
- {
- data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
- data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
- data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
- }
- break;
- case GL_UNSIGNED_INT:
- for (unsigned int i = 0; i < numTris; i++)
- {
- data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
- data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
- data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
- }
- break;
- default: UNREACHABLE();
- }
-}
-
-void Renderer11::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)
- {
- gl::Buffer *indexBuffer = elementArrayBuffer;
- BufferStorage *storage = indexBuffer->getStorage();
- intptr_t offset = reinterpret_cast<intptr_t>(indices);
- indices = static_cast<const GLubyte*>(storage->getData()) + offset;
- }
-
- const int indexType = get32BitIndexSupport() ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
-
- if (!mLineLoopIB)
- {
- mLineLoopIB = new StreamingIndexBufferInterface(this);
- if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType))
- {
- delete mLineLoopIB;
- mLineLoopIB = NULL;
-
- ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
- return gl::error(GL_OUT_OF_MEMORY);
- }
- }
-
- // Checked by Renderer11::applyPrimitiveType
- ASSERT(count >= 0);
-
- if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
- {
- ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
- return gl::error(GL_OUT_OF_MEMORY);
- }
-
- const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
- if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, indexType))
- {
- ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
- return gl::error(GL_OUT_OF_MEMORY);
- }
-
- void* mappedMemory = NULL;
- unsigned int offset;
- if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
- {
- ERR("Could not map index buffer for GL_LINE_LOOP.");
- return gl::error(GL_OUT_OF_MEMORY);
- }
-
- if (indexType == GL_UNSIGNED_SHORT)
- fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned short*>(mappedMemory));
- else
- fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned int*>(mappedMemory));
- unsigned int indexBufferOffset = offset;
-
- if (!mLineLoopIB->unmapBuffer())
- {
- ERR("Could not unmap index buffer for GL_LINE_LOOP.");
- return gl::error(GL_OUT_OF_MEMORY);
- }
-
- if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
- {
- IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer());
-
- mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
- mAppliedIBSerial = mLineLoopIB->getSerial();
- mAppliedStorageIBSerial = 0;
- mAppliedIBOffset = indexBufferOffset;
- }
-
- mDeviceContext->DrawIndexed(count + 1, 0, -minIndex);
-}
-
-void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances)
-{
- // Get the raw indices for an indexed draw
- if (type != GL_NONE && elementArrayBuffer)
- {
- gl::Buffer *indexBuffer = elementArrayBuffer;
- BufferStorage *storage = indexBuffer->getStorage();
- intptr_t offset = reinterpret_cast<intptr_t>(indices);
- indices = static_cast<const GLubyte*>(storage->getData()) + offset;
- }
-
- const int indexType = get32BitIndexSupport() ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
-
- if (!mTriangleFanIB)
- {
- mTriangleFanIB = new StreamingIndexBufferInterface(this);
- if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType))
- {
- delete mTriangleFanIB;
- mTriangleFanIB = NULL;
-
- ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN.");
- return gl::error(GL_OUT_OF_MEMORY);
- }
- }
-
- // Checked by Renderer11::applyPrimitiveType
- ASSERT(count >= 3);
-
- const unsigned int numTris = count - 2;
-
- if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
- {
- ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
- return gl::error(GL_OUT_OF_MEMORY);
- }
-
- const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
- if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType))
- {
- ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN.");
- return gl::error(GL_OUT_OF_MEMORY);
- }
-
- void* mappedMemory = NULL;
- unsigned int offset;
- if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
- {
- ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN.");
- return gl::error(GL_OUT_OF_MEMORY);
- }
-
- if (indexType == GL_UNSIGNED_SHORT)
- fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned short*>(mappedMemory));
- else
- fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned int*>(mappedMemory));
- unsigned int indexBufferOffset = offset;
-
-
- if (!mTriangleFanIB->unmapBuffer())
- {
- ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN.");
- return gl::error(GL_OUT_OF_MEMORY);
- }
-
- if (mAppliedIBSerial != mTriangleFanIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
- {
- IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer());
-
- mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
- mAppliedIBSerial = mTriangleFanIB->getSerial();
- mAppliedStorageIBSerial = 0;
- mAppliedIBOffset = indexBufferOffset;
- }
-
- if (instances > 0)
- {
- mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0);
- }
- else
- {
- mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex);
- }
-}
-
-void Renderer11::applyShaders(gl::ProgramBinary *programBinary)
-{
- unsigned int programBinarySerial = programBinary->getSerial();
- const bool updateProgramState = (programBinarySerial != mAppliedProgramBinarySerial);
-
- if (updateProgramState)
- {
- ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
- ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
-
- ID3D11VertexShader *vertexShader = NULL;
- if (vertexExe) vertexShader = ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader();
-
- ID3D11PixelShader *pixelShader = NULL;
- if (pixelExe) pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader();
-
- mDeviceContext->PSSetShader(pixelShader, NULL, 0);
- mDeviceContext->VSSetShader(vertexShader, NULL, 0);
-
- programBinary->dirtyAllUniforms();
-
- mAppliedProgramBinarySerial = programBinarySerial;
- }
-
- // Only use the geometry shader currently for point sprite drawing
- const bool usesGeometryShader = (programBinary->usesGeometryShader() && mCurRasterState.pointDrawMode);
-
- if (updateProgramState || usesGeometryShader != mIsGeometryShaderActive)
- {
- if (usesGeometryShader)
- {
- ShaderExecutable *geometryExe = programBinary->getGeometryExecutable();
- ID3D11GeometryShader *geometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader();
- mDeviceContext->GSSetShader(geometryShader, NULL, 0);
- }
- else
- {
- mDeviceContext->GSSetShader(NULL, NULL, 0);
- }
-
- mIsGeometryShaderActive = usesGeometryShader;
- }
-}
-
-void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray)
-{
- ShaderExecutable11 *vertexExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
- ShaderExecutable11 *pixelExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getPixelExecutable());
-
- unsigned int totalRegisterCountVS = 0;
- unsigned int totalRegisterCountPS = 0;
-
- bool vertexUniformsDirty = false;
- bool pixelUniformsDirty = false;
-
- for (gl::UniformArray::const_iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
- {
- const gl::Uniform *uniform = *uniform_iterator;
-
- if (uniform->vsRegisterIndex >= 0)
- {
- totalRegisterCountVS += uniform->registerCount;
- vertexUniformsDirty = vertexUniformsDirty || uniform->dirty;
- }
-
- if (uniform->psRegisterIndex >= 0)
- {
- totalRegisterCountPS += uniform->registerCount;
- pixelUniformsDirty = pixelUniformsDirty || uniform->dirty;
- }
- }
-
- ID3D11Buffer *vertexConstantBuffer = vertexExecutable->getConstantBuffer(mDevice, totalRegisterCountVS);
- ID3D11Buffer *pixelConstantBuffer = pixelExecutable->getConstantBuffer(mDevice, totalRegisterCountPS);
-
- 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 (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
- {
- gl::Uniform *uniform = *uniform_iterator;
-
- if (uniform->type != GL_SAMPLER_2D && uniform->type != GL_SAMPLER_CUBE)
- {
- if (uniform->vsRegisterIndex >= 0 && mapVS)
- {
- memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4]));
- }
-
- if (uniform->psRegisterIndex >= 0 && mapPS)
- {
- memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4]));
- }
- }
-
- uniform->dirty = false;
- }
-
- if (mapVS)
- {
- mDeviceContext->Unmap(vertexConstantBuffer, 0);
- }
-
- if (mapPS)
- {
- mDeviceContext->Unmap(pixelConstantBuffer, 0);
- }
-
- if (mCurrentVertexConstantBuffer != vertexConstantBuffer)
- {
- mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer);
- mCurrentVertexConstantBuffer = vertexConstantBuffer;
- }
-
- if (mCurrentPixelConstantBuffer != pixelConstantBuffer)
- {
- mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer);
- mCurrentPixelConstantBuffer = pixelConstantBuffer;
- }
-
- // Driver uniforms
- if (!mDriverConstantBufferVS)
- {
- D3D11_BUFFER_DESC constantBufferDescription = {0};
- constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants);
- constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
- constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
- constantBufferDescription.CPUAccessFlags = 0;
- constantBufferDescription.MiscFlags = 0;
- constantBufferDescription.StructureByteStride = 0;
-
- HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS);
- ASSERT(SUCCEEDED(result));
-
- mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS);
- }
-
- if (!mDriverConstantBufferPS)
- {
- D3D11_BUFFER_DESC constantBufferDescription = {0};
- constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants);
- constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
- constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
- constantBufferDescription.CPUAccessFlags = 0;
- constantBufferDescription.MiscFlags = 0;
- constantBufferDescription.StructureByteStride = 0;
-
- HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS);
- ASSERT(SUCCEEDED(result));
-
- mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS);
- }
-
- if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0)
- {
- mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0);
- memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants));
- }
-
- if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0)
- {
- mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0);
- memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants));
- }
-
- // needed for the point sprite geometry shader
- if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
- {
- mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
- mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
- }
-}
-
-void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
-{
- gl::Renderbuffer *firstRenderbuffer = frameBuffer->getFirstColorbuffer();
- GLenum internalFormat = firstRenderbuffer ? firstRenderbuffer->getInternalFormat() : GL_NONE;
-
- bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
- ((!clearParams.colorMaskRed && gl::GetRedSize(internalFormat) > 0) ||
- (!clearParams.colorMaskGreen && gl::GetGreenSize(internalFormat) > 0) ||
- (!clearParams.colorMaskBlue && gl::GetBlueSize(internalFormat) > 0) ||
- (!clearParams.colorMaskAlpha && gl::GetAlphaSize(internalFormat) > 0));
-
- unsigned int stencilUnmasked = 0x0;
- if (frameBuffer->hasStencil())
- {
- unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
- stencilUnmasked = (0x1 << stencilSize) - 1;
- }
- bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
- (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
-
- bool needScissoredClear = mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 ||
- mCurScissor.x + mCurScissor.width < mRenderTargetDesc.width ||
- mCurScissor.y + mCurScissor.height < mRenderTargetDesc.height);
-
- if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear)
- {
- maskedClear(clearParams, frameBuffer);
- }
- else
- {
- if (clearParams.mask & GL_COLOR_BUFFER_BIT)
- {
- for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- if (frameBuffer->isEnabledColorAttachment(colorAttachment))
- {
- gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer(colorAttachment);
- if (renderbufferObject)
- {
- RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
- if (!renderTarget)
- {
- ERR("render target pointer unexpectedly null.");
- return;
- }
-
- ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
- if (!framebufferRTV)
- {
- ERR("render target view pointer unexpectedly null.");
- return;
- }
-
- GLenum format = renderbufferObject->getInternalFormat();
-
- const float clearValues[4] = { (gl::GetRedSize(format) > 0) ? clearParams.colorClearValue.red : 0.0f,
- (gl::GetGreenSize(format) > 0) ? clearParams.colorClearValue.green : 0.0f,
- (gl::GetBlueSize(format) > 0) ? clearParams.colorClearValue.blue : 0.0f,
- (gl::GetAlphaSize(format) > 0) ? clearParams.colorClearValue.alpha : 1.0f };
- mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
- }
- }
- }
- }
- if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT)
- {
- gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer();
- if (renderbufferObject)
- {
- RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getDepthStencil());
- if (!renderTarget)
- {
- ERR("render target pointer unexpectedly null.");
- return;
- }
-
- ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
- if (!framebufferDSV)
- {
- ERR("depth stencil view pointer unexpectedly null.");
- return;
- }
-
- UINT clearFlags = 0;
- if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
- {
- clearFlags |= D3D11_CLEAR_DEPTH;
- }
- if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
- {
- clearFlags |= D3D11_CLEAR_STENCIL;
- }
-
- float depthClear = gl::clamp01(clearParams.depthClearValue);
- UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF;
-
- mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
- }
- }
- }
-}
-
-void Renderer11::maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
-{
- HRESULT result;
-
- if (!mClearResourcesInitialized)
- {
- ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS);
-
- D3D11_BUFFER_DESC vbDesc;
- vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 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 = mDevice->CreateBuffer(&vbDesc, NULL, &mClearVB);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mClearVB, "Renderer11 masked clear vertex buffer");
-
- D3D11_INPUT_ELEMENT_DESC quadLayout[] =
- {
- { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
- { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
- };
-
- result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Clear, sizeof(g_VS_Clear), &mClearIL);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mClearIL, "Renderer11 masked clear input layout");
-
- result = mDevice->CreateVertexShader(g_VS_Clear, sizeof(g_VS_Clear), NULL, &mClearVS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader");
-
- result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)");
-
- result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)");
-
- D3D11_RASTERIZER_DESC rsScissorDesc;
- rsScissorDesc.FillMode = D3D11_FILL_SOLID;
- rsScissorDesc.CullMode = D3D11_CULL_NONE;
- rsScissorDesc.FrontCounterClockwise = FALSE;
- rsScissorDesc.DepthBias = 0;
- rsScissorDesc.DepthBiasClamp = 0.0f;
- rsScissorDesc.SlopeScaledDepthBias = 0.0f;
- rsScissorDesc.DepthClipEnable = FALSE;
- rsScissorDesc.ScissorEnable = TRUE;
- rsScissorDesc.MultisampleEnable = FALSE;
- rsScissorDesc.AntialiasedLineEnable = FALSE;
-
- result = mDevice->CreateRasterizerState(&rsScissorDesc, &mClearScissorRS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mClearScissorRS, "Renderer11 masked clear scissor rasterizer state");
-
- D3D11_RASTERIZER_DESC rsNoScissorDesc;
- rsNoScissorDesc.FillMode = D3D11_FILL_SOLID;
- rsNoScissorDesc.CullMode = D3D11_CULL_NONE;
- rsNoScissorDesc.FrontCounterClockwise = FALSE;
- rsNoScissorDesc.DepthBias = 0;
- rsNoScissorDesc.DepthBiasClamp = 0.0f;
- rsNoScissorDesc.SlopeScaledDepthBias = 0.0f;
- rsNoScissorDesc.DepthClipEnable = FALSE;
- rsNoScissorDesc.ScissorEnable = FALSE;
- rsNoScissorDesc.MultisampleEnable = FALSE;
- rsNoScissorDesc.AntialiasedLineEnable = FALSE;
-
- result = mDevice->CreateRasterizerState(&rsNoScissorDesc, &mClearNoScissorRS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mClearNoScissorRS, "Renderer11 masked clear no scissor rasterizer state");
-
- mClearResourcesInitialized = true;
- }
-
- // Prepare the depth stencil state to write depth values if the depth should be cleared
- // and stencil values if the stencil should be cleared
- gl::DepthStencilState glDSState;
- glDSState.depthTest = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0;
- glDSState.depthFunc = GL_ALWAYS;
- glDSState.depthMask = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0;
- glDSState.stencilTest = (clearParams.mask & GL_STENCIL_BUFFER_BIT) != 0;
- glDSState.stencilFunc = GL_ALWAYS;
- glDSState.stencilMask = 0;
- glDSState.stencilFail = GL_REPLACE;
- glDSState.stencilPassDepthFail = GL_REPLACE;
- glDSState.stencilPassDepthPass = GL_REPLACE;
- glDSState.stencilWritemask = clearParams.stencilWriteMask;
- glDSState.stencilBackFunc = GL_ALWAYS;
- glDSState.stencilBackMask = 0;
- glDSState.stencilBackFail = GL_REPLACE;
- glDSState.stencilBackPassDepthFail = GL_REPLACE;
- glDSState.stencilBackPassDepthPass = GL_REPLACE;
- glDSState.stencilBackWritemask = clearParams.stencilWriteMask;
-
- int stencilClear = clearParams.stencilClearValue & 0x000000FF;
-
- ID3D11DepthStencilState *dsState = mStateCache.getDepthStencilState(glDSState);
-
- // Prepare the blend state to use a write mask if the color buffer should be cleared
- gl::BlendState glBlendState;
- glBlendState.blend = false;
- glBlendState.sourceBlendRGB = GL_ONE;
- glBlendState.destBlendRGB = GL_ZERO;
- glBlendState.sourceBlendAlpha = GL_ONE;
- glBlendState.destBlendAlpha = GL_ZERO;
- glBlendState.blendEquationRGB = GL_FUNC_ADD;
- glBlendState.blendEquationAlpha = GL_FUNC_ADD;
- glBlendState.colorMaskRed = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskRed : false;
- glBlendState.colorMaskGreen = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskGreen : false;
- glBlendState.colorMaskBlue = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskBlue : false;
- glBlendState.colorMaskAlpha = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskAlpha : false;
- glBlendState.sampleAlphaToCoverage = false;
- glBlendState.dither = false;
-
- static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
- static const UINT sampleMask = 0xFFFFFFFF;
-
- ID3D11BlendState *blendState = mStateCache.getBlendState(frameBuffer, glBlendState);
-
- // Set the vertices
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- result = mDeviceContext->Map(mClearVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
- if (FAILED(result))
- {
- ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result);
- return;
- }
-
- d3d11::PositionDepthColorVertex *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex*>(mappedResource.pData);
-
- float depthClear = gl::clamp01(clearParams.depthClearValue);
- d3d11::SetPositionDepthColorVertex(&vertices[0], -1.0f, 1.0f, depthClear, clearParams.colorClearValue);
- d3d11::SetPositionDepthColorVertex(&vertices[1], -1.0f, -1.0f, depthClear, clearParams.colorClearValue);
- d3d11::SetPositionDepthColorVertex(&vertices[2], 1.0f, 1.0f, depthClear, clearParams.colorClearValue);
- d3d11::SetPositionDepthColorVertex(&vertices[3], 1.0f, -1.0f, depthClear, clearParams.colorClearValue);
-
- mDeviceContext->Unmap(mClearVB, 0);
-
- // Apply state
- mDeviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
- mDeviceContext->OMSetDepthStencilState(dsState, stencilClear);
- mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS);
-
- // Apply shaders
- ID3D11PixelShader *pixelShader = frameBuffer->usingExtendedDrawBuffers() ? mClearMultiplePS : mClearSinglePS;
-
- mDeviceContext->IASetInputLayout(mClearIL);
- mDeviceContext->VSSetShader(mClearVS, NULL, 0);
- mDeviceContext->PSSetShader(pixelShader, NULL, 0);
- mDeviceContext->GSSetShader(NULL, NULL, 0);
-
- // Apply vertex buffer
- static UINT stride = sizeof(d3d11::PositionDepthColorVertex);
- static UINT startIdx = 0;
- mDeviceContext->IASetVertexBuffers(0, 1, &mClearVB, &stride, &startIdx);
- mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
-
- // Draw the clear quad
- mDeviceContext->Draw(4, 0);
-
- // Clean up
- markAllStateDirty();
-}
-
-void Renderer11::markAllStateDirty()
-{
- for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
- {
- mAppliedRenderTargetSerials[rtIndex] = 0;
- }
- mAppliedDepthbufferSerial = 0;
- mAppliedStencilbufferSerial = 0;
- mDepthStencilInitialized = false;
- mRenderTargetDescInitialized = false;
-
- for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
- {
- mForceSetVertexSamplerStates[i] = true;
- mCurVertexTextureSerials[i] = 0;
- }
- for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++)
- {
- mForceSetPixelSamplerStates[i] = true;
- mCurPixelTextureSerials[i] = 0;
- }
-
- mForceSetBlendState = true;
- mForceSetRasterState = true;
- mForceSetDepthStencilState = true;
- mForceSetScissor = true;
- mForceSetViewport = true;
-
- mAppliedIBSerial = 0;
- mAppliedStorageIBSerial = 0;
- mAppliedIBOffset = 0;
-
- mAppliedProgramBinarySerial = 0;
- memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants));
- memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants));
-
- mInputLayoutCache.markDirty();
-
- mCurrentVertexConstantBuffer = NULL;
- mCurrentPixelConstantBuffer = NULL;
- mCurrentGeometryConstantBuffer = NULL;
-
- mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
-}
-
-void Renderer11::releaseDeviceResources()
-{
- mStateCache.clear();
- mInputLayoutCache.clear();
-
- delete mVertexDataManager;
- mVertexDataManager = NULL;
-
- delete mIndexDataManager;
- mIndexDataManager = NULL;
-
- delete mLineLoopIB;
- mLineLoopIB = NULL;
-
- delete mTriangleFanIB;
- mTriangleFanIB = NULL;
-
- SafeRelease(mCopyVB);
- SafeRelease(mCopySampler);
- SafeRelease(mCopyIL);
- SafeRelease(mCopyIL);
- SafeRelease(mCopyVS);
- SafeRelease(mCopyRGBAPS);
- SafeRelease(mCopyRGBPS);
- SafeRelease(mCopyLumPS);
- SafeRelease(mCopyLumAlphaPS);
-
- mCopyResourcesInitialized = false;
-
- SafeRelease(mClearVB);
- SafeRelease(mClearIL);
- SafeRelease(mClearVS);
- SafeRelease(mClearSinglePS);
- SafeRelease(mClearMultiplePS);
- SafeRelease(mClearScissorRS);
- SafeRelease(mClearNoScissorRS);
-
- mClearResourcesInitialized = false;
-
- SafeRelease(mDriverConstantBufferVS);
- SafeRelease(mDriverConstantBufferPS);
- SafeRelease(mSyncQuery);
-}
-
-void Renderer11::notifyDeviceLost()
-{
- mDeviceLost = true;
- mDisplay->notifyDeviceLost();
-}
-
-bool Renderer11::isDeviceLost()
-{
- return mDeviceLost;
-}
-
-// set notify to true to broadcast a message to all contexts of the device loss
-bool Renderer11::testDeviceLost(bool notify)
-{
- bool isLost = false;
-
- // GetRemovedReason is used to test if the device is removed
- HRESULT result = mDevice->GetDeviceRemovedReason();
- isLost = d3d11::isDeviceLostError(result);
-
- if (isLost)
- {
- // Log error if this is a new device lost event
- if (mDeviceLost == false)
- {
- ERR("The D3D11 device was removed: 0x%08X", result);
- }
-
- // ensure we note the device loss --
- // we'll probably get this done again by notifyDeviceLost
- // but best to remember it!
- // Note that we don't want to clear the device loss status here
- // -- this needs to be done by resetDevice
- mDeviceLost = true;
- if (notify)
- {
- notifyDeviceLost();
- }
- }
-
- 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;
- }
-
- D3D_FEATURE_LEVEL featureLevels[] =
- {
- D3D_FEATURE_LEVEL_11_0,
- D3D_FEATURE_LEVEL_10_1,
- D3D_FEATURE_LEVEL_10_0,
-#if !defined(ANGLE_ENABLE_D3D9)
- D3D_FEATURE_LEVEL_9_3,
- D3D_FEATURE_LEVEL_9_2,
- D3D_FEATURE_LEVEL_9_1,
-#endif
- };
-
- ID3D11Device* dummyDevice;
- D3D_FEATURE_LEVEL dummyFeatureLevel;
- ID3D11DeviceContext* dummyContext;
-
- HRESULT result = D3D11CreateDevice(NULL,
- D3D_DRIVER_TYPE_HARDWARE,
- NULL,
- #if defined(_DEBUG)
- D3D11_CREATE_DEVICE_DEBUG,
- #else
- 0,
- #endif
- featureLevels,
- ArraySize(featureLevels),
- D3D11_SDK_VERSION,
- &dummyDevice,
- &dummyFeatureLevel,
- &dummyContext);
-
- if (!mDevice || FAILED(result))
- {
- return false;
- }
-
- dummyContext->Release();
- dummyDevice->Release();
-
- return true;
-}
-
-void Renderer11::release()
-{
- releaseDeviceResources();
-
- if (mDxgiFactory)
- {
- mDxgiFactory->Release();
- mDxgiFactory = NULL;
- }
-
- if (mDxgiAdapter)
- {
- mDxgiAdapter->Release();
- mDxgiAdapter = NULL;
- }
-
- if (mDeviceContext)
- {
- mDeviceContext->ClearState();
- mDeviceContext->Flush();
- mDeviceContext->Release();
- mDeviceContext = NULL;
- }
-
- if (mDevice)
- {
- mDevice->Release();
- mDevice = NULL;
- }
-
- if (mD3d11Module)
- {
- FreeLibrary(mD3d11Module);
- mD3d11Module = NULL;
- }
-
- if (mDxgiModule)
- {
- FreeLibrary(mDxgiModule);
- mDxgiModule = NULL;
- }
-}
-
-bool Renderer11::resetDevice()
-{
- // recreate everything
- release();
- EGLint result = initialize();
-
- if (result != EGL_SUCCESS)
- {
- ERR("Could not reinitialize D3D11 device: %08X", result);
- return false;
- }
-
- mDeviceLost = false;
-
- return true;
-}
-
-DWORD Renderer11::getAdapterVendor() const
-{
- return mAdapterDescription.VendorId;
-}
-
-std::string Renderer11::getRendererDescription() const
-{
- std::ostringstream rendererString;
-
- rendererString << mDescription;
- rendererString << " Direct3D11";
-
- rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel();
- rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel();
-
- return rendererString.str();
-}
-
-GUID Renderer11::getAdapterIdentifier() const
-{
- // Use the adapter LUID as our adapter ID
- // This number is local to a machine is only guaranteed to be unique between restarts
- META_ASSERT(sizeof(LUID) <= sizeof(GUID));
- GUID adapterId = {0};
- memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID));
- return adapterId;
-}
-
-bool Renderer11::getBGRATextureSupport() const
-{
- return mBGRATextureSupport;
-}
-
-bool Renderer11::getDXT1TextureSupport()
-{
- return mDXT1TextureSupport;
-}
-
-bool Renderer11::getDXT3TextureSupport()
-{
- return mDXT3TextureSupport;
-}
-
-bool Renderer11::getDXT5TextureSupport()
-{
- return mDXT5TextureSupport;
-}
-
-bool Renderer11::getDepthTextureSupport() const
-{
- return mDepthTextureSupport;
-}
-
-bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable)
-{
- *renderable = mFloat32RenderSupport;
- *filtering = mFloat32FilterSupport;
- return mFloat32TextureSupport;
-}
-
-bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable)
-{
- *renderable = mFloat16RenderSupport;
- *filtering = mFloat16FilterSupport;
- return mFloat16TextureSupport;
-}
-
-bool Renderer11::getLuminanceTextureSupport()
-{
- return false;
-}
-
-bool Renderer11::getLuminanceAlphaTextureSupport()
-{
- return false;
-}
-
-bool Renderer11::getTextureFilterAnisotropySupport() const
-{
- return true;
-}
-
-float Renderer11::getTextureMaxAnisotropy() const
-{
- switch (mFeatureLevel)
- {
- 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;
- 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 Renderer11::getEventQuerySupport()
-{
- return true;
-}
-
-Range Renderer11::getViewportBounds() const
-{
- switch (mFeatureLevel)
- {
- case D3D_FEATURE_LEVEL_11_0:
- return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX);
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
- return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX);
- case D3D_FEATURE_LEVEL_9_3:
- return Range(D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2);
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1:
- return Range(D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2);
- default: UNREACHABLE();
- return Range(0, 0);
- }
-}
-
-unsigned int Renderer11::getMaxVertexTextureImageUnits() const
-{
- META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
- switch (mFeatureLevel)
- {
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
- return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4;
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1:
- return 0;
- default: UNREACHABLE();
- return 0;
- }
-}
-
-unsigned int Renderer11::getMaxCombinedTextureImageUnits() const
-{
- return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
-}
-
-unsigned int Renderer11::getReservedVertexUniformVectors() const
-{
- return 0; // Driver uniforms are stored in a separate constant buffer
-}
-
-unsigned int Renderer11::getReservedFragmentUniformVectors() const
-{
- return 0; // Driver uniforms are stored in a separate constant buffer
-}
-
-unsigned int Renderer11::getMaxVertexUniformVectors() const
-{
- META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
- ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1);
- return MAX_VERTEX_UNIFORM_VECTORS_D3D11;
-}
-
-unsigned int Renderer11::getMaxFragmentUniformVectors() const
-{
- META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
- ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1);
- return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11;
-}
-
-unsigned int Renderer11::getMaxVaryingVectors() const
-{
- META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT);
- switch (mFeatureLevel)
- {
- case D3D_FEATURE_LEVEL_11_0:
- return D3D11_VS_OUTPUT_REGISTER_COUNT;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
- return D3D10_VS_OUTPUT_REGISTER_COUNT;
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1:
- return 8;
- default: UNREACHABLE();
- return 0;
- }
-}
-
-bool Renderer11::getNonPower2TextureSupport() const
-{
- switch (mFeatureLevel)
- {
- 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 Renderer11::getOcclusionQuerySupport() const
-{
- switch (mFeatureLevel)
- {
- 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:
- return true;
- case D3D_FEATURE_LEVEL_9_1:
- return false;
- default: UNREACHABLE();
- return false;
- }
-}
-
-bool Renderer11::getInstancingSupport() const
-{
- switch (mFeatureLevel)
- {
- 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 Renderer11::getShareHandleSupport() const
-{
- // We only currently support share handles with BGRA surfaces, because
- // chrome needs BGRA. Once chrome fixes this, we should always support them.
- // PIX doesn't seem to support using share handles, so disable them.
- return getBGRATextureSupport() && !gl::perfActive();
-}
-
-bool Renderer11::getDerivativeInstructionSupport() const
-{
- switch (mFeatureLevel)
- {
- 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:
- return true;
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1:
- return false;
- default: UNREACHABLE();
- return false;
- }
-}
-
-bool Renderer11::getPostSubBufferSupport() const
-{
- // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2.
- return false;
-}
-
-int Renderer11::getMajorShaderModel() const
-{
- switch (mFeatureLevel)
- {
- 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:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MAJOR_VERSION; // 4 (level 9)
- default: UNREACHABLE(); return 0;
- }
-}
-
-int Renderer11::getMinorShaderModel() const
-{
- switch (mFeatureLevel)
- {
- 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:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0 (level 9)
- default: UNREACHABLE(); return 0;
- }
-}
-
-float Renderer11::getMaxPointSize() const
-{
- // choose a reasonable maximum. we enforce this in the shader.
- // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size)
- return 1024.0f;
-}
-
-int Renderer11::getMaxViewportDimension() const
-{
- // Maximum viewport size must be at least as large as the largest render buffer (or larger).
- // In our case return the maximum texture size, which is the maximum render buffer size.
- META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX);
- META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX);
-
- switch (mFeatureLevel)
- {
- case D3D_FEATURE_LEVEL_11_0:
- return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
- return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
- case D3D_FEATURE_LEVEL_9_3:
- return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1:
- return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048
- default: UNREACHABLE();
- return 0;
- }
-}
-
-int Renderer11::getMaxTextureWidth() const
-{
- switch (mFeatureLevel)
- {
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
- case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048
- default: UNREACHABLE(); return 0;
- }
-}
-
-int Renderer11::getMaxTextureHeight() const
-{
- switch (mFeatureLevel)
- {
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
- case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048
- default: UNREACHABLE(); return 0;
- }
-}
-
-bool Renderer11::get32BitIndexSupport() const
-{
- switch (mFeatureLevel)
- {
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return false;
- default: UNREACHABLE(); return false;
- }
-}
-
-int Renderer11::getMinSwapInterval() const
-{
- return 0;
-}
-
-int Renderer11::getMaxSwapInterval() const
-{
- return 4;
-}
-
-int Renderer11::getMaxSupportedSamples() const
-{
- return mMaxSupportedSamples;
-}
-
-int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const
-{
- if (requested == 0)
- {
- return 0;
- }
-
- MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format);
- if (iter != mMultisampleSupportMap.end())
- {
- const MultisampleSupportInfo& info = iter->second;
- for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++)
- {
- if (info.qualityLevels[i] > 0)
- {
- return i + 1;
- }
- }
- }
-
- return -1;
-}
-
-unsigned int Renderer11::getMaxRenderTargets() const
-{
- META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
- META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
- META_ASSERT(D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
- META_ASSERT(D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
-
- switch (mFeatureLevel)
- {
- case D3D_FEATURE_LEVEL_11_0:
- return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
- case D3D_FEATURE_LEVEL_9_3: // return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; // 4
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: // return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; // 1
- // Feature level 10.0 and 10.1 cards perform very poorly when the pixel shader
- // outputs to multiple RTs that are not bound.
- // TODO: Remove pixel shader outputs for render targets that are not bound.
- return 1;
- default:
- UNREACHABLE();
- return 1;
- }
-}
-
-bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
-{
- if (source && dest)
- {
- TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance());
- TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance());
-
- mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
- return true;
- }
-
- return false;
-}
-
-bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source)
-{
- if (source && dest)
- {
- TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance());
- TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance());
-
- mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
- return true;
- }
-
- return false;
-}
-
-bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
-{
- gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
- if (!colorbuffer)
- {
- ERR("Failed to retrieve the color buffer from the frame buffer.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
- if (!sourceRenderTarget)
- {
- ERR("Failed to retrieve the render target from the frame buffer.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
- if (!source)
- {
- ERR("Failed to retrieve the render target view from the render target.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance());
- if (!storage11)
- {
- ERR("Failed to retrieve the texture storage from the destination.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level));
- if (!destRenderTarget)
- {
- ERR("Failed to retrieve the render target from the destination storage.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
- if (!dest)
- {
- ERR("Failed to retrieve the render target view from the destination render target.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- gl::Rectangle destRect;
- destRect.x = xoffset;
- destRect.y = yoffset;
- destRect.width = sourceRect.width;
- destRect.height = sourceRect.height;
-
- bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(),
- dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat);
-
- return ret;
-}
-
-bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
-{
- gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
- if (!colorbuffer)
- {
- ERR("Failed to retrieve the color buffer from the frame buffer.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
- if (!sourceRenderTarget)
- {
- ERR("Failed to retrieve the render target from the frame buffer.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
- if (!source)
- {
- ERR("Failed to retrieve the render target view from the render target.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance());
- if (!storage11)
- {
- ERR("Failed to retrieve the texture storage from the destination.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level));
- if (!destRenderTarget)
- {
- ERR("Failed to retrieve the render target from the destination storage.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
- if (!dest)
- {
- ERR("Failed to retrieve the render target view from the destination render target.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- gl::Rectangle destRect;
- destRect.x = xoffset;
- destRect.y = yoffset;
- destRect.width = sourceRect.width;
- destRect.height = sourceRect.height;
-
- bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(),
- dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat);
-
- return ret;
-}
-
-bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight,
- ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat)
-{
- HRESULT result;
-
- if (!mCopyResourcesInitialized)
- {
- ASSERT(!mCopyVB && !mCopySampler && !mCopyIL && !mCopyVS && !mCopyRGBAPS && !mCopyRGBPS && !mCopyLumPS && !mCopyLumAlphaPS);
-
- 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;
-
- result = mDevice->CreateBuffer(&vbDesc, NULL, &mCopyVB);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mCopyVB, "Renderer11 copy texture vertex buffer");
-
- D3D11_SAMPLER_DESC samplerDesc;
- samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
- 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.0f;
- samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 ? 0.0f : FLT_MAX;
-
- result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mCopySampler, "Renderer11 copy 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 = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mCopyIL);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mCopyIL, "Renderer11 copy texture input layout");
-
- result = mDevice->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mCopyVS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mCopyVS, "Renderer11 copy texture vertex shader");
-
- result = mDevice->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mCopyRGBAPS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mCopyRGBAPS, "Renderer11 copy texture RGBA pixel shader");
-
- result = mDevice->CreatePixelShader(g_PS_PassthroughRGB, sizeof(g_PS_PassthroughRGB), NULL, &mCopyRGBPS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mCopyRGBPS, "Renderer11 copy texture RGB pixel shader");
-
- result = mDevice->CreatePixelShader(g_PS_PassthroughLum, sizeof(g_PS_PassthroughLum), NULL, &mCopyLumPS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mCopyLumPS, "Renderer11 copy texture luminance pixel shader");
-
- result = mDevice->CreatePixelShader(g_PS_PassthroughLumAlpha, sizeof(g_PS_PassthroughLumAlpha), NULL, &mCopyLumAlphaPS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mCopyLumAlphaPS, "Renderer11 copy texture luminance alpha pixel shader");
-
- mCopyResourcesInitialized = true;
- }
-
- // Verify the source and destination area sizes
- if (sourceArea.x < 0 || sourceArea.x + sourceArea.width > static_cast<int>(sourceWidth) ||
- sourceArea.y < 0 || sourceArea.y + sourceArea.height > static_cast<int>(sourceHeight) ||
- destArea.x < 0 || destArea.x + destArea.width > static_cast<int>(destWidth) ||
- destArea.y < 0 || destArea.y + destArea.height > static_cast<int>(destHeight))
- {
- return gl::error(GL_INVALID_VALUE, false);
- }
-
- // Set vertices
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- result = mDeviceContext->Map(mCopyVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
- if (FAILED(result))
- {
- ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
-
- // Create a quad in homogeneous coordinates
- float x1 = (destArea.x / float(destWidth)) * 2.0f - 1.0f;
- float y1 = ((destHeight - destArea.y - destArea.height) / float(destHeight)) * 2.0f - 1.0f;
- float x2 = ((destArea.x + destArea.width) / float(destWidth)) * 2.0f - 1.0f;
- float y2 = ((destHeight - destArea.y) / float(destHeight)) * 2.0f - 1.0f;
-
- float u1 = sourceArea.x / float(sourceWidth);
- float v1 = sourceArea.y / float(sourceHeight);
- float u2 = (sourceArea.x + sourceArea.width) / float(sourceWidth);
- float v2 = (sourceArea.y + sourceArea.height) / float(sourceHeight);
-
- 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);
-
- mDeviceContext->Unmap(mCopyVB, 0);
-
- static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
- static UINT startIdx = 0;
- mDeviceContext->IASetVertexBuffers(0, 1, &mCopyVB, &stride, &startIdx);
-
- // Apply state
- mDeviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
- mDeviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
- mDeviceContext->RSSetState(NULL);
-
- // Apply shaders
- mDeviceContext->IASetInputLayout(mCopyIL);
- mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
- mDeviceContext->VSSetShader(mCopyVS, NULL, 0);
-
- ID3D11PixelShader *ps = NULL;
- switch(destFormat)
- {
- case GL_RGBA: ps = mCopyRGBAPS; break;
- case GL_RGB: ps = mCopyRGBPS; break;
- case GL_ALPHA: ps = mCopyRGBAPS; break;
- case GL_BGRA_EXT: ps = mCopyRGBAPS; break;
- case GL_LUMINANCE: ps = mCopyLumPS; break;
- case GL_LUMINANCE_ALPHA: ps = mCopyLumAlphaPS; break;
- default: UNREACHABLE(); ps = NULL; break;
- }
-
- mDeviceContext->PSSetShader(ps, NULL, 0);
- mDeviceContext->GSSetShader(NULL, NULL, 0);
-
- // Unset the currently bound shader resource to avoid conflicts
- static ID3D11ShaderResourceView *const nullSRV = NULL;
- mDeviceContext->PSSetShaderResources(0, 1, &nullSRV);
-
- // Apply render target
- setOneTimeRenderTarget(dest);
-
- // Set the viewport
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
- viewport.Width = destWidth;
- viewport.Height = destHeight;
- viewport.MinDepth = 0.0f;
- viewport.MaxDepth = 1.0f;
- mDeviceContext->RSSetViewports(1, &viewport);
-
- // Apply textures
- mDeviceContext->PSSetShaderResources(0, 1, &source);
- mDeviceContext->PSSetSamplers(0, 1, &mCopySampler);
-
- // Draw the quad
- mDeviceContext->Draw(4, 0);
-
- // Unbind textures and render targets and vertex buffer
- mDeviceContext->PSSetShaderResources(0, 1, &nullSRV);
-
- unapplyRenderTargets();
-
- UINT zero = 0;
- ID3D11Buffer *const nullBuffer = NULL;
- mDeviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
-
- markAllStateDirty();
-
- return true;
-}
-
-void Renderer11::unapplyRenderTargets()
-{
- setOneTimeRenderTarget(NULL);
-}
-
-void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView)
-{
- ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
-
- rtvArray[0] = renderTargetView;
-
- mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL);
-
- // Do not preserve the serial for this one-time-use render target
- for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
- {
- mAppliedRenderTargetSerials[rtIndex] = 0;
- }
-}
-
-RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
-{
- SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
- RenderTarget11 *renderTarget = NULL;
-
- if (depth)
- {
- // Note: depth stencil may be NULL for 0 sized surfaces
- renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(),
- swapChain11->getDepthStencilTexture(), NULL,
- swapChain11->getWidth(), swapChain11->getHeight());
- }
- else
- {
- // Note: render target may be NULL for 0 sized surfaces
- renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(),
- swapChain11->getOffscreenTexture(),
- swapChain11->getRenderTargetShaderResource(),
- swapChain11->getWidth(), swapChain11->getHeight());
- }
- return renderTarget;
-}
-
-RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
-{
- RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples, depth);
- return renderTarget;
-}
-
-ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type)
-{
- ShaderExecutable11 *executable = NULL;
-
- switch (type)
- {
- case rx::SHADER_VERTEX:
- {
- ID3D11VertexShader *vshader = NULL;
- HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader);
- ASSERT(SUCCEEDED(result));
-
- if (vshader)
- {
- executable = new ShaderExecutable11(function, length, vshader);
- }
- }
- break;
- case rx::SHADER_PIXEL:
- {
- ID3D11PixelShader *pshader = NULL;
- HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader);
- ASSERT(SUCCEEDED(result));
-
- if (pshader)
- {
- executable = new ShaderExecutable11(function, length, pshader);
- }
- }
- break;
- case rx::SHADER_GEOMETRY:
- {
- ID3D11GeometryShader *gshader = NULL;
- HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader);
- ASSERT(SUCCEEDED(result));
-
- if (gshader)
- {
- executable = new ShaderExecutable11(function, length, gshader);
- }
- }
- break;
- default:
- UNREACHABLE();
- break;
- }
-
- return executable;
-}
-
-ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround)
-{
- std::string profile;
-
- switch (type)
- {
- case rx::SHADER_VERTEX:
- profile = "vs_4_0";
- break;
- case rx::SHADER_PIXEL:
- profile = "ps_4_0";
- break;
- case rx::SHADER_GEOMETRY:
- profile = "gs_4_0";
- break;
- default:
- UNREACHABLE();
- return NULL;
- }
-
- if (mFeatureLevel == D3D_FEATURE_LEVEL_9_3)
- profile += "_level_9_3";
- else if (mFeatureLevel == D3D_FEATURE_LEVEL_9_2 || mFeatureLevel == D3D_FEATURE_LEVEL_9_1)
- profile += "_level_9_1";
-
- ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile.c_str(), D3DCOMPILE_OPTIMIZATION_LEVEL0, false);
- if (!binary)
- return NULL;
-
- ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type);
- binary->Release();
-
- return executable;
-}
-
-VertexBuffer *Renderer11::createVertexBuffer()
-{
- return new VertexBuffer11(this);
-}
-
-IndexBuffer *Renderer11::createIndexBuffer()
-{
- return new IndexBuffer11(this);
-}
-
-BufferStorage *Renderer11::createBufferStorage()
-{
- return new BufferStorage11(this);
-}
-
-QueryImpl *Renderer11::createQuery(GLenum type)
-{
- return new Query11(this, type);
-}
-
-FenceImpl *Renderer11::createFence()
-{
- return new Fence11(this);
-}
-
-bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource)
-{
- ASSERT(colorbuffer != NULL);
-
- RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
- if (renderTarget)
- {
- *subresourceIndex = renderTarget->getSubresourceIndex();
-
- ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView();
- if (colorBufferRTV)
- {
- ID3D11Resource *textureResource = NULL;
- colorBufferRTV->GetResource(&textureResource);
-
- if (textureResource)
- {
- HRESULT result = textureResource->QueryInterface(IID_ID3D11Texture2D, (void**)resource);
- textureResource->Release();
-
- if (SUCCEEDED(result))
- {
- return true;
- }
- else
- {
- ERR("Failed to extract the ID3D11Texture2D from the render target resource, "
- "HRESULT: 0x%X.", result);
- }
- }
- }
- }
-
- return false;
-}
-
-bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
- bool blitRenderTarget, bool blitDepthStencil)
-{
- if (blitRenderTarget)
- {
- gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer();
-
- if (!readBuffer)
- {
- ERR("Failed to retrieve the read buffer from the read framebuffer.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- RenderTarget *readRenderTarget = readBuffer->getRenderTarget();
-
- for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- if (drawTarget->isEnabledColorAttachment(colorAttachment))
- {
- gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment);
-
- if (!drawBuffer)
- {
- ERR("Failed to retrieve the draw buffer from the draw framebuffer.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget();
-
- if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false))
- {
- return false;
- }
- }
- }
- }
-
- if (blitDepthStencil)
- {
- gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer();
- gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer();
-
- if (!readBuffer)
- {
- ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- if (!drawBuffer)
- {
- ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- RenderTarget *readRenderTarget = readBuffer->getDepthStencil();
- RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil();
-
- if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true))
- {
- return false;
- }
- }
-
- return true;
-}
-
-void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
- GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
-{
- ID3D11Texture2D *colorBufferTexture = NULL;
- unsigned int subresourceIndex = 0;
-
- gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
-
- if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
- {
- gl::Rectangle area;
- area.x = x;
- area.y = y;
- area.width = width;
- area.height = height;
-
- readTextureData(colorBufferTexture, subresourceIndex, area, colorbuffer->getActualFormat(), format, type, outputPitch,
- packReverseRowOrder, packAlignment, pixels);
-
- colorBufferTexture->Release();
- colorBufferTexture = NULL;
- }
-}
-
-Image *Renderer11::createImage()
-{
- return new Image11();
-}
-
-void Renderer11::generateMipmap(Image *dest, Image *src)
-{
- Image11 *dest11 = Image11::makeImage11(dest);
- Image11 *src11 = Image11::makeImage11(src);
- Image11::generateMipmap(dest11, src11);
-}
-
-TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain)
-{
- SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
- return new TextureStorage11_2D(this, swapChain11);
-}
-
-TextureStorage *Renderer11::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
-{
- return new TextureStorage11_2D(this, levels, internalformat, usage, forceRenderable, width, height);
-}
-
-TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
-{
- return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size);
-}
-
-static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum sourceGLFormat, GLenum destFormat, GLenum destType)
-{
- if (sourceFormat == DXGI_FORMAT_A8_UNORM &&
- destFormat == GL_ALPHA &&
- destType == GL_UNSIGNED_BYTE)
- {
- return 1;
- }
- else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM &&
- sourceGLFormat == GL_RGBA8_OES &&
- destFormat == GL_RGBA &&
- destType == GL_UNSIGNED_BYTE)
- {
- return 4;
- }
- else if (sourceFormat == DXGI_FORMAT_B8G8R8A8_UNORM &&
- destFormat == GL_BGRA_EXT &&
- destType == GL_UNSIGNED_BYTE)
- {
- return 4;
- }
- else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT &&
- sourceGLFormat == GL_RGBA16F_EXT &&
- destFormat == GL_RGBA &&
- destType == GL_HALF_FLOAT_OES)
- {
- return 8;
- }
- else if (sourceFormat == DXGI_FORMAT_R32G32B32_FLOAT &&
- destFormat == GL_RGB &&
- destType == GL_FLOAT)
- {
- return 12;
- }
- else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT &&
- sourceGLFormat == GL_RGBA32F_EXT &&
- destFormat == GL_RGBA &&
- destType == GL_FLOAT)
- {
- return 16;
- }
- else
- {
- return 0;
- }
-}
-
-static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, GLenum glFormat, unsigned int x,
- unsigned int y, int inputPitch, gl::Color *outColor)
-{
- switch (format)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- unsigned int rgba = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch);
- outColor->red = (rgba & 0x000000FF) * (1.0f / 0x000000FF);
- outColor->green = (rgba & 0x0000FF00) * (1.0f / 0x0000FF00);
- outColor->blue = (rgba & 0x00FF0000) * (1.0f / 0x00FF0000);
-
- if (gl::GetAlphaSize(glFormat) > 0)
- {
- outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000);
- }
- else
- {
- outColor->alpha = 1.0f;
- }
- }
- break;
-
- case DXGI_FORMAT_A8_UNORM:
- {
- outColor->red = 0.0f;
- outColor->green = 0.0f;
- outColor->blue = 0.0f;
- outColor->alpha = *(data + x + y * inputPitch) / 255.0f;
- }
- break;
-
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- {
- outColor->red = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 0);
- outColor->green = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 1);
- outColor->blue = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 2);
-
- if (gl::GetAlphaSize(glFormat) > 0)
- {
- outColor->alpha = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 3);
- }
- else
- {
- outColor->alpha = 1.0f;
- }
- }
- break;
-
- case DXGI_FORMAT_R32G32B32_FLOAT:
- {
- outColor->red = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 0);
- outColor->green = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 1);
- outColor->blue = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 2);
- outColor->alpha = 1.0f;
- }
- break;
-
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- {
- outColor->red = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 0));
- outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 1));
- outColor->blue = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 2));
-
- if (gl::GetAlphaSize(glFormat) > 0)
- {
- outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 3));
- }
- else
- {
- outColor->alpha = 1.0f;
- }
- }
- break;
-
- case DXGI_FORMAT_B8G8R8A8_UNORM:
- {
- unsigned int bgra = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch);
- outColor->red = (bgra & 0x00FF0000) * (1.0f / 0x00FF0000);
- outColor->blue = (bgra & 0x000000FF) * (1.0f / 0x000000FF);
- outColor->green = (bgra & 0x0000FF00) * (1.0f / 0x0000FF00);
- outColor->alpha = (bgra & 0xFF000000) * (1.0f / 0xFF000000);
- }
- break;
-
- case DXGI_FORMAT_R8_UNORM:
- {
- outColor->red = *(data + x + y * inputPitch) / 255.0f;
- outColor->green = 0.0f;
- outColor->blue = 0.0f;
- outColor->alpha = 1.0f;
- }
- break;
-
- case DXGI_FORMAT_R8G8_UNORM:
- {
- unsigned short rg = *reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch);
-
- outColor->red = (rg & 0xFF00) * (1.0f / 0xFF00);
- outColor->green = (rg & 0x00FF) * (1.0f / 0x00FF);
- outColor->blue = 0.0f;
- outColor->alpha = 1.0f;
- }
- break;
-
- case DXGI_FORMAT_R16_FLOAT:
- {
- outColor->red = gl::float16ToFloat32(*reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch));
- outColor->green = 0.0f;
- outColor->blue = 0.0f;
- outColor->alpha = 1.0f;
- }
- break;
-
- case DXGI_FORMAT_R16G16_FLOAT:
- {
- outColor->red = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 0));
- outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 1));
- outColor->blue = 0.0f;
- outColor->alpha = 1.0f;
- }
- break;
-
- default:
- ERR("ReadPixelColor not implemented for DXGI format %u.", format);
- UNIMPLEMENTED();
- break;
- }
-}
-
-static inline void writePixelColor(const gl::Color &color, GLenum format, GLenum type, unsigned int x,
- unsigned int y, int outputPitch, void *outData)
-{
- unsigned char* byteData = reinterpret_cast<unsigned char*>(outData);
- unsigned short* shortData = reinterpret_cast<unsigned short*>(outData);
-
- switch (format)
- {
- case GL_RGBA:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red + 0.5f);
- byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
- byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue + 0.5f);
- byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f);
- break;
-
- default:
- ERR("WritePixelColor not implemented for format GL_RGBA and type 0x%X.", type);
- UNIMPLEMENTED();
- break;
- }
- break;
-
- case GL_BGRA_EXT:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.blue + 0.5f);
- byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
- byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.red + 0.5f);
- byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f);
- break;
-
- case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
- // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
- // this type is packed as follows:
- // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------
- // | 4th | 3rd | 2nd | 1st component |
- // --------------------------------------------------------------------------------
- // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
- shortData[x + y * outputPitch / sizeof(unsigned short)] =
- (static_cast<unsigned short>(15 * color.alpha + 0.5f) << 12) |
- (static_cast<unsigned short>(15 * color.red + 0.5f) << 8) |
- (static_cast<unsigned short>(15 * color.green + 0.5f) << 4) |
- (static_cast<unsigned short>(15 * color.blue + 0.5f) << 0);
- break;
-
- case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
- // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
- // this type is packed as follows:
- // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------
- // | 4th | 3rd | 2nd | 1st component |
- // --------------------------------------------------------------------------------
- // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
- shortData[x + y * outputPitch / sizeof(unsigned short)] =
- (static_cast<unsigned short>( color.alpha + 0.5f) << 15) |
- (static_cast<unsigned short>(31 * color.red + 0.5f) << 10) |
- (static_cast<unsigned short>(31 * color.green + 0.5f) << 5) |
- (static_cast<unsigned short>(31 * color.blue + 0.5f) << 0);
- break;
-
- default:
- ERR("WritePixelColor not implemented for format GL_BGRA_EXT and type 0x%X.", type);
- UNIMPLEMENTED();
- break;
- }
- break;
-
- case GL_RGB:
- switch (type)
- {
- case GL_UNSIGNED_SHORT_5_6_5:
- shortData[x + y * outputPitch / sizeof(unsigned short)] =
- (static_cast<unsigned short>(31 * color.blue + 0.5f) << 0) |
- (static_cast<unsigned short>(63 * color.green + 0.5f) << 5) |
- (static_cast<unsigned short>(31 * color.red + 0.5f) << 11);
- break;
-
- case GL_UNSIGNED_BYTE:
- byteData[3 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red + 0.5f);
- byteData[3 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
- byteData[3 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue + 0.5f);
- break;
-
- default:
- ERR("WritePixelColor not implemented for format GL_RGB and type 0x%X.", type);
- UNIMPLEMENTED();
- break;
- }
- break;
-
- default:
- ERR("WritePixelColor not implemented for format 0x%X.", format);
- UNIMPLEMENTED();
- break;
- }
-}
-
-void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area,
- GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder,
- GLint packAlignment, void *pixels)
-{
- D3D11_TEXTURE2D_DESC textureDesc;
- texture->GetDesc(&textureDesc);
-
- D3D11_TEXTURE2D_DESC stagingDesc;
- stagingDesc.Width = area.width;
- stagingDesc.Height = area.height;
- stagingDesc.MipLevels = 1;
- stagingDesc.ArraySize = 1;
- stagingDesc.Format = textureDesc.Format;
- 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;
-
- ID3D11Texture2D* stagingTex = NULL;
- HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex);
- if (FAILED(result))
- {
- ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result);
- return;
- }
-
- ID3D11Texture2D* srcTex = NULL;
- if (textureDesc.SampleDesc.Count > 1)
- {
- D3D11_TEXTURE2D_DESC resolveDesc;
- resolveDesc.Width = textureDesc.Width;
- resolveDesc.Height = textureDesc.Height;
- resolveDesc.MipLevels = 1;
- resolveDesc.ArraySize = 1;
- resolveDesc.Format = textureDesc.Format;
- resolveDesc.SampleDesc.Count = 1;
- resolveDesc.SampleDesc.Quality = 0;
- resolveDesc.Usage = D3D11_USAGE_DEFAULT;
- resolveDesc.BindFlags = 0;
- resolveDesc.CPUAccessFlags = 0;
- resolveDesc.MiscFlags = 0;
-
- result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex);
- if (FAILED(result))
- {
- ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result);
- stagingTex->Release();
- return;
- }
-
- mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format);
- subResource = 0;
- }
- else
- {
- srcTex = texture;
- srcTex->AddRef();
- }
-
- D3D11_BOX srcBox;
- srcBox.left = area.x;
- srcBox.right = area.x + area.width;
- srcBox.top = area.y;
- srcBox.bottom = area.y + area.height;
- srcBox.front = 0;
- srcBox.back = 1;
-
- mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox);
-
- srcTex->Release();
- srcTex = NULL;
-
- D3D11_MAPPED_SUBRESOURCE mapping;
- mDeviceContext->Map(stagingTex, 0, D3D11_MAP_READ, 0, &mapping);
-
- unsigned char *source;
- int inputPitch;
- if (packReverseRowOrder)
- {
- source = static_cast<unsigned char*>(mapping.pData) + mapping.RowPitch * (area.height - 1);
- inputPitch = -static_cast<int>(mapping.RowPitch);
- }
- else
- {
- source = static_cast<unsigned char*>(mapping.pData);
- inputPitch = static_cast<int>(mapping.RowPitch);
- }
-
- unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, sourceFormat, format, type);
- if (fastPixelSize != 0)
- {
- unsigned char *dest = static_cast<unsigned char*>(pixels);
- for (int j = 0; j < area.height; j++)
- {
- memcpy(dest + j * outputPitch, source + j * inputPitch, area.width * fastPixelSize);
- }
- }
- else if (textureDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM &&
- format == GL_RGBA &&
- type == GL_UNSIGNED_BYTE)
- {
- // Fast path for swapping red with blue
- unsigned char *dest = static_cast<unsigned char*>(pixels);
-
- for (int j = 0; j < area.height; j++)
- {
- for (int i = 0; i < area.width; i++)
- {
- unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
- *(unsigned int*)(dest + 4 * i + j * outputPitch) =
- (argb & 0xFF00FF00) | // Keep alpha and green
- (argb & 0x00FF0000) >> 16 | // Move red to blue
- (argb & 0x000000FF) << 16; // Move blue to red
- }
- }
- }
- else
- {
- gl::Color pixelColor;
- for (int j = 0; j < area.height; j++)
- {
- for (int i = 0; i < area.width; i++)
- {
- readPixelColor(source, textureDesc.Format, sourceFormat, i, j, inputPitch, &pixelColor);
- writePixelColor(pixelColor, format, type, i, j, outputPitch, pixels);
- }
- }
- }
-
- mDeviceContext->Unmap(stagingTex, 0);
-
- stagingTex->Release();
- stagingTex = NULL;
-}
-
-bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
- RenderTarget *drawRenderTarget, bool wholeBufferCopy)
-{
- ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height);
-
- RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget);
- if (!drawRenderTarget)
- {
- ERR("Failed to retrieve the draw render target from the draw framebuffer.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture();
- unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
-
- RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget);
- if (!readRenderTarget)
- {
- ERR("Failed to retrieve the read render target from the read framebuffer.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- ID3D11Texture2D *readTexture = NULL;
- unsigned int readSubresource = 0;
- if (readRenderTarget->getSamples() > 0)
- {
- readTexture = resolveMultisampledTexture(readRenderTarget11->getTexture(), readRenderTarget11->getSubresourceIndex());
- readSubresource = 0;
- }
- else
- {
- readTexture = readRenderTarget11->getTexture();
- readTexture->AddRef();
- readSubresource = readRenderTarget11->getSubresourceIndex();
- }
-
- if (!readTexture)
- {
- ERR("Failed to retrieve the read render target view from the read render target.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- 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;
-
- // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
- // We also require complete framebuffer copies for depth-stencil blit.
- D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox;
-
- mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0,
- readTexture, readSubresource, pSrcBox);
-
- SafeRelease(readTexture);
-
- return true;
-}
-
-ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource)
-{
- D3D11_TEXTURE2D_DESC textureDesc;
- source->GetDesc(&textureDesc);
-
- if (textureDesc.SampleDesc.Count > 1)
- {
- D3D11_TEXTURE2D_DESC resolveDesc;
- resolveDesc.Width = textureDesc.Width;
- resolveDesc.Height = textureDesc.Height;
- resolveDesc.MipLevels = 1;
- resolveDesc.ArraySize = 1;
- resolveDesc.Format = textureDesc.Format;
- resolveDesc.SampleDesc.Count = 1;
- resolveDesc.SampleDesc.Quality = 0;
- resolveDesc.Usage = textureDesc.Usage;
- resolveDesc.BindFlags = textureDesc.BindFlags;
- resolveDesc.CPUAccessFlags = 0;
- resolveDesc.MiscFlags = 0;
-
- ID3D11Texture2D *resolveTexture = NULL;
- HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture);
- if (FAILED(result))
- {
- ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result);
- return NULL;
- }
-
- mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format);
- return resolveTexture;
- }
- else
- {
- source->AddRef();
- return source;
- }
-}
-
-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;
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h
deleted file mode 100644
index 773fc26db1..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h
+++ /dev/null
@@ -1,373 +0,0 @@
-//
-// 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.
-//
-
-// Renderer11.h: Defines a back-end specific class for the D3D11 renderer.
-
-#ifndef LIBGLESV2_RENDERER_RENDERER11_H_
-#define LIBGLESV2_RENDERER_RENDERER11_H_
-
-#include "common/angleutils.h"
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/mathutil.h"
-
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/d3d11/RenderStateCache.h"
-#include "libGLESv2/renderer/d3d11/InputLayoutCache.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-
-#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
-struct IInspectable;
-namespace ABI {
- namespace Windows {
- namespace ApplicationModel {
- struct ISuspendingEventArgs;
- }
- }
-}
-#endif
-
-namespace gl
-{
-class Renderbuffer;
-}
-
-namespace rx
-{
-
-class VertexDataManager;
-class IndexDataManager;
-class StreamingIndexBufferInterface;
-
-enum
-{
- MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024,
- MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024
-};
-
-class Renderer11 : public Renderer
-{
- public:
- Renderer11(egl::Display *display);
- virtual ~Renderer11();
-
- static Renderer11 *makeRenderer11(Renderer *renderer);
-
- virtual EGLint initialize();
- virtual bool resetDevice();
-
- virtual int generateConfigs(ConfigDesc **configDescList);
- virtual void deleteConfigs(ConfigDesc *configDescList);
-
- virtual void sync(bool block);
-
- virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
-
- virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
- virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture);
-
- virtual void setRasterizerState(const gl::RasterizerState &rasterState);
- virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor,
- unsigned int sampleMask);
- virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
- int stencilBackRef, bool frontFaceCCW);
-
- virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
- virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
- bool ignoreViewport);
-
- virtual bool applyPrimitiveType(GLenum mode, GLsizei count);
- virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
- virtual void applyShaders(gl::ProgramBinary *programBinary);
- virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray);
- virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances);
- virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
-
- virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances);
- virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
-
- virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
-
- virtual void markAllStateDirty();
-
- // lost device
- void notifyDeviceLost();
- virtual bool isDeviceLost();
- virtual bool testDeviceLost(bool notify);
- virtual bool testDeviceResettable();
-
- // Renderer capabilities
- virtual DWORD getAdapterVendor() const;
- virtual std::string getRendererDescription() const;
- virtual GUID getAdapterIdentifier() const;
-
- virtual bool getBGRATextureSupport() const;
- virtual bool getDXT1TextureSupport();
- virtual bool getDXT3TextureSupport();
- virtual bool getDXT5TextureSupport();
- virtual bool getEventQuerySupport();
- virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable);
- virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable);
- virtual bool getLuminanceTextureSupport();
- virtual bool getLuminanceAlphaTextureSupport();
- virtual unsigned int getMaxVertexTextureImageUnits() const;
- virtual unsigned int getMaxCombinedTextureImageUnits() const;
- virtual unsigned int getReservedVertexUniformVectors() const;
- virtual unsigned int getReservedFragmentUniformVectors() const;
- virtual unsigned int getMaxVertexUniformVectors() const;
- virtual unsigned int getMaxFragmentUniformVectors() const;
- virtual unsigned int getMaxVaryingVectors() const;
- virtual bool getNonPower2TextureSupport() const;
- virtual bool getDepthTextureSupport() const;
- virtual bool getOcclusionQuerySupport() const;
- virtual bool getInstancingSupport() const;
- virtual bool getTextureFilterAnisotropySupport() const;
- virtual float getTextureMaxAnisotropy() const;
- virtual bool getShareHandleSupport() const;
- virtual bool getDerivativeInstructionSupport() const;
- virtual bool getPostSubBufferSupport() const;
-
- virtual int getMajorShaderModel() const;
- virtual float getMaxPointSize() const;
- virtual int getMaxViewportDimension() const;
- virtual int getMaxTextureWidth() const;
- virtual int getMaxTextureHeight() const;
- virtual bool get32BitIndexSupport() const;
- virtual int getMinSwapInterval() const;
- virtual int getMaxSwapInterval() const;
-
- virtual GLsizei getMaxSupportedSamples() const;
- int getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const;
-
- virtual unsigned int getMaxRenderTargets() const;
-
- // Pixel operations
- virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source);
- virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source);
-
- virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level);
- virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level);
-
- bool copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight,
- ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat);
-
- virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
- bool blitRenderTarget, bool blitDepthStencil);
- virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
- GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels);
-
- // RenderTarget creation
- virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth);
- virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth);
-
- // Shader operations
- virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type);
- virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround);
-
- // Image operations
- virtual Image *createImage();
- virtual void generateMipmap(Image *dest, Image *source);
- virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
- virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
- virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
-
- // Buffer creation
- virtual VertexBuffer *createVertexBuffer();
- virtual IndexBuffer *createIndexBuffer();
- virtual BufferStorage *createBufferStorage();
-
- // Query and Fence creation
- virtual QueryImpl *createQuery(GLenum type);
- virtual FenceImpl *createFence();
-
- // D3D11-renderer specific methods
- ID3D11Device *getDevice() { return mDevice; }
- ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
- IDXGIFactory *getDxgiFactory() { return mDxgiFactory; };
- D3D_FEATURE_LEVEL getFeatureLevel() { return mFeatureLevel; }
-
- bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource);
- void unapplyRenderTargets();
- void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView);
-
- virtual bool getLUID(LUID *adapterLuid) const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Renderer11);
-
- void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
- void drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances);
-
- void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area,
- GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder,
- GLint packAlignment, void *pixels);
-
- void maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
- rx::Range getViewportBounds() const;
-
- bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
- RenderTarget *drawRenderTarget, bool wholeBufferCopy);
- ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
-
-#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
- HRESULT onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *);
-#endif
-
- HMODULE mD3d11Module;
- HMODULE mDxgiModule;
-
- bool mDeviceLost;
-
- void initializeDevice();
- void releaseDeviceResources();
- int getMinorShaderModel() const;
- void release();
-
- RenderStateCache mStateCache;
-
- // Support flags
- bool mFloat16TextureSupport;
- bool mFloat16FilterSupport;
- bool mFloat16RenderSupport;
-
- bool mFloat32TextureSupport;
- bool mFloat32FilterSupport;
- bool mFloat32RenderSupport;
-
- bool mDXT1TextureSupport;
- bool mDXT3TextureSupport;
- bool mDXT5TextureSupport;
-
- bool mDepthTextureSupport;
-
- // Multisample format support
- struct MultisampleSupportInfo
- {
- unsigned int qualityLevels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT];
- };
-
- typedef std::unordered_map<DXGI_FORMAT, MultisampleSupportInfo, std::hash<int> > MultisampleSupportMap;
- MultisampleSupportMap mMultisampleSupportMap;
-
- unsigned int mMaxSupportedSamples;
-
- // current render target states
- unsigned int mAppliedRenderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
- unsigned int mAppliedDepthbufferSerial;
- unsigned int mAppliedStencilbufferSerial;
- bool mDepthStencilInitialized;
- bool mRenderTargetDescInitialized;
- rx::RenderTarget::Desc mRenderTargetDesc;
- unsigned int mCurDepthSize;
- unsigned int mCurStencilSize;
-
- // Currently applied sampler states
- bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
- gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-
- bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS];
- gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS];
-
- // Currently applied textures
- unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
- unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS];
-
- // Currently applied blend state
- bool mForceSetBlendState;
- gl::BlendState mCurBlendState;
- gl::Color mCurBlendColor;
- unsigned int mCurSampleMask;
-
- // Currently applied rasterizer state
- bool mForceSetRasterState;
- gl::RasterizerState mCurRasterState;
-
- // Currently applied depth stencil state
- bool mForceSetDepthStencilState;
- gl::DepthStencilState mCurDepthStencilState;
- int mCurStencilRef;
- int mCurStencilBackRef;
-
- // Currently applied scissor rectangle
- bool mForceSetScissor;
- bool mScissorEnabled;
- gl::Rectangle mCurScissor;
-
- // Currently applied viewport
- bool mForceSetViewport;
- gl::Rectangle mCurViewport;
- float mCurNear;
- float mCurFar;
-
- // Currently applied primitive topology
- D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology;
-
- unsigned int mAppliedIBSerial;
- unsigned int mAppliedStorageIBSerial;
- unsigned int mAppliedIBOffset;
-
- unsigned int mAppliedProgramBinarySerial;
- bool mIsGeometryShaderActive;
-
- dx_VertexConstants mVertexConstants;
- dx_VertexConstants mAppliedVertexConstants;
- ID3D11Buffer *mDriverConstantBufferVS;
- ID3D11Buffer *mCurrentVertexConstantBuffer;
-
- dx_PixelConstants mPixelConstants;
- dx_PixelConstants mAppliedPixelConstants;
- ID3D11Buffer *mDriverConstantBufferPS;
- ID3D11Buffer *mCurrentPixelConstantBuffer;
-
- ID3D11Buffer *mCurrentGeometryConstantBuffer;
-
- // Vertex, index and input layouts
- VertexDataManager *mVertexDataManager;
- IndexDataManager *mIndexDataManager;
- InputLayoutCache mInputLayoutCache;
-
- StreamingIndexBufferInterface *mLineLoopIB;
- StreamingIndexBufferInterface *mTriangleFanIB;
-
- // Texture copy resources
- bool mCopyResourcesInitialized;
- ID3D11Buffer *mCopyVB;
- ID3D11SamplerState *mCopySampler;
- ID3D11InputLayout *mCopyIL;
- ID3D11VertexShader *mCopyVS;
- ID3D11PixelShader *mCopyRGBAPS;
- ID3D11PixelShader *mCopyRGBPS;
- ID3D11PixelShader *mCopyLumPS;
- ID3D11PixelShader *mCopyLumAlphaPS;
-
- // Masked clear resources
- bool mClearResourcesInitialized;
- ID3D11Buffer *mClearVB;
- ID3D11InputLayout *mClearIL;
- ID3D11VertexShader *mClearVS;
- ID3D11PixelShader *mClearSinglePS;
- ID3D11PixelShader *mClearMultiplePS;
- ID3D11RasterizerState *mClearScissorRS;
- ID3D11RasterizerState *mClearNoScissorRS;
-
- // Sync query
- ID3D11Query *mSyncQuery;
-
- ID3D11Device *mDevice;
- D3D_FEATURE_LEVEL mFeatureLevel;
- ID3D11DeviceContext *mDeviceContext;
- IDXGIAdapter *mDxgiAdapter;
- DXGI_ADAPTER_DESC mAdapterDescription;
- char mDescription[128];
- IDXGIFactory *mDxgiFactory;
-
- // Cached device caps
- bool mBGRATextureSupport;
-};
-
-}
-#endif // LIBGLESV2_RENDERER_RENDERER11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp
deleted file mode 100644
index 0c981ac503..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp
+++ /dev/null
@@ -1,667 +0,0 @@
-#include "precompiled.h"
-//
-// 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.
-//
-
-// 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 "libGLESv2/renderer/d3d11/TextureStorage11.h"
-
-#include "libGLESv2/renderer/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d11/RenderTarget11.h"
-#include "libGLESv2/renderer/d3d11/SwapChain11.h"
-#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
-
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/main.h"
-
-namespace rx
-{
-
-TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
- : mBindFlags(bindFlags),
- mLodOffset(0),
- mMipLevels(0),
- mTexture(NULL),
- mTextureFormat(DXGI_FORMAT_UNKNOWN),
- mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
- mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
- mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
- mSRV(NULL),
- mTextureWidth(0),
- mTextureHeight(0)
-{
- mRenderer = Renderer11::makeRenderer11(renderer);
-}
-
-TextureStorage11::~TextureStorage11()
-{
-}
-
-TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
-{
- ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
- return static_cast<TextureStorage11*>(storage);
-}
-
-DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable)
-{
- UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
-
- if (d3d11::IsDepthStencilFormat(format))
- {
- bindFlags |= D3D11_BIND_DEPTH_STENCIL;
- }
- else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
- {
- bindFlags |= D3D11_BIND_RENDER_TARGET;
- }
- return bindFlags;
-}
-
-bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format)
-{
- switch(format)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- case DXGI_FORMAT_A8_UNORM:
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- case DXGI_FORMAT_B8G8R8A8_UNORM:
- case DXGI_FORMAT_R8_UNORM:
- case DXGI_FORMAT_R8G8_UNORM:
- case DXGI_FORMAT_R16_FLOAT:
- case DXGI_FORMAT_R16G16_FLOAT:
- return true;
- case DXGI_FORMAT_BC1_UNORM:
- case DXGI_FORMAT_BC2_UNORM:
- case DXGI_FORMAT_BC3_UNORM:
- case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices
- return false;
- default:
- UNREACHABLE();
- return false;
- }
-}
-
-UINT TextureStorage11::getBindFlags() const
-{
- return mBindFlags;
-}
-
-ID3D11Texture2D *TextureStorage11::getBaseTexture() const
-{
- return mTexture;
-}
-
-int TextureStorage11::getLodOffset() const
-{
- return mLodOffset;
-}
-
-bool TextureStorage11::isRenderTarget() const
-{
- return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
-}
-
-bool TextureStorage11::isManaged() const
-{
- return false;
-}
-
-int TextureStorage11::levelCount()
-{
- int levels = 0;
- if (getBaseTexture())
- {
- levels = mMipLevels - getLodOffset();
- }
- return levels;
-}
-
-UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex)
-{
- UINT index = 0;
- if (getBaseTexture())
- {
- index = D3D11CalcSubresource(level, faceIndex, mMipLevels);
- }
- return index;
-}
-
-bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource,
- int level, int face, GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height)
-{
- if (srcTexture)
- {
- // Round up the width and height to the nearest multiple of dimension alignment
- unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat);
- width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment;
- height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment;
-
- D3D11_BOX srcBox;
- srcBox.left = xoffset;
- srcBox.top = yoffset;
- srcBox.right = xoffset + width;
- srcBox.bottom = yoffset + height;
- srcBox.front = 0;
- srcBox.back = 1;
-
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-
- ASSERT(getBaseTexture());
- context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face),
- xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox);
- return true;
- }
-
- return false;
-}
-
-void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
-{
- if (source && dest)
- {
- ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
- ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
-
- if (sourceSRV && destRTV)
- {
- gl::Rectangle sourceArea;
- sourceArea.x = 0;
- sourceArea.y = 0;
- sourceArea.width = source->getWidth();
- sourceArea.height = source->getHeight();
-
- gl::Rectangle destArea;
- destArea.x = 0;
- destArea.y = 0;
- destArea.width = dest->getWidth();
- destArea.height = dest->getHeight();
-
- mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(),
- destRTV, destArea, dest->getWidth(), dest->getHeight(),
- GL_RGBA);
- }
- }
-}
-
-TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
- : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
-{
- mTexture = swapchain->getOffscreenTexture();
- mSRV = swapchain->getRenderTargetShaderResource();
-
- for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
- {
- mRenderTarget[i] = NULL;
- }
-
- D3D11_TEXTURE2D_DESC texDesc;
- mTexture->GetDesc(&texDesc);
- mMipLevels = texDesc.MipLevels;
- mTextureFormat = texDesc.Format;
- mTextureWidth = texDesc.Width;
- mTextureHeight = texDesc.Height;
-
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- mSRV->GetDesc(&srvDesc);
- mShaderResourceFormat = srvDesc.Format;
-
- ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- offscreenRTV->GetDesc(&rtvDesc);
- mRenderTargetFormat = rtvDesc.Format;
- offscreenRTV->Release();
-
- mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
-}
-
-TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
- : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable))
-{
- for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
- {
- mRenderTarget[i] = NULL;
- }
-
- DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel());
- if (d3d11::IsDepthStencilFormat(convertedFormat))
- {
- mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
- mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
- mDepthStencilFormat = convertedFormat;
- mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
- }
- else
- {
- mTextureFormat = convertedFormat;
- mShaderResourceFormat = convertedFormat;
- mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
- mRenderTargetFormat = convertedFormat;
- }
-
- // 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 (width > 0 && height > 0)
- {
- // adjust size if needed for compressed textures
- gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
-
- ID3D11Device *device = mRenderer->getDevice();
-
- D3D11_TEXTURE2D_DESC desc;
- desc.Width = width; // Compressed texture size constraints?
- desc.Height = height;
- desc.MipLevels = mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 ? ((levels > 0) ? levels + mLodOffset : 0) : 1;
- desc.ArraySize = 1;
- desc.Format = mTextureFormat;
- desc.SampleDesc.Count = 1;
- desc.SampleDesc.Quality = 0;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = getBindFlags();
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = 0;
-
- HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
-
- // this can happen from windows TDR
- if (d3d11::isDeviceLostError(result))
- {
- mRenderer->notifyDeviceLost();
- gl::error(GL_OUT_OF_MEMORY);
- }
- else if (FAILED(result))
- {
- ASSERT(result == E_OUTOFMEMORY);
- ERR("Creating image failed.");
- gl::error(GL_OUT_OF_MEMORY);
- }
- else
- {
- mTexture->GetDesc(&desc);
- mMipLevels = desc.MipLevels;
- mTextureWidth = desc.Width;
- mTextureHeight = desc.Height;
- }
- }
-}
-
-TextureStorage11_2D::~TextureStorage11_2D()
-{
- if (mTexture)
- {
- mTexture->Release();
- mTexture = NULL;
- }
-
- if (mSRV)
- {
- mSRV->Release();
- mSRV = NULL;
- }
-
- for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
- {
- delete mRenderTarget[i];
- mRenderTarget[i] = NULL;
- }
-}
-
-TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
-{
- ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
- return static_cast<TextureStorage11_2D*>(storage);
-}
-
-RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
-{
- if (level >= 0 && level < static_cast<int>(mMipLevels))
- {
- if (!mRenderTarget[level])
- {
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result;
-
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srvDesc.Format = mShaderResourceFormat;
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- srvDesc.Texture2D.MostDetailedMip = level;
- srvDesc.Texture2D.MipLevels = level ? 1 : -1;
-
- ID3D11ShaderResourceView *srv;
- result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
-
- if (result == E_OUTOFMEMORY)
- {
- return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
- }
- ASSERT(SUCCEEDED(result));
-
- if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
- {
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
- rtvDesc.Texture2D.MipSlice = level;
-
- ID3D11RenderTargetView *rtv;
- result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
-
- if (result == E_OUTOFMEMORY)
- {
- srv->Release();
- return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
- }
- ASSERT(SUCCEEDED(result));
-
- // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
- // also needs to keep a reference to the texture.
- mTexture->AddRef();
-
- mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
- std::max(mTextureWidth >> level, 1U),
- std::max(mTextureHeight >> level, 1U));
- }
- else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
- {
- D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
- dsvDesc.Format = mDepthStencilFormat;
- dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
- dsvDesc.Texture2D.MipSlice = level;
- dsvDesc.Flags = 0;
-
- ID3D11DepthStencilView *dsv;
- result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
-
- if (result == E_OUTOFMEMORY)
- {
- srv->Release();
- return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
- }
- ASSERT(SUCCEEDED(result));
-
- // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
- // also needs to keep a reference to the texture.
- mTexture->AddRef();
-
- mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
- std::max(mTextureWidth >> level, 1U),
- std::max(mTextureHeight >> level, 1U));
- }
- else
- {
- UNREACHABLE();
- }
- }
-
- return mRenderTarget[level];
- }
- else
- {
- return NULL;
- }
-}
-
-ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
-{
- if (!mSRV)
- {
- ID3D11Device *device = mRenderer->getDevice();
-
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srvDesc.Format = mShaderResourceFormat;
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
- srvDesc.Texture2D.MostDetailedMip = 0;
-
- HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
-
- if (result == E_OUTOFMEMORY)
- {
- return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
- }
- ASSERT(SUCCEEDED(result));
- }
-
- return mSRV;
-}
-
-void TextureStorage11_2D::generateMipmap(int level)
-{
- RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
- RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
-
- generateMipmapLayer(source, dest);
-}
-
-TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
- : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable))
-{
- for (unsigned int i = 0; i < 6; i++)
- {
- for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
- {
- mRenderTarget[i][j] = NULL;
- }
- }
-
- DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel());
- if (d3d11::IsDepthStencilFormat(convertedFormat))
- {
- mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
- mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
- mDepthStencilFormat = convertedFormat;
- mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
- }
- else
- {
- mTextureFormat = convertedFormat;
- mShaderResourceFormat = convertedFormat;
- mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
- mRenderTargetFormat = convertedFormat;
- }
-
- // 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 (size > 0)
- {
- // adjust size if needed for compressed textures
- int height = size;
- gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
-
- ID3D11Device *device = mRenderer->getDevice();
-
- D3D11_TEXTURE2D_DESC desc;
- desc.Width = size;
- desc.Height = size;
- desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
- desc.ArraySize = 6;
- desc.Format = mTextureFormat;
- 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;
-
- HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
-
- if (FAILED(result))
- {
- ASSERT(result == E_OUTOFMEMORY);
- ERR("Creating image failed.");
- gl::error(GL_OUT_OF_MEMORY);
- }
- else
- {
- mTexture->GetDesc(&desc);
- mMipLevels = desc.MipLevels;
- mTextureWidth = desc.Width;
- mTextureHeight = desc.Height;
- }
- }
-}
-
-TextureStorage11_Cube::~TextureStorage11_Cube()
-{
- if (mTexture)
- {
- mTexture->Release();
- mTexture = NULL;
- }
-
- if (mSRV)
- {
- mSRV->Release();
- mSRV = NULL;
- }
-
- for (unsigned int i = 0; i < 6; i++)
- {
- for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
- {
- delete mRenderTarget[i][j];
- mRenderTarget[i][j] = NULL;
- }
- }
-}
-
-TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
-{
- ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
- return static_cast<TextureStorage11_Cube*>(storage);
-}
-
-RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
-{
- unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
- if (level >= 0 && level < static_cast<int>(mMipLevels))
- {
- if (!mRenderTarget[faceIdx][level])
- {
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result;
-
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srvDesc.Format = mShaderResourceFormat;
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube
- srvDesc.Texture2DArray.MostDetailedMip = level;
- srvDesc.Texture2DArray.MipLevels = 1;
- srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
- srvDesc.Texture2DArray.ArraySize = 1;
-
- ID3D11ShaderResourceView *srv;
- result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
-
- if (result == E_OUTOFMEMORY)
- {
- return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
- }
- ASSERT(SUCCEEDED(result));
-
- if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
- {
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
- rtvDesc.Texture2DArray.MipSlice = level;
- rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
- rtvDesc.Texture2DArray.ArraySize = 1;
-
- ID3D11RenderTargetView *rtv;
- result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
-
- if (result == E_OUTOFMEMORY)
- {
- srv->Release();
- return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
- }
- ASSERT(SUCCEEDED(result));
-
- // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
- // also needs to keep a reference to the texture.
- mTexture->AddRef();
-
- mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
- std::max(mTextureWidth >> level, 1U),
- std::max(mTextureHeight >> level, 1U));
- }
- else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
- {
- D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
- dsvDesc.Format = mRenderTargetFormat;
- dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
- dsvDesc.Texture2DArray.MipSlice = level;
- dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
- dsvDesc.Texture2DArray.ArraySize = 1;
-
- ID3D11DepthStencilView *dsv;
- result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
-
- if (result == E_OUTOFMEMORY)
- {
- srv->Release();
- return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
- }
- ASSERT(SUCCEEDED(result));
-
- // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
- // also needs to keep a reference to the texture.
- mTexture->AddRef();
-
- mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
- std::max(mTextureWidth >> level, 1U),
- std::max(mTextureHeight >> level, 1U));
- }
- else
- {
- UNREACHABLE();
- }
- }
-
- return mRenderTarget[faceIdx][level];
- }
- else
- {
- return NULL;
- }
-}
-
-ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
-{
- if (!mSRV)
- {
- ID3D11Device *device = mRenderer->getDevice();
-
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srvDesc.Format = mShaderResourceFormat;
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
- srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
- srvDesc.TextureCube.MostDetailedMip = 0;
-
- HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
-
- if (result == E_OUTOFMEMORY)
- {
- return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
- }
- ASSERT(SUCCEEDED(result));
- }
-
- return mSRV;
-}
-
-void TextureStorage11_Cube::generateMipmap(int face, int level)
-{
- RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
- RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
-
- generateMipmapLayer(source, dest);
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h
deleted file mode 100644
index 3c5ded05b8..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h
+++ /dev/null
@@ -1,120 +0,0 @@
-//
-// 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.
-//
-
-// 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 LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
-#define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
-
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/renderer/TextureStorage.h"
-
-namespace rx
-{
-class RenderTarget;
-class RenderTarget11;
-class Renderer;
-class Renderer11;
-class SwapChain11;
-
-class TextureStorage11 : public TextureStorage
-{
- public:
- TextureStorage11(Renderer *renderer, UINT bindFlags);
- virtual ~TextureStorage11();
-
- static TextureStorage11 *makeTextureStorage11(TextureStorage *storage);
-
- static DWORD GetTextureBindFlags(DXGI_FORMAT d3dfmt, GLenum glusage, bool forceRenderable);
- static bool IsTextureFormatRenderable(DXGI_FORMAT format);
-
- UINT getBindFlags() const;
-
- virtual ID3D11Texture2D *getBaseTexture() const;
- virtual ID3D11ShaderResourceView *getSRV() = 0;
- virtual RenderTarget *getRenderTarget() { return getRenderTarget(0); }
- virtual RenderTarget *getRenderTarget(int level) { return NULL; }
- virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return getRenderTarget(faceTarget, 0); }
- virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level) { return NULL; }
-
- virtual void generateMipmap(int level) {};
- virtual void generateMipmap(int face, int level) {};
-
- virtual int getLodOffset() const;
- virtual bool isRenderTarget() const;
- virtual bool isManaged() const;
- virtual int levelCount();
- UINT getSubresourceIndex(int level, int faceTarget);
-
- bool updateSubresourceLevel(ID3D11Texture2D *texture, unsigned int sourceSubresource, int level,
- int faceTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-
- protected:
- void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest);
-
- Renderer11 *mRenderer;
- int mLodOffset;
- unsigned int mMipLevels;
-
- ID3D11Texture2D *mTexture;
- DXGI_FORMAT mTextureFormat;
- DXGI_FORMAT mShaderResourceFormat;
- DXGI_FORMAT mRenderTargetFormat;
- DXGI_FORMAT mDepthStencilFormat;
- unsigned int mTextureWidth;
- unsigned int mTextureHeight;
-
- ID3D11ShaderResourceView *mSRV;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage11);
-
- const UINT mBindFlags;
-};
-
-class TextureStorage11_2D : public TextureStorage11
-{
- public:
- TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain);
- TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
- virtual ~TextureStorage11_2D();
-
- static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage);
-
- virtual ID3D11ShaderResourceView *getSRV();
- virtual RenderTarget *getRenderTarget(int level);
-
- virtual void generateMipmap(int level);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D);
-
- RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
-};
-
-class TextureStorage11_Cube : public TextureStorage11
-{
- public:
- TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
- virtual ~TextureStorage11_Cube();
-
- static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage);
-
- virtual ID3D11ShaderResourceView *getSRV();
- virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level);
-
- virtual void generateMipmap(int face, int level);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube);
-
- RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp
deleted file mode 100644
index 6f9b4181f1..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp
+++ /dev/null
@@ -1,440 +0,0 @@
-#include "precompiled.h"
-//
-// 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 "libGLESv2/renderer/d3d11/VertexBuffer11.h"
-#include "libGLESv2/renderer/BufferStorage.h"
-
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/renderer/d3d11/Renderer11.h"
-#include "libGLESv2/Context.h"
-
-namespace rx
-{
-
-VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer)
-{
- mBuffer = NULL;
- mBufferSize = 0;
- mDynamicUsage = false;
-}
-
-VertexBuffer11::~VertexBuffer11()
-{
- if (mBuffer)
- {
- mBuffer->Release();
- mBuffer = NULL;
- }
-}
-
-bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
-{
- if (mBuffer)
- {
- mBuffer->Release();
- mBuffer = NULL;
- }
-
- 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 false;
- }
- }
-
- mBufferSize = size;
- mDynamicUsage = dynamicUsage;
- return true;
-}
-
-VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer)
-{
- ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer));
- return static_cast<VertexBuffer11*>(vetexBuffer);
-}
-
-bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
- GLsizei instances, unsigned int offset)
-{
- if (mBuffer)
- {
- gl::Buffer *buffer = attrib.mBoundBuffer.get();
-
- int inputStride = attrib.stride();
- const VertexConverter &converter = getVertexConversion(attrib);
-
- ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
-
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
- if (FAILED(result))
- {
- ERR("Vertex buffer map failed with error 0x%08x", result);
- return false;
- }
-
- char* output = reinterpret_cast<char*>(mappedResource.pData) + offset;
-
- const char *input = NULL;
- if (buffer)
- {
- BufferStorage *storage = buffer->getStorage();
- input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset);
- }
- else
- {
- input = static_cast<const char*>(attrib.mPointer);
- }
-
- if (instances == 0 || attrib.mDivisor == 0)
- {
- input += inputStride * start;
- }
-
- converter.conversionFunc(input, inputStride, count, output);
-
- dxContext->Unmap(mBuffer, 0);
-
- return true;
- }
- else
- {
- ERR("Vertex buffer not initialized.");
- return false;
- }
-}
-
-bool VertexBuffer11::storeRawData(const void* data, unsigned int size, unsigned int offset)
-{
- if (mBuffer)
- {
- ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
-
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
- if (FAILED(result))
- {
- ERR("Vertex buffer map failed with error 0x%08x", result);
- return false;
- }
-
- char* bufferData = static_cast<char*>(mappedResource.pData);
- memcpy(bufferData + offset, data, size);
-
- dxContext->Unmap(mBuffer, 0);
-
- return true;
- }
- else
- {
- ERR("Vertex buffer not initialized.");
- return false;
- }
-}
-
-bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
- GLsizei instances, unsigned int *outSpaceRequired) const
-{
- unsigned int elementSize = getVertexConversion(attrib).outputElementSize;
-
- unsigned int elementCount = 0;
- if (instances == 0 || attrib.mDivisor == 0)
- {
- elementCount = count;
- }
- else
- {
- if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1))
- {
- // Round up
- elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor;
- }
- else
- {
- elementCount = instances / attrib.mDivisor;
- }
- }
-
- if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
- {
- if (outSpaceRequired)
- {
- *outSpaceRequired = elementSize * elementCount;
- }
- return true;
- }
- else
- {
- return false;
- }
-}
-
-bool VertexBuffer11::requiresConversion(const gl::VertexAttribute &attrib) const
-{
- return !getVertexConversion(attrib).identity;
-}
-
-unsigned int VertexBuffer11::getBufferSize() const
-{
- return mBufferSize;
-}
-
-bool VertexBuffer11::setBufferSize(unsigned int size)
-{
- if (size > mBufferSize)
- {
- return initialize(size, mDynamicUsage);
- }
- else
- {
- return true;
- }
-}
-
-bool VertexBuffer11::discard()
-{
- if (mBuffer)
- {
- ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
-
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
- if (FAILED(result))
- {
- ERR("Vertex buffer map failed with error 0x%08x", result);
- return false;
- }
-
- dxContext->Unmap(mBuffer, 0);
-
- return true;
- }
- else
- {
- ERR("Vertex buffer not initialized.");
- return false;
- }
-}
-
-unsigned int VertexBuffer11::getVertexSize(const gl::VertexAttribute &attrib) const
-{
- return getVertexConversion(attrib).outputElementSize;
-}
-
-DXGI_FORMAT VertexBuffer11::getDXGIFormat(const gl::VertexAttribute &attrib) const
-{
- return getVertexConversion(attrib).dxgiFormat;
-}
-
-ID3D11Buffer *VertexBuffer11::getBuffer() const
-{
- return mBuffer;
-}
-
-template <typename T, unsigned int componentCount, bool widen, bool normalized>
-static void copyVertexData(const void *input, unsigned int stride, unsigned int count, void *output)
-{
- unsigned int attribSize = sizeof(T) * componentCount;
-
- if (attribSize == stride && !widen)
- {
- memcpy(output, input, count * attribSize);
- }
- else
- {
- unsigned int outputStride = widen ? 4 : componentCount;
- T defaultVal = normalized ? std::numeric_limits<T>::max() : T(1);
-
- for (unsigned int i = 0; i < count; i++)
- {
- const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + i * stride);
- T *offsetOutput = reinterpret_cast<T*>(output) + i * outputStride;
-
- for (unsigned int j = 0; j < componentCount; j++)
- {
- offsetOutput[j] = offsetInput[j];
- }
-
- if (widen)
- {
- offsetOutput[3] = defaultVal;
- }
- }
- }
-}
-
-template <unsigned int componentCount>
-static void copyFixedVertexData(const void* input, unsigned int stride, unsigned int count, void* output)
-{
- static const float divisor = 1.0f / (1 << 16);
-
- for (unsigned int i = 0; i < count; i++)
- {
- const GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(reinterpret_cast<const char*>(input) + stride * i);
- float* offsetOutput = reinterpret_cast<float*>(output) + i * componentCount;
-
- for (unsigned int j = 0; j < componentCount; j++)
- {
- offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor;
- }
- }
-}
-
-template <typename T, unsigned int componentCount, bool normalized>
-static void copyToFloatVertexData(const void* input, unsigned int stride, unsigned int count, void* output)
-{
- typedef std::numeric_limits<T> NL;
-
- for (unsigned int i = 0; i < count; i++)
- {
- const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + stride * i);
- float *offsetOutput = reinterpret_cast<float*>(output) + i * componentCount;
-
- for (unsigned int j = 0; j < componentCount; 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]);
- }
- }
- }
-}
-
-const VertexBuffer11::VertexConverter VertexBuffer11::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] =
-{
- { // GL_BYTE
- { // unnormalized
- { &copyToFloatVertexData<GLbyte, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
- { &copyToFloatVertexData<GLbyte, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
- { &copyToFloatVertexData<GLbyte, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
- { &copyToFloatVertexData<GLbyte, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
- },
- { // normalized
- { &copyVertexData<GLbyte, 1, false, true>, true, DXGI_FORMAT_R8_SNORM, 1 },
- { &copyVertexData<GLbyte, 2, false, true>, true, DXGI_FORMAT_R8G8_SNORM, 2 },
- { &copyVertexData<GLbyte, 3, true, true>, false, DXGI_FORMAT_R8G8B8A8_SNORM, 4 },
- { &copyVertexData<GLbyte, 4, false, true>, true, DXGI_FORMAT_R8G8B8A8_SNORM, 4 },
- },
- },
- { // GL_UNSIGNED_BYTE
- { // unnormalized
- { &copyToFloatVertexData<GLubyte, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
- { &copyToFloatVertexData<GLubyte, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
- { &copyToFloatVertexData<GLubyte, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
- { &copyToFloatVertexData<GLubyte, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
- },
- { // normalized
- { &copyVertexData<GLubyte, 1, false, true>, true, DXGI_FORMAT_R8_UNORM, 1 },
- { &copyVertexData<GLubyte, 2, false, true>, true, DXGI_FORMAT_R8G8_UNORM, 2 },
- { &copyVertexData<GLubyte, 3, true, true>, false, DXGI_FORMAT_R8G8B8A8_UNORM, 4 },
- { &copyVertexData<GLubyte, 4, false, true>, true, DXGI_FORMAT_R8G8B8A8_UNORM, 4 },
- },
- },
- { // GL_SHORT
- { // unnormalized
- { &copyToFloatVertexData<GLshort, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
- { &copyToFloatVertexData<GLshort, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
- { &copyToFloatVertexData<GLshort, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
- { &copyToFloatVertexData<GLshort, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
- },
- { // normalized
- { &copyVertexData<GLshort, 1, false, true>, true, DXGI_FORMAT_R16_SNORM, 2 },
- { &copyVertexData<GLshort, 2, false, true>, true, DXGI_FORMAT_R16G16_SNORM, 4 },
- { &copyVertexData<GLshort, 3, true, true>, false, DXGI_FORMAT_R16G16B16A16_SNORM, 8 },
- { &copyVertexData<GLshort, 4, false, true>, true, DXGI_FORMAT_R16G16B16A16_SNORM, 8 },
- },
- },
- { // GL_UNSIGNED_SHORT
- { // unnormalized
- { &copyToFloatVertexData<GLushort, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
- { &copyToFloatVertexData<GLushort, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
- { &copyToFloatVertexData<GLushort, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
- { &copyToFloatVertexData<GLushort, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
- },
- { // normalized
- { &copyVertexData<GLushort, 1, false, true>, true, DXGI_FORMAT_R16_UNORM, 2 },
- { &copyVertexData<GLushort, 2, false, true>, true, DXGI_FORMAT_R16G16_UNORM, 4 },
- { &copyVertexData<GLushort, 3, true, true>, false, DXGI_FORMAT_R16G16B16A16_UNORM, 8 },
- { &copyVertexData<GLushort, 4, false, true>, true, DXGI_FORMAT_R16G16B16A16_UNORM, 8 },
- },
- },
- { // GL_FIXED
- { // unnormalized
- { &copyFixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 },
- { &copyFixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
- { &copyFixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
- { &copyFixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
- },
- { // normalized
- { &copyFixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 },
- { &copyFixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
- { &copyFixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
- { &copyFixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
- },
- },
- { // GL_FLOAT
- { // unnormalized
- { &copyVertexData<GLfloat, 1, false, false>, true, DXGI_FORMAT_R32_FLOAT, 4 },
- { &copyVertexData<GLfloat, 2, false, false>, true, DXGI_FORMAT_R32G32_FLOAT, 8 },
- { &copyVertexData<GLfloat, 3, false, false>, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
- { &copyVertexData<GLfloat, 4, false, false>, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
- },
- { // normalized
- { &copyVertexData<GLfloat, 1, false, false>, true, DXGI_FORMAT_R32_FLOAT, 4 },
- { &copyVertexData<GLfloat, 2, false, false>, true, DXGI_FORMAT_R32G32_FLOAT, 8 },
- { &copyVertexData<GLfloat, 3, false, false>, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
- { &copyVertexData<GLfloat, 4, false, false>, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
- },
- },
-};
-
-const VertexBuffer11::VertexConverter &VertexBuffer11::getVertexConversion(const gl::VertexAttribute &attribute)
-{
- unsigned int typeIndex = 0;
- switch (attribute.mType)
- {
- case GL_BYTE: typeIndex = 0; break;
- case GL_UNSIGNED_BYTE: typeIndex = 1; break;
- case GL_SHORT: typeIndex = 2; break;
- case GL_UNSIGNED_SHORT: typeIndex = 3; break;
- case GL_FIXED: typeIndex = 4; break;
- case GL_FLOAT: typeIndex = 5; break;
- default: UNREACHABLE(); break;
- }
-
- return mPossibleTranslations[typeIndex][attribute.mNormalized ? 1 : 0][attribute.mSize - 1];
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h
deleted file mode 100644
index eceb426e82..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// 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 LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
-#define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
-
-#include "libGLESv2/renderer/VertexBuffer.h"
-
-namespace rx
-{
-class Renderer11;
-
-class VertexBuffer11 : public VertexBuffer
-{
- public:
- explicit VertexBuffer11(rx::Renderer11 *const renderer);
- virtual ~VertexBuffer11();
-
- virtual bool initialize(unsigned int size, bool dynamicUsage);
-
- static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer);
-
- virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
- unsigned int offset);
- virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset);
-
- virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
- unsigned int *outSpaceRequired) const;
-
- virtual bool requiresConversion(const gl::VertexAttribute &attrib) const;
-
- virtual unsigned int getBufferSize() const;
- virtual bool setBufferSize(unsigned int size);
- virtual bool discard();
-
- unsigned int getVertexSize(const gl::VertexAttribute &attrib) const;
- DXGI_FORMAT getDXGIFormat(const gl::VertexAttribute &attrib) const;
-
- ID3D11Buffer *getBuffer() const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(VertexBuffer11);
-
- rx::Renderer11 *const mRenderer;
-
- ID3D11Buffer *mBuffer;
- unsigned int mBufferSize;
- bool mDynamicUsage;
-
- typedef void (*VertexConversionFunction)(const void *, unsigned int, unsigned int, void *);
- struct VertexConverter
- {
- VertexConversionFunction conversionFunc;
- bool identity;
- DXGI_FORMAT dxgiFormat;
- unsigned int outputElementSize;
- };
-
- enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
-
- // This table is used to generate mAttributeTypes.
- static const VertexConverter mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1]
-
- static const VertexConverter &getVertexConversion(const gl::VertexAttribute &attribute);
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp
deleted file mode 100644
index 34b8259a80..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp
+++ /dev/null
@@ -1,688 +0,0 @@
-#include "precompiled.h"
-//
-// 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.
-//
-
-// renderer11_utils.cpp: Conversion functions and other utility routines
-// specific to the D3D11 renderer.
-
-#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
-
-#include "common/debug.h"
-
-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;
- 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)
-{
- if (maxAnisotropy > 1.0f)
- {
- return D3D11_ENCODE_ANISOTROPIC_FILTER(false);
- }
- 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, false);
- }
-}
-
-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;
-}
-
-FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset)
-{
- return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast<float>(lodOffset) : -FLT_MAX;
-}
-
-FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset)
-{
- return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast<float>(lodOffset) : FLT_MAX;
-}
-
-}
-
-namespace d3d11_gl
-{
-
-GLenum ConvertBackBufferFormat(DXGI_FORMAT format)
-{
- switch (format)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM: return GL_RGBA8_OES;
- case DXGI_FORMAT_B8G8R8A8_UNORM: return GL_BGRA8_EXT;
- default:
- UNREACHABLE();
- }
-
- return GL_RGBA8_OES;
-}
-
-GLenum ConvertDepthStencilFormat(DXGI_FORMAT format)
-{
- switch (format)
- {
- case DXGI_FORMAT_UNKNOWN: return GL_NONE;
- case DXGI_FORMAT_D16_UNORM: return GL_DEPTH_COMPONENT16;
- case DXGI_FORMAT_D24_UNORM_S8_UINT: return GL_DEPTH24_STENCIL8_OES;
- default:
- UNREACHABLE();
- }
-
- return GL_DEPTH24_STENCIL8_OES;
-}
-
-GLenum ConvertRenderbufferFormat(DXGI_FORMAT format)
-{
- switch (format)
- {
- case DXGI_FORMAT_B8G8R8A8_UNORM:
- return GL_BGRA8_EXT;
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- return GL_RGBA8_OES;
- case DXGI_FORMAT_D16_UNORM:
- return GL_DEPTH_COMPONENT16;
- case DXGI_FORMAT_D24_UNORM_S8_UINT:
- return GL_DEPTH24_STENCIL8_OES;
- default:
- UNREACHABLE();
- }
-
- return GL_RGBA8_OES;
-}
-
-GLenum ConvertTextureInternalFormat(DXGI_FORMAT format)
-{
- switch (format)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- return GL_RGBA8_OES;
- case DXGI_FORMAT_A8_UNORM:
- return GL_ALPHA8_EXT;
- case DXGI_FORMAT_BC1_UNORM:
- return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
- case DXGI_FORMAT_BC2_UNORM:
- return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
- case DXGI_FORMAT_BC3_UNORM:
- return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- return GL_RGBA32F_EXT;
- case DXGI_FORMAT_R32G32B32_FLOAT:
- return GL_RGB32F_EXT;
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- return GL_RGBA16F_EXT;
- case DXGI_FORMAT_B8G8R8A8_UNORM:
- return GL_BGRA8_EXT;
- case DXGI_FORMAT_R8_UNORM:
- return GL_R8_EXT;
- case DXGI_FORMAT_R8G8_UNORM:
- return GL_RG8_EXT;
- case DXGI_FORMAT_R16_FLOAT:
- return GL_R16F_EXT;
- case DXGI_FORMAT_R16G16_FLOAT:
- return GL_RG16F_EXT;
- case DXGI_FORMAT_D16_UNORM:
- return GL_DEPTH_COMPONENT16;
- case DXGI_FORMAT_D24_UNORM_S8_UINT:
- return GL_DEPTH24_STENCIL8_OES;
- case DXGI_FORMAT_UNKNOWN:
- return GL_NONE;
- default:
- UNREACHABLE();
- }
-
- return GL_RGBA8_OES;
-}
-
-}
-
-namespace gl_d3d11
-{
-
-DXGI_FORMAT ConvertRenderbufferFormat(GLenum format)
-{
- switch (format)
- {
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGBA8_OES:
- case GL_RGB565:
- case GL_RGB8_OES:
- return DXGI_FORMAT_R8G8B8A8_UNORM;
- case GL_BGRA8_EXT:
- return DXGI_FORMAT_B8G8R8A8_UNORM;
- case GL_DEPTH_COMPONENT16:
- return DXGI_FORMAT_D16_UNORM;
- case GL_STENCIL_INDEX8:
- case GL_DEPTH24_STENCIL8_OES:
- return DXGI_FORMAT_D24_UNORM_S8_UINT;
- default:
- UNREACHABLE();
- }
-
- return DXGI_FORMAT_R8G8B8A8_UNORM;
-}
-
-DXGI_FORMAT ConvertTextureFormat(GLenum internalformat, D3D_FEATURE_LEVEL featureLevel)
-{
- switch (internalformat)
- {
- case GL_RGB565:
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGB8_OES:
- case GL_RGBA8_OES:
- case GL_LUMINANCE8_EXT:
- case GL_LUMINANCE8_ALPHA8_EXT:
- return DXGI_FORMAT_R8G8B8A8_UNORM;
- case GL_ALPHA8_EXT:
- return featureLevel >= D3D_FEATURE_LEVEL_10_0 ? DXGI_FORMAT_A8_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- return DXGI_FORMAT_BC1_UNORM;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- return DXGI_FORMAT_BC2_UNORM;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- return DXGI_FORMAT_BC3_UNORM;
- case GL_RGBA32F_EXT:
- case GL_ALPHA32F_EXT:
- case GL_LUMINANCE_ALPHA32F_EXT:
- return DXGI_FORMAT_R32G32B32A32_FLOAT;
- case GL_RGB32F_EXT:
- case GL_LUMINANCE32F_EXT:
- return DXGI_FORMAT_R32G32B32A32_FLOAT;
- case GL_RGBA16F_EXT:
- case GL_ALPHA16F_EXT:
- case GL_LUMINANCE_ALPHA16F_EXT:
- case GL_RGB16F_EXT:
- case GL_LUMINANCE16F_EXT:
- return DXGI_FORMAT_R16G16B16A16_FLOAT;
- case GL_BGRA8_EXT:
- return DXGI_FORMAT_B8G8R8A8_UNORM;
- case GL_R8_EXT:
- return DXGI_FORMAT_R8_UNORM;
- case GL_RG8_EXT:
- return DXGI_FORMAT_R8G8_UNORM;
- case GL_R16F_EXT:
- return DXGI_FORMAT_R16_FLOAT;
- case GL_RG16F_EXT:
- return DXGI_FORMAT_R16G16_FLOAT;
- case GL_DEPTH_COMPONENT16:
- return DXGI_FORMAT_D16_UNORM;
- case GL_DEPTH_COMPONENT32_OES:
- case GL_DEPTH24_STENCIL8_OES:
- return DXGI_FORMAT_D24_UNORM_S8_UINT;
- case GL_NONE:
- return DXGI_FORMAT_UNKNOWN;
- default:
- UNREACHABLE();
- }
-
- return DXGI_FORMAT_R8G8B8A8_UNORM;
-}
-
-}
-
-namespace d3d11
-{
-
-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 SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z,
- const gl::Color &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;
-}
-
-size_t ComputePixelSizeBits(DXGI_FORMAT format)
-{
- switch (format)
- {
- case DXGI_FORMAT_R1_UNORM:
- return 1;
-
- case DXGI_FORMAT_A8_UNORM:
- case DXGI_FORMAT_R8_SINT:
- case DXGI_FORMAT_R8_SNORM:
- case DXGI_FORMAT_R8_TYPELESS:
- case DXGI_FORMAT_R8_UINT:
- case DXGI_FORMAT_R8_UNORM:
- return 8;
-
- case DXGI_FORMAT_B5G5R5A1_UNORM:
- case DXGI_FORMAT_B5G6R5_UNORM:
- case DXGI_FORMAT_D16_UNORM:
- case DXGI_FORMAT_R16_FLOAT:
- case DXGI_FORMAT_R16_SINT:
- case DXGI_FORMAT_R16_SNORM:
- case DXGI_FORMAT_R16_TYPELESS:
- case DXGI_FORMAT_R16_UINT:
- case DXGI_FORMAT_R16_UNORM:
- case DXGI_FORMAT_R8G8_SINT:
- case DXGI_FORMAT_R8G8_SNORM:
- case DXGI_FORMAT_R8G8_TYPELESS:
- case DXGI_FORMAT_R8G8_UINT:
- case DXGI_FORMAT_R8G8_UNORM:
- return 16;
-
- case DXGI_FORMAT_B8G8R8X8_TYPELESS:
- case DXGI_FORMAT_B8G8R8X8_UNORM:
- case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
- case DXGI_FORMAT_D24_UNORM_S8_UINT:
- case DXGI_FORMAT_D32_FLOAT:
- case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
- case DXGI_FORMAT_G8R8_G8B8_UNORM:
- case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
- case DXGI_FORMAT_R10G10B10A2_TYPELESS:
- case DXGI_FORMAT_R10G10B10A2_UINT:
- case DXGI_FORMAT_R10G10B10A2_UNORM:
- case DXGI_FORMAT_R11G11B10_FLOAT:
- case DXGI_FORMAT_R16G16_FLOAT:
- case DXGI_FORMAT_R16G16_SINT:
- case DXGI_FORMAT_R16G16_SNORM:
- case DXGI_FORMAT_R16G16_TYPELESS:
- case DXGI_FORMAT_R16G16_UINT:
- case DXGI_FORMAT_R16G16_UNORM:
- case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
- case DXGI_FORMAT_R24G8_TYPELESS:
- case DXGI_FORMAT_R32_FLOAT:
- case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
- case DXGI_FORMAT_R32_SINT:
- case DXGI_FORMAT_R32_TYPELESS:
- case DXGI_FORMAT_R32_UINT:
- case DXGI_FORMAT_R8G8_B8G8_UNORM:
- case DXGI_FORMAT_R8G8B8A8_SINT:
- case DXGI_FORMAT_R8G8B8A8_SNORM:
- case DXGI_FORMAT_R8G8B8A8_TYPELESS:
- case DXGI_FORMAT_R8G8B8A8_UINT:
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
- case DXGI_FORMAT_B8G8R8A8_TYPELESS:
- case DXGI_FORMAT_B8G8R8A8_UNORM:
- case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
- case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
- case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
- case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
- return 32;
-
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- case DXGI_FORMAT_R16G16B16A16_SINT:
- case DXGI_FORMAT_R16G16B16A16_SNORM:
- case DXGI_FORMAT_R16G16B16A16_TYPELESS:
- case DXGI_FORMAT_R16G16B16A16_UINT:
- case DXGI_FORMAT_R16G16B16A16_UNORM:
- case DXGI_FORMAT_R32G32_FLOAT:
- case DXGI_FORMAT_R32G32_SINT:
- case DXGI_FORMAT_R32G32_TYPELESS:
- case DXGI_FORMAT_R32G32_UINT:
- case DXGI_FORMAT_R32G8X24_TYPELESS:
- return 64;
-
- case DXGI_FORMAT_R32G32B32_FLOAT:
- case DXGI_FORMAT_R32G32B32_SINT:
- case DXGI_FORMAT_R32G32B32_TYPELESS:
- case DXGI_FORMAT_R32G32B32_UINT:
- return 96;
-
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- case DXGI_FORMAT_R32G32B32A32_SINT:
- case DXGI_FORMAT_R32G32B32A32_TYPELESS:
- case DXGI_FORMAT_R32G32B32A32_UINT:
- return 128;
-
- case DXGI_FORMAT_BC1_TYPELESS:
- case DXGI_FORMAT_BC1_UNORM:
- case DXGI_FORMAT_BC1_UNORM_SRGB:
- case DXGI_FORMAT_BC4_SNORM:
- case DXGI_FORMAT_BC4_TYPELESS:
- case DXGI_FORMAT_BC4_UNORM:
- return 4;
-
- case DXGI_FORMAT_BC2_TYPELESS:
- case DXGI_FORMAT_BC2_UNORM:
- case DXGI_FORMAT_BC2_UNORM_SRGB:
- case DXGI_FORMAT_BC3_TYPELESS:
- case DXGI_FORMAT_BC3_UNORM:
- case DXGI_FORMAT_BC3_UNORM_SRGB:
- case DXGI_FORMAT_BC5_SNORM:
- case DXGI_FORMAT_BC5_TYPELESS:
- case DXGI_FORMAT_BC5_UNORM:
- case DXGI_FORMAT_BC6H_SF16:
- case DXGI_FORMAT_BC6H_TYPELESS:
- case DXGI_FORMAT_BC6H_UF16:
- case DXGI_FORMAT_BC7_TYPELESS:
- case DXGI_FORMAT_BC7_UNORM:
- case DXGI_FORMAT_BC7_UNORM_SRGB:
- return 8;
-
- default:
- return 0;
- }
-}
-
-size_t ComputeBlockSizeBits(DXGI_FORMAT format)
-{
- switch (format)
- {
- case DXGI_FORMAT_BC1_TYPELESS:
- case DXGI_FORMAT_BC1_UNORM:
- case DXGI_FORMAT_BC1_UNORM_SRGB:
- case DXGI_FORMAT_BC4_SNORM:
- case DXGI_FORMAT_BC4_TYPELESS:
- case DXGI_FORMAT_BC4_UNORM:
- case DXGI_FORMAT_BC2_TYPELESS:
- case DXGI_FORMAT_BC2_UNORM:
- case DXGI_FORMAT_BC2_UNORM_SRGB:
- case DXGI_FORMAT_BC3_TYPELESS:
- case DXGI_FORMAT_BC3_UNORM:
- case DXGI_FORMAT_BC3_UNORM_SRGB:
- case DXGI_FORMAT_BC5_SNORM:
- case DXGI_FORMAT_BC5_TYPELESS:
- case DXGI_FORMAT_BC5_UNORM:
- case DXGI_FORMAT_BC6H_SF16:
- case DXGI_FORMAT_BC6H_TYPELESS:
- case DXGI_FORMAT_BC6H_UF16:
- case DXGI_FORMAT_BC7_TYPELESS:
- case DXGI_FORMAT_BC7_UNORM:
- case DXGI_FORMAT_BC7_UNORM_SRGB:
- return ComputePixelSizeBits(format) * 16;
- default:
- UNREACHABLE();
- return 0;
- }
-}
-
-bool IsCompressed(DXGI_FORMAT format)
-{
- switch (format)
- {
- case DXGI_FORMAT_BC1_TYPELESS:
- case DXGI_FORMAT_BC1_UNORM:
- case DXGI_FORMAT_BC1_UNORM_SRGB:
- case DXGI_FORMAT_BC4_SNORM:
- case DXGI_FORMAT_BC4_TYPELESS:
- case DXGI_FORMAT_BC4_UNORM:
- case DXGI_FORMAT_BC2_TYPELESS:
- case DXGI_FORMAT_BC2_UNORM:
- case DXGI_FORMAT_BC2_UNORM_SRGB:
- case DXGI_FORMAT_BC3_TYPELESS:
- case DXGI_FORMAT_BC3_UNORM:
- case DXGI_FORMAT_BC3_UNORM_SRGB:
- case DXGI_FORMAT_BC5_SNORM:
- case DXGI_FORMAT_BC5_TYPELESS:
- case DXGI_FORMAT_BC5_UNORM:
- case DXGI_FORMAT_BC6H_SF16:
- case DXGI_FORMAT_BC6H_TYPELESS:
- case DXGI_FORMAT_BC6H_UF16:
- case DXGI_FORMAT_BC7_TYPELESS:
- case DXGI_FORMAT_BC7_UNORM:
- case DXGI_FORMAT_BC7_UNORM_SRGB:
- return true;
- case DXGI_FORMAT_UNKNOWN:
- UNREACHABLE();
- return false;
- default:
- return false;
- }
-}
-
-unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format)
-{
- switch (format)
- {
- case DXGI_FORMAT_BC1_TYPELESS:
- case DXGI_FORMAT_BC1_UNORM:
- case DXGI_FORMAT_BC1_UNORM_SRGB:
- case DXGI_FORMAT_BC4_SNORM:
- case DXGI_FORMAT_BC4_TYPELESS:
- case DXGI_FORMAT_BC4_UNORM:
- case DXGI_FORMAT_BC2_TYPELESS:
- case DXGI_FORMAT_BC2_UNORM:
- case DXGI_FORMAT_BC2_UNORM_SRGB:
- case DXGI_FORMAT_BC3_TYPELESS:
- case DXGI_FORMAT_BC3_UNORM:
- case DXGI_FORMAT_BC3_UNORM_SRGB:
- case DXGI_FORMAT_BC5_SNORM:
- case DXGI_FORMAT_BC5_TYPELESS:
- case DXGI_FORMAT_BC5_UNORM:
- case DXGI_FORMAT_BC6H_SF16:
- case DXGI_FORMAT_BC6H_TYPELESS:
- case DXGI_FORMAT_BC6H_UF16:
- case DXGI_FORMAT_BC7_TYPELESS:
- case DXGI_FORMAT_BC7_UNORM:
- case DXGI_FORMAT_BC7_UNORM_SRGB:
- return 4;
- case DXGI_FORMAT_UNKNOWN:
- UNREACHABLE();
- return 1;
- default:
- return 1;
- }
-}
-
-bool IsDepthStencilFormat(DXGI_FORMAT format)
-{
- switch (format)
- {
- case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
- case DXGI_FORMAT_D32_FLOAT:
- case DXGI_FORMAT_D24_UNORM_S8_UINT:
- case DXGI_FORMAT_D16_UNORM:
- return true;
- default:
- return false;
- }
-}
-
-DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format)
-{
- switch (format)
- {
- case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32G8X24_TYPELESS;
- case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_TYPELESS;
- case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24G8_TYPELESS;
- case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_TYPELESS;
- default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN;
- }
-}
-
-DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format)
-{
- switch (format)
- {
- case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
- case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_UINT;
- case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
- case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_UNORM;
- default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN;
- }
-}
-
-HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
-{
-#if defined(_DEBUG)
- return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name);
-#else
- return S_OK;
-#endif
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h
deleted file mode 100644
index 70ad4fea2b..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h
+++ /dev/null
@@ -1,95 +0,0 @@
-//
-// 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.
-//
-
-// renderer11_utils.h: Conversion functions and other utility routines
-// specific to the D3D11 renderer.
-
-#ifndef LIBGLESV2_RENDERER_RENDERER11_UTILS_H
-#define LIBGLESV2_RENDERER_RENDERER11_UTILS_H
-
-#include "libGLESv2/angletypes.h"
-
-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);
-D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap);
-FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset);
-FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset);
-
-DXGI_FORMAT ConvertRenderbufferFormat(GLenum format);
-DXGI_FORMAT ConvertTextureFormat(GLenum format, D3D_FEATURE_LEVEL featureLevel);
-}
-
-namespace d3d11_gl
-{
-
-GLenum ConvertBackBufferFormat(DXGI_FORMAT format);
-GLenum ConvertDepthStencilFormat(DXGI_FORMAT format);
-GLenum ConvertRenderbufferFormat(DXGI_FORMAT format);
-GLenum ConvertTextureInternalFormat(DXGI_FORMAT format);
-
-}
-
-namespace d3d11
-{
-
-struct PositionTexCoordVertex
-{
- float x, y;
- float u, v;
-};
-void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v);
-
-struct PositionDepthColorVertex
-{
- float x, y, z;
- float r, g, b, a;
-};
-void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z,
- const gl::Color &color);
-
-size_t ComputePixelSizeBits(DXGI_FORMAT format);
-size_t ComputeBlockSizeBits(DXGI_FORMAT format);
-
-bool IsCompressed(DXGI_FORMAT format);
-unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format);
-
-bool IsDepthStencilFormat(DXGI_FORMAT format);
-DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format);
-DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format);
-
-HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name);
-
-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;
- }
-}
-
-}
-
-#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl
deleted file mode 100644
index cb132dc99c..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl
+++ /dev/null
@@ -1,42 +0,0 @@
-void VS_Clear( in float3 inPosition : POSITION, in float4 inColor : COLOR,
- out float4 outPosition : SV_POSITION, out float4 outColor : COLOR)
-{
- outPosition = float4(inPosition, 1.0f);
- outColor = inColor;
-}
-
-// Assume we are in SM4+, which has 8 color outputs
-struct PS_OutputMultiple
-{
- float4 color0 : SV_TARGET0;
- float4 color1 : SV_TARGET1;
- float4 color2 : SV_TARGET2;
- float4 color3 : SV_TARGET3;
-#ifdef SM4
- float4 color4 : SV_TARGET4;
- float4 color5 : SV_TARGET5;
- float4 color6 : SV_TARGET6;
- float4 color7 : SV_TARGET7;
-#endif
-};
-
-PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR)
-{
- PS_OutputMultiple outColor;
- outColor.color0 = inColor;
- outColor.color1 = inColor;
- outColor.color2 = inColor;
- outColor.color3 = inColor;
-#ifdef SM4
- outColor.color4 = inColor;
- outColor.color5 = inColor;
- outColor.color6 = inColor;
- outColor.color7 = inColor;
-#endif
- return outColor;
-}
-
-float4 PS_ClearSingle(in float4 inPosition : SV_Position, in float4 inColor : COLOR) : SV_Target0
-{
- return inColor;
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl
deleted file mode 100644
index 43b7801efc..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl
+++ /dev/null
@@ -1,29 +0,0 @@
-Texture2D Texture : register(t0);
-SamplerState Sampler : register(s0);
-
-void VS_Passthrough( 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;
-}
-
-float4 PS_PassthroughRGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
-{
- return Texture.Sample(Sampler, inTexCoord).rgba;
-}
-
-float4 PS_PassthroughRGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
-{
- return float4(Texture.Sample(Sampler, inTexCoord).rgb, 1.0f);
-}
-
-float4 PS_PassthroughLum(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
-{
- return float4(Texture.Sample(Sampler, inTexCoord).rrr, 1.0f);
-}
-
-float4 PS_PassthroughLumAlpha(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
-{
- return Texture.Sample(Sampler, inTexCoord).rrra;
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp
deleted file mode 100644
index 9fdc1246f1..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "precompiled.h"
-//
-// 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.
-//
-
-// BufferStorage9.cpp Defines the BufferStorage9 class.
-
-#include "libGLESv2/renderer/d3d9/BufferStorage9.h"
-#include "common/debug.h"
-
-namespace rx
-{
-
-BufferStorage9::BufferStorage9()
-{
- mMemory = NULL;
- mAllocatedSize = 0;
- mSize = 0;
-}
-
-BufferStorage9::~BufferStorage9()
-{
- delete[] mMemory;
-}
-
-BufferStorage9 *BufferStorage9::makeBufferStorage9(BufferStorage *bufferStorage)
-{
- ASSERT(HAS_DYNAMIC_TYPE(BufferStorage9*, bufferStorage));
- return static_cast<BufferStorage9*>(bufferStorage);
-}
-
-void *BufferStorage9::getData()
-{
- return mMemory;
-}
-
-void BufferStorage9::setData(const void* data, unsigned int size, unsigned int offset)
-{
- if (!mMemory || offset + size > mAllocatedSize)
- {
- unsigned int newAllocatedSize = offset + size;
- void *newMemory = new char[newAllocatedSize];
-
- if (offset > 0 && mMemory && mAllocatedSize > 0)
- {
- memcpy(newMemory, mMemory, std::min(offset, mAllocatedSize));
- }
-
- delete[] mMemory;
- mMemory = newMemory;
- mAllocatedSize = newAllocatedSize;
- }
-
- mSize = std::max(mSize, offset + size);
- if (data)
- {
- memcpy(reinterpret_cast<char*>(mMemory) + offset, data, size);
- }
-}
-
-void BufferStorage9::clear()
-{
- mSize = 0;
-}
-
-unsigned int BufferStorage9::getSize() const
-{
- return mSize;
-}
-
-bool BufferStorage9::supportsDirectBinding() const
-{
- return false;
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h
deleted file mode 100644
index 3e803969bc..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// 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.
-//
-
-// BufferStorage9.h Defines the BufferStorage9 class.
-
-#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_
-#define LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_
-
-#include "libGLESv2/renderer/BufferStorage.h"
-
-namespace rx
-{
-
-class BufferStorage9 : public BufferStorage
-{
- public:
- BufferStorage9();
- virtual ~BufferStorage9();
-
- static BufferStorage9 *makeBufferStorage9(BufferStorage *bufferStorage);
-
- virtual void *getData();
- virtual void setData(const void* data, unsigned int size, unsigned int offset);
- virtual void clear();
- virtual unsigned int getSize() const;
- virtual bool supportsDirectBinding() const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BufferStorage9);
-
- void *mMemory;
- unsigned int mAllocatedSize;
-
- unsigned int mSize;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp
deleted file mode 100644
index 639c37b4e4..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-#include "precompiled.h"
-//
-// 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::Fence9 class.
-
-#include "libGLESv2/renderer/d3d9/Fence9.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d9/Renderer9.h"
-
-namespace rx
-{
-
-Fence9::Fence9(rx::Renderer9 *renderer)
-{
- mRenderer = renderer;
- mQuery = NULL;
-}
-
-Fence9::~Fence9()
-{
- if (mQuery)
- {
- mRenderer->freeEventQuery(mQuery);
- mQuery = NULL;
- }
-}
-
-GLboolean Fence9::isFence()
-{
- // GL_NV_fence spec:
- // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
- return mQuery != NULL;
-}
-
-void Fence9::setFence(GLenum condition)
-{
- if (!mQuery)
- {
- mQuery = mRenderer->allocateEventQuery();
- if (!mQuery)
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
- }
-
- HRESULT result = mQuery->Issue(D3DISSUE_END);
- ASSERT(SUCCEEDED(result));
-
- setCondition(condition);
- setStatus(GL_FALSE);
-}
-
-GLboolean Fence9::testFence()
-{
- if (mQuery == NULL)
- {
- return gl::error(GL_INVALID_OPERATION, GL_TRUE);
- }
-
- HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
-
- if (d3d9::isDeviceLostError(result))
- {
- mRenderer->notifyDeviceLost();
- return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
- }
-
- ASSERT(result == S_OK || result == S_FALSE);
- setStatus(result == S_OK);
- return getStatus();
-}
-
-void Fence9::finishFence()
-{
- if (mQuery == NULL)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- while (!testFence())
- {
- Sleep(0);
- }
-}
-
-void Fence9::getFenceiv(GLenum pname, GLint *params)
-{
- if (mQuery == NULL)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- switch (pname)
- {
- case GL_FENCE_STATUS_NV:
- {
- // GL_NV_fence spec:
- // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
- // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
- if (getStatus())
- {
- params[0] = GL_TRUE;
- return;
- }
-
- HRESULT result = mQuery->GetData(NULL, 0, 0);
-
- if (d3d9::isDeviceLostError(result))
- {
- params[0] = GL_TRUE;
- mRenderer->notifyDeviceLost();
- return gl::error(GL_OUT_OF_MEMORY);
- }
-
- ASSERT(result == S_OK || result == S_FALSE);
- setStatus(result == S_OK);
- params[0] = getStatus();
-
- break;
- }
- case GL_FENCE_CONDITION_NV:
- params[0] = getCondition();
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- break;
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h
deleted file mode 100644
index 2fbbca3124..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h
+++ /dev/null
@@ -1,79 +0,0 @@
-//
-// 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.h: Defines the rx::Image9 class, which acts as the interface to
-// the actual underlying surfaces of a Texture.
-
-#ifndef LIBGLESV2_RENDERER_IMAGE9_H_
-#define LIBGLESV2_RENDERER_IMAGE9_H_
-
-#include "libGLESv2/renderer/Image.h"
-#include "common/debug.h"
-
-namespace gl
-{
-class Framebuffer;
-}
-
-namespace rx
-{
-class Renderer;
-class Renderer9;
-class TextureStorageInterface2D;
-class TextureStorageInterfaceCube;
-
-class Image9 : public Image
-{
- public:
- Image9();
- ~Image9();
-
- static Image9 *makeImage9(Image *img);
-
- static void generateMipmap(Image9 *dest, Image9 *source);
- static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface);
- static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source);
-
- virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease);
-
- virtual bool isRenderableFormat() const;
- D3DFORMAT getD3DFormat() const;
-
- virtual bool isDirty() const {return mSurface && mDirty;}
- IDirect3DSurface9 *getSurface();
-
- virtual void setManagedSurface(TextureStorageInterface2D *storage, int level);
- virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level);
- virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
- virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-
- virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLint unpackAlignment, const void *input);
- virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- const void *input);
-
- virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Image9);
-
- void createSurface();
- void setManagedSurface(IDirect3DSurface9 *surface);
- bool updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-
- HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect);
- void unlock();
-
- Renderer9 *mRenderer;
-
- D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable.
- D3DFORMAT mD3DFormat;
-
- IDirect3DSurface9 *mSurface;
-};
-}
-
-#endif // LIBGLESV2_RENDERER_IMAGE9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp
deleted file mode 100644
index 7cb5d13a18..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-#include "precompiled.h"
-//
-// 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.cpp: Defines the D3D9 IndexBuffer implementation.
-
-#include "libGLESv2/renderer/d3d9/IndexBuffer9.h"
-#include "libGLESv2/renderer/d3d9/Renderer9.h"
-
-namespace rx
-{
-
-IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer)
-{
- mIndexBuffer = NULL;
- mBufferSize = 0;
- mIndexType = 0;
- mDynamic = false;
-}
-
-IndexBuffer9::~IndexBuffer9()
-{
- if (mIndexBuffer)
- {
- mIndexBuffer->Release();
- mIndexBuffer = NULL;
- }
-}
-
-bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
-{
- if (mIndexBuffer)
- {
- mIndexBuffer->Release();
- mIndexBuffer = NULL;
- }
-
- updateSerial();
-
- if (bufferSize > 0)
- {
- D3DFORMAT format;
- if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE)
- {
- format = D3DFMT_INDEX16;
- }
- else if (indexType == GL_UNSIGNED_INT)
- {
- if (mRenderer->get32BitIndexSupport())
- {
- format = D3DFMT_INDEX32;
- }
- else
- {
- ERR("Attempted to create a 32-bit index buffer but renderer does not support 32-bit indices.");
- return false;
- }
- }
- else
- {
- ERR("Invalid index type %u.", indexType);
- return false;
- }
-
- DWORD usageFlags = D3DUSAGE_WRITEONLY;
- if (dynamic)
- {
- usageFlags |= D3DUSAGE_DYNAMIC;
- }
-
- HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer);
- if (FAILED(result))
- {
- ERR("Failed to create an index buffer of size %u, result: 0x%08x.", mBufferSize, result);
- return false;
- }
- }
-
- mBufferSize = bufferSize;
- mIndexType = indexType;
- mDynamic = dynamic;
-
- return true;
-}
-
-IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer)
-{
- ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer));
- return static_cast<IndexBuffer9*>(indexBuffer);
-}
-
-bool IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
-{
- if (mIndexBuffer)
- {
- DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0;
-
- void *mapPtr = NULL;
- HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags);
- if (FAILED(result))
- {
- ERR("Index buffer lock failed with error 0x%08x", result);
- return false;
- }
-
- *outMappedMemory = mapPtr;
- return true;
- }
- else
- {
- ERR("Index buffer not initialized.");
- return false;
- }
-}
-
-bool IndexBuffer9::unmapBuffer()
-{
- if (mIndexBuffer)
- {
- HRESULT result = mIndexBuffer->Unlock();
- if (FAILED(result))
- {
- ERR("Index buffer unlock failed with error 0x%08x", result);
- return false;
- }
-
- return true;
- }
- else
- {
- ERR("Index buffer not initialized.");
- return false;
- }
-}
-
-GLenum IndexBuffer9::getIndexType() const
-{
- return mIndexType;
-}
-
-unsigned int IndexBuffer9::getBufferSize() const
-{
- return mBufferSize;
-}
-
-bool IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType)
-{
- if (bufferSize > mBufferSize || indexType != mIndexType)
- {
- return initialize(bufferSize, indexType, mDynamic);
- }
- else
- {
- return true;
- }
-}
-
-bool IndexBuffer9::discard()
-{
- if (mIndexBuffer)
- {
- void *dummy;
- HRESULT result;
-
- result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
- if (FAILED(result))
- {
- ERR("Discard lock failed with error 0x%08x", result);
- return false;
- }
-
- result = mIndexBuffer->Unlock();
- if (FAILED(result))
- {
- ERR("Discard unlock failed with error 0x%08x", result);
- return false;
- }
-
- return true;
- }
- else
- {
- ERR("Index buffer not initialized.");
- return false;
- }
-}
-
-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;
-}
-
-} \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp
deleted file mode 100644
index 72781cbc39..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-#include "precompiled.h"
-//
-// 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 "libGLESv2/renderer/d3d9/Query9.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d9/Renderer9.h"
-
-namespace rx
-{
-
-Query9::Query9(rx::Renderer9 *renderer, GLenum type) : QueryImpl(type)
-{
- mRenderer = renderer;
- mQuery = NULL;
-}
-
-Query9::~Query9()
-{
- if (mQuery)
- {
- mQuery->Release();
- mQuery = NULL;
- }
-}
-
-void Query9::begin()
-{
- if (mQuery == NULL)
- {
- if (FAILED(mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery)))
- {
- return gl::error(GL_OUT_OF_MEMORY);
- }
- }
-
- HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
- ASSERT(SUCCEEDED(result));
-}
-
-void Query9::end()
-{
- if (mQuery == NULL)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- HRESULT result = mQuery->Issue(D3DISSUE_END);
- ASSERT(SUCCEEDED(result));
-
- mStatus = GL_FALSE;
- mResult = GL_FALSE;
-}
-
-GLuint Query9::getResult()
-{
- if (mQuery != NULL)
- {
- while (!testQuery())
- {
- Sleep(0);
- // 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 (mRenderer->testDeviceLost(true))
- {
- return gl::error(GL_OUT_OF_MEMORY, 0);
- }
- }
- }
-
- return mResult;
-}
-
-GLboolean Query9::isResultAvailable()
-{
- if (mQuery != NULL)
- {
- testQuery();
- }
-
- return mStatus;
-}
-
-GLboolean Query9::testQuery()
-{
- if (mQuery != NULL && mStatus != GL_TRUE)
- {
- DWORD numPixels = 0;
-
- HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH);
- if (hres == S_OK)
- {
- mStatus = GL_TRUE;
-
- switch (getType())
- {
- case GL_ANY_SAMPLES_PASSED_EXT:
- case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
- mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
- break;
- default:
- ASSERT(false);
- }
- }
- else if (d3d9::isDeviceLostError(hres))
- {
- mRenderer->notifyDeviceLost();
- return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
- }
-
- return mStatus;
- }
-
- return GL_TRUE; // prevent blocking when query is null
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp
deleted file mode 100644
index 090431db99..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-#include "precompiled.h"
-//
-// 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.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9
-// pointers retained by renderbuffers.
-
-#include "libGLESv2/renderer/d3d9/RenderTarget9.h"
-#include "libGLESv2/renderer/d3d9/Renderer9.h"
-
-#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
-#include "libGLESv2/main.h"
-
-namespace rx
-{
-
-RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface)
-{
- mRenderer = Renderer9::makeRenderer9(renderer);
- mRenderTarget = surface;
-
- if (mRenderTarget)
- {
- D3DSURFACE_DESC description;
- mRenderTarget->GetDesc(&description);
-
- mWidth = description.Width;
- mHeight = description.Height;
-
- mInternalFormat = d3d9_gl::GetEquivalentFormat(description.Format);
- mActualFormat = d3d9_gl::GetEquivalentFormat(description.Format);
- mSamples = d3d9_gl::GetSamplesFromMultisampleType(description.MultiSampleType);
- }
-}
-
-RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples)
-{
- mRenderer = Renderer9::makeRenderer9(renderer);
- mRenderTarget = NULL;
-
- D3DFORMAT requestedFormat = gl_d3d9::ConvertRenderbufferFormat(format);
- int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples);
-
- if (supportedSamples == -1)
- {
- gl::error(GL_OUT_OF_MEMORY);
-
- return;
- }
-
- HRESULT result = D3DERR_INVALIDCALL;
-
- if (width > 0 && height > 0)
- {
- if (requestedFormat == D3DFMT_D24S8)
- {
- result = mRenderer->getDevice()->CreateDepthStencilSurface(width, height, requestedFormat,
- gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples),
- 0, FALSE, &mRenderTarget, NULL);
- }
- else
- {
- result = mRenderer->getDevice()->CreateRenderTarget(width, height, requestedFormat,
- gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples),
- 0, FALSE, &mRenderTarget, NULL);
- }
-
- if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
- {
- gl::error(GL_OUT_OF_MEMORY);
-
- return;
- }
-
- ASSERT(SUCCEEDED(result));
- }
-
- mWidth = width;
- mHeight = height;
- mInternalFormat = format;
- mSamples = supportedSamples;
- mActualFormat = d3d9_gl::GetEquivalentFormat(requestedFormat);
-}
-
-RenderTarget9::~RenderTarget9()
-{
- if (mRenderTarget)
- {
- mRenderTarget->Release();
- }
-}
-
-RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target)
-{
- ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target));
- return static_cast<rx::RenderTarget9*>(target);
-}
-
-IDirect3DSurface9 *RenderTarget9::getSurface()
-{
- // Caller is responsible for releasing the returned surface reference.
- if (mRenderTarget)
- {
- mRenderTarget->AddRef();
- }
-
- return mRenderTarget;
-}
-
-} \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h
deleted file mode 100644
index 24fd2bdd84..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h
+++ /dev/null
@@ -1,356 +0,0 @@
-//
-// 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.
-//
-
-// Renderer9.h: Defines a back-end specific class for the D3D9 renderer.
-
-#ifndef LIBGLESV2_RENDERER_RENDERER9_H_
-#define LIBGLESV2_RENDERER_RENDERER9_H_
-
-#include "common/angleutils.h"
-#include "libGLESv2/mathutil.h"
-#include "libGLESv2/renderer/ShaderCache.h"
-#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-
-namespace gl
-{
-class Renderbuffer;
-}
-
-namespace rx
-{
-class VertexDataManager;
-class IndexDataManager;
-class StreamingIndexBufferInterface;
-struct TranslatedAttribute;
-
-class Renderer9 : public Renderer
-{
- public:
- Renderer9(egl::Display *display, HDC hDc, bool softwareDevice);
- virtual ~Renderer9();
-
- static Renderer9 *makeRenderer9(Renderer *renderer);
-
- virtual EGLint initialize();
- virtual bool resetDevice();
-
- virtual int generateConfigs(ConfigDesc **configDescList);
- virtual void deleteConfigs(ConfigDesc *configDescList);
-
- void startScene();
- void endScene();
-
- virtual void sync(bool block);
-
- virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
-
- IDirect3DQuery9* allocateEventQuery();
- void freeEventQuery(IDirect3DQuery9* query);
-
- // resource creation
- IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length);
- IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length);
- HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer);
- HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer);
-#if 0
- void *createTexture2D();
- void *createTextureCube();
- void *createQuery();
- void *createIndexBuffer();
- void *createVertexbuffer();
-
- // state setup
- void applyShaders();
- void applyConstants();
-#endif
- virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
- virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture);
-
- virtual void setRasterizerState(const gl::RasterizerState &rasterState);
- virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor,
- unsigned int sampleMask);
- virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
- int stencilBackRef, bool frontFaceCCW);
-
- virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
- virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
- bool ignoreViewport);
-
- virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
- virtual void applyShaders(gl::ProgramBinary *programBinary);
- virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray);
- virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount);
- virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances);
- virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
-
- virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances);
- virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
-
- virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
-
- virtual void markAllStateDirty();
-
- // lost device
- void notifyDeviceLost();
- virtual bool isDeviceLost();
- virtual bool testDeviceLost(bool notify);
- virtual bool testDeviceResettable();
-
- // Renderer capabilities
- IDirect3DDevice9 *getDevice() { return mDevice; }
- virtual DWORD getAdapterVendor() const;
- virtual std::string getRendererDescription() const;
- virtual GUID getAdapterIdentifier() const;
-
- virtual bool getBGRATextureSupport() const;
- virtual bool getDXT1TextureSupport();
- virtual bool getDXT3TextureSupport();
- virtual bool getDXT5TextureSupport();
- virtual bool getEventQuerySupport();
- virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable);
- virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable);
- virtual bool getLuminanceTextureSupport();
- virtual bool getLuminanceAlphaTextureSupport();
- virtual unsigned int getMaxVertexTextureImageUnits() const;
- virtual unsigned int getMaxCombinedTextureImageUnits() const;
- virtual unsigned int getReservedVertexUniformVectors() const;
- virtual unsigned int getReservedFragmentUniformVectors() const;
- virtual unsigned int getMaxVertexUniformVectors() const;
- virtual unsigned int getMaxFragmentUniformVectors() const;
- virtual unsigned int getMaxVaryingVectors() const;
- virtual bool getNonPower2TextureSupport() const;
- virtual bool getDepthTextureSupport() const;
- virtual bool getOcclusionQuerySupport() const;
- virtual bool getInstancingSupport() const;
- virtual bool getTextureFilterAnisotropySupport() const;
- virtual float getTextureMaxAnisotropy() const;
- virtual bool getShareHandleSupport() const;
- virtual bool getDerivativeInstructionSupport() const;
- virtual bool getPostSubBufferSupport() const;
-
- virtual int getMajorShaderModel() const;
- virtual float getMaxPointSize() const;
- virtual int getMaxViewportDimension() const;
- virtual int getMaxTextureWidth() const;
- virtual int getMaxTextureHeight() const;
- virtual bool get32BitIndexSupport() const;
- DWORD getCapsDeclTypes() const;
- virtual int getMinSwapInterval() const;
- virtual int getMaxSwapInterval() const;
-
- virtual GLsizei getMaxSupportedSamples() const;
- int getNearestSupportedSamples(D3DFORMAT format, int requested) const;
-
- virtual unsigned int getMaxRenderTargets() const;
-
- D3DFORMAT ConvertTextureInternalFormat(GLint internalformat);
-
- // Pixel operations
- virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source);
- virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source);
-
- virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level);
- virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level);
-
- virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
- bool blitRenderTarget, bool blitDepthStencil);
- virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
- GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels);
-
- // RenderTarget creation
- virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth);
- virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth);
-
- // Shader operations
- virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type);
- virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround);
-
- // Image operations
- virtual Image *createImage();
- virtual void generateMipmap(Image *dest, Image *source);
- virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
- virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
- virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
-
- // Buffer creation
- virtual VertexBuffer *createVertexBuffer();
- virtual IndexBuffer *createIndexBuffer();
- virtual BufferStorage *createBufferStorage();
-
- // Query and Fence creation
- virtual QueryImpl *createQuery(GLenum type);
- virtual FenceImpl *createFence();
-
- // D3D9-renderer specific methods
- bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
-
- D3DPOOL getTexturePool(DWORD usage) const;
-
- virtual bool getLUID(LUID *adapterLuid) const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Renderer9);
-
- void deinitialize();
-
- void applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v);
- void applyUniformniv(gl::Uniform *targetUniform, const GLint *v);
- void applyUniformnbv(gl::Uniform *targetUniform, const GLint *v);
-
- void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
- void drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
-
- void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
- bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
- gl::Renderbuffer *getNullColorbuffer(gl::Renderbuffer *depthbuffer);
-
- D3DPOOL getBufferPool(DWORD usage) const;
-
- HMODULE mD3d9Module;
- HDC mDc;
-
- void initializeDevice();
- D3DPRESENT_PARAMETERS getDefaultPresentParameters();
- void releaseDeviceResources();
-
- HRESULT getDeviceStatusCode();
- bool isRemovedDeviceResettable() const;
- bool resetRemovedDevice();
-
- UINT mAdapter;
- D3DDEVTYPE mDeviceType;
- bool mSoftwareDevice; // FIXME: Deprecate
- 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.
-
- Blit *mBlit;
-
- HWND mDeviceWindow;
-
- bool mDeviceLost;
- D3DCAPS9 mDeviceCaps;
- D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
-
- D3DPRIMITIVETYPE mPrimitiveType;
- int mPrimitiveCount;
- GLsizei mRepeatDraw;
-
- bool mSceneStarted;
- bool mSupportsNonPower2Textures;
- bool mSupportsTextureFilterAnisotropy;
- int mMinSwapInterval;
- int mMaxSwapInterval;
-
- bool mOcclusionQuerySupport;
- bool mEventQuerySupport;
- bool mVertexTextureSupport;
-
- bool mDepthTextureSupport;
-
- bool mFloat32TextureSupport;
- bool mFloat32FilterSupport;
- bool mFloat32RenderSupport;
-
- bool mFloat16TextureSupport;
- bool mFloat16FilterSupport;
- bool mFloat16RenderSupport;
-
- bool mDXT1TextureSupport;
- bool mDXT3TextureSupport;
- bool mDXT5TextureSupport;
-
- bool mLuminanceTextureSupport;
- bool mLuminanceAlphaTextureSupport;
-
- std::map<D3DFORMAT, bool *> mMultiSampleSupport;
- GLsizei mMaxSupportedSamples;
-
- // current render target states
- unsigned int mAppliedRenderTargetSerial;
- unsigned int mAppliedDepthbufferSerial;
- unsigned int mAppliedStencilbufferSerial;
- bool mDepthStencilInitialized;
- bool mRenderTargetDescInitialized;
- rx::RenderTarget::Desc mRenderTargetDesc;
- unsigned int mCurStencilSize;
- unsigned int mCurDepthSize;
-
- IDirect3DStateBlock9 *mMaskedClearSavedState;
-
- // previously set render states
- bool mForceSetDepthStencilState;
- gl::DepthStencilState mCurDepthStencilState;
- int mCurStencilRef;
- int mCurStencilBackRef;
- bool mCurFrontFaceCCW;
-
- bool mForceSetRasterState;
- gl::RasterizerState mCurRasterState;
-
- bool mForceSetScissor;
- gl::Rectangle mCurScissor;
- bool mScissorEnabled;
-
- bool mForceSetViewport;
- gl::Rectangle mCurViewport;
- float mCurNear;
- float mCurFar;
- float mCurDepthFront;
-
- bool mForceSetBlendState;
- gl::BlendState mCurBlendState;
- gl::Color mCurBlendColor;
- GLuint mCurSampleMask;
-
- // Currently applied sampler states
- bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
- gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-
- bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS];
- gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS];
-
- // Currently applied textures
- unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
- unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS];
-
- unsigned int mAppliedIBSerial;
- unsigned int mAppliedProgramBinarySerial;
-
- rx::dx_VertexConstants mVertexConstants;
- rx::dx_PixelConstants mPixelConstants;
- bool mDxUniformsDirty;
-
- // 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;
-
- enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 };
- struct NullColorbufferCacheEntry
- {
- UINT lruCount;
- int width;
- int height;
- gl::Renderbuffer *buffer;
- } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES];
- UINT mMaxNullColorbufferLRU;
-
-};
-
-}
-#endif // LIBGLESV2_RENDERER_RENDERER9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp
deleted file mode 100644
index 57f5bcd256..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp
+++ /dev/null
@@ -1,530 +0,0 @@
-#include "precompiled.h"
-//
-// 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 "libGLESv2/renderer/d3d9/VertexBuffer9.h"
-#include "libGLESv2/renderer/d3d9/vertexconversion.h"
-#include "libGLESv2/renderer/BufferStorage.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/renderer/d3d9/Renderer9.h"
-
-#include "libGLESv2/Buffer.h"
-
-namespace rx
-{
-
-bool VertexBuffer9::mTranslationsInitialized = false;
-VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
-
-VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer)
-{
- mVertexBuffer = NULL;
- mBufferSize = 0;
- mDynamicUsage = false;
-
- if (!mTranslationsInitialized)
- {
- initializeTranslations(renderer->getCapsDeclTypes());
- mTranslationsInitialized = true;
- }
-}
-
-VertexBuffer9::~VertexBuffer9()
-{
- if (mVertexBuffer)
- {
- mVertexBuffer->Release();
- mVertexBuffer = NULL;
- }
-}
-
-bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
-{
- if (mVertexBuffer)
- {
- mVertexBuffer->Release();
- mVertexBuffer = NULL;
- }
-
- updateSerial();
-
- if (size > 0)
- {
- DWORD flags = D3DUSAGE_WRITEONLY;
- if (dynamicUsage)
- {
- flags |= D3DUSAGE_DYNAMIC;
- }
-
- HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer);
-
- if (FAILED(result))
- {
- ERR("Out of memory allocating a vertex buffer of size %lu.", size);
- return false;
- }
- }
-
- mBufferSize = size;
- mDynamicUsage = dynamicUsage;
- return true;
-}
-
-VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer)
-{
- ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer));
- return static_cast<VertexBuffer9*>(vertexBuffer);
-}
-
-bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
- GLsizei instances, unsigned int offset)
-{
- if (mVertexBuffer)
- {
- gl::Buffer *buffer = attrib.mBoundBuffer.get();
-
- int inputStride = attrib.stride();
- int elementSize = attrib.typeSize();
- const FormatConverter &converter = formatConverter(attrib);
-
- DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
-
- void *mapPtr = NULL;
-
- unsigned int mapSize;
- if (!spaceRequired(attrib, count, instances, &mapSize))
- {
- return false;
- }
-
- HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags);
-
- if (FAILED(result))
- {
- ERR("Lock failed with error 0x%08x", result);
- return false;
- }
-
- const char *input = NULL;
- if (buffer)
- {
- BufferStorage *storage = buffer->getStorage();
- input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset);
- }
- else
- {
- input = static_cast<const char*>(attrib.mPointer);
- }
-
- if (instances == 0 || attrib.mDivisor == 0)
- {
- input += inputStride * start;
- }
-
- if (converter.identity && inputStride == elementSize)
- {
- memcpy(mapPtr, input, count * inputStride);
- }
- else
- {
- converter.convertArray(input, inputStride, count, mapPtr);
- }
-
- mVertexBuffer->Unlock();
-
- return true;
- }
- else
- {
- ERR("Vertex buffer not initialized.");
- return false;
- }
-}
-
-bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned int offset)
-{
- if (mVertexBuffer)
- {
- DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
-
- void *mapPtr = NULL;
- HRESULT result = mVertexBuffer->Lock(offset, size, &mapPtr, lockFlags);
-
- if (FAILED(result))
- {
- ERR("Lock failed with error 0x%08x", result);
- return false;
- }
-
- memcpy(mapPtr, data, size);
-
- mVertexBuffer->Unlock();
-
- return true;
- }
- else
- {
- ERR("Vertex buffer not initialized.");
- return false;
- }
-}
-
-bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
- unsigned int *outSpaceRequired) const
-{
- return spaceRequired(attrib, count, instances, outSpaceRequired);
-}
-
-bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const
-{
- return !formatConverter(attrib).identity;
-}
-
-unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const
-{
- unsigned int spaceRequired;
- return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0;
-}
-
-D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const
-{
- return formatConverter(attrib).d3dDeclType;
-}
-
-unsigned int VertexBuffer9::getBufferSize() const
-{
- return mBufferSize;
-}
-
-bool VertexBuffer9::setBufferSize(unsigned int size)
-{
- if (size > mBufferSize)
- {
- return initialize(size, mDynamicUsage);
- }
- else
- {
- return true;
- }
-}
-
-bool VertexBuffer9::discard()
-{
- if (mVertexBuffer)
- {
- void *dummy;
- HRESULT result;
-
- result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
- if (FAILED(result))
- {
- ERR("Discard lock failed with error 0x%08x", result);
- return false;
- }
-
- result = mVertexBuffer->Unlock();
- if (FAILED(result))
- {
- ERR("Discard unlock failed with error 0x%08x", result);
- return false;
- }
-
- return true;
- }
- else
- {
- ERR("Vertex buffer not initialized.");
- return false;
- }
-}
-
-IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
-{
- return mVertexBuffer;
-}
-
-// 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 };
-};
-
-// Initialize a TranslationInfo
-#define TRANSLATION(type, norm, size, preferred) \
- { \
- 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) }, \
- }
-
-const VertexBuffer9::TranslationDescription VertexBuffer9::mPossibleTranslations[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)
-};
-
-void VertexBuffer9::initializeTranslations(DWORD declTypes)
-{
- 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 (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
- {
- mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
- }
- else
- {
- mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
- }
- }
- }
- }
-}
-
-unsigned int VertexBuffer9::typeIndex(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 VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute)
-{
- return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
-}
-
-bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
- unsigned int *outSpaceRequired)
-{
- unsigned int elementSize = formatConverter(attrib).outputElementSize;
-
- if (attrib.mArrayEnabled)
- {
- unsigned int elementCount = 0;
- if (instances == 0 || attrib.mDivisor == 0)
- {
- elementCount = count;
- }
- else
- {
- if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1))
- {
- // Round up
- elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor;
- }
- else
- {
- elementCount = static_cast<unsigned int>(instances) / attrib.mDivisor;
- }
- }
-
- if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
- {
- if (outSpaceRequired)
- {
- *outSpaceRequired = elementSize * elementCount;
- }
- return true;
- }
- else
- {
- return false;
- }
- }
- else
- {
- const unsigned int elementSize = 4;
- if (outSpaceRequired)
- {
- *outSpaceRequired = elementSize * 4;
- }
- return true;
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h
deleted file mode 100644
index 2f88117bda..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h
+++ /dev/null
@@ -1,91 +0,0 @@
-//
-// 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 LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
-#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
-
-#include "libGLESv2/renderer/VertexBuffer.h"
-
-namespace rx
-{
-class Renderer9;
-
-class VertexBuffer9 : public VertexBuffer
-{
- public:
- explicit VertexBuffer9(rx::Renderer9 *const renderer);
- virtual ~VertexBuffer9();
-
- virtual bool initialize(unsigned int size, bool dynamicUsage);
-
- static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer);
-
- virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
- unsigned int offset);
- virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset);
-
- virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const;
-
- virtual bool requiresConversion(const gl::VertexAttribute &attrib) const;
-
- unsigned int getVertexSize(const gl::VertexAttribute &attrib) const;
- D3DDECLTYPE getDeclType(const gl::VertexAttribute &attrib) const;
-
- virtual unsigned int getBufferSize() const;
- virtual bool setBufferSize(unsigned int size);
- virtual bool discard();
-
- IDirect3DVertexBuffer9 *getBuffer() const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(VertexBuffer9);
-
- rx::Renderer9 *const mRenderer;
-
- IDirect3DVertexBuffer9 *mVertexBuffer;
- unsigned int mBufferSize;
- bool mDynamicUsage;
-
- // Attribute format conversion
- enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
-
- struct FormatConverter
- {
- bool identity;
- std::size_t outputElementSize;
- void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
- D3DDECLTYPE d3dDeclType;
- };
-
- static bool mTranslationsInitialized;
- static void initializeTranslations(DWORD declTypes);
-
- // [GL types as enumerated by typeIndex()][normalized][size - 1]
- static FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
-
- struct TranslationDescription
- {
- DWORD capsFlag;
- FormatConverter preferredConversion;
- FormatConverter fallbackConversion;
- };
-
- // This table is used to generate mFormatConverters.
- // [GL types as enumerated by typeIndex()][normalized][size - 1]
- static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
-
- static unsigned int typeIndex(GLenum type);
- static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute);
-
- static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
- unsigned int *outSpaceRequired);
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp
deleted file mode 100644
index b7f2ffb1d9..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp
+++ /dev/null
@@ -1,500 +0,0 @@
-#include "precompiled.h"
-//
-// 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.
-//
-
-// renderer9_utils.cpp: Conversion functions and other utility routines
-// specific to the D3D9 renderer.
-
-#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
-#include "libGLESv2/mathutil.h"
-#include "libGLESv2/Context.h"
-
-#include "common/debug.h"
-
-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::Color 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;
- 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 maxAnisotropy)
-{
- 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();
- }
-
- if (maxAnisotropy > 1.0f)
- {
- *d3dMinFilter = D3DTEXF_ANISOTROPIC;
- }
-}
-
-D3DFORMAT ConvertRenderbufferFormat(GLenum format)
-{
- switch (format)
- {
- case GL_NONE: return D3DFMT_NULL;
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGBA8_OES: return D3DFMT_A8R8G8B8;
- case GL_RGB565: return D3DFMT_R5G6B5;
- case GL_RGB8_OES: return D3DFMT_X8R8G8B8;
- case GL_DEPTH_COMPONENT16:
- case GL_STENCIL_INDEX8:
- case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
- default: UNREACHABLE(); return D3DFMT_A8R8G8B8;
- }
-}
-
-D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
-{
- if (samples <= 1)
- return D3DMULTISAMPLE_NONE;
- else
- return (D3DMULTISAMPLE_TYPE)samples;
-}
-
-}
-
-namespace d3d9_gl
-{
-
-unsigned int GetStencilSize(D3DFORMAT stencilFormat)
-{
- if (stencilFormat == D3DFMT_INTZ)
- {
- return 8;
- }
- switch(stencilFormat)
- {
- case D3DFMT_D24FS8:
- case D3DFMT_D24S8:
- return 8;
- case D3DFMT_D24X4S4:
- return 4;
- case D3DFMT_D15S1:
- return 1;
- case D3DFMT_D16_LOCKABLE:
- case D3DFMT_D32:
- case D3DFMT_D24X8:
- case D3DFMT_D32F_LOCKABLE:
- case D3DFMT_D16:
- return 0;
- //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
- //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
- default:
- return 0;
- }
-}
-
-unsigned int GetAlphaSize(D3DFORMAT colorFormat)
-{
- switch (colorFormat)
- {
- case D3DFMT_A16B16G16R16F:
- return 16;
- case D3DFMT_A32B32G32R32F:
- return 32;
- case D3DFMT_A2R10G10B10:
- return 2;
- case D3DFMT_A8R8G8B8:
- return 8;
- case D3DFMT_A1R5G5B5:
- return 1;
- case D3DFMT_X8R8G8B8:
- case D3DFMT_R5G6B5:
- return 0;
- default:
- return 0;
- }
-}
-
-GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
-{
- if (type == D3DMULTISAMPLE_NONMASKABLE)
- return 0;
- else
- return type;
-}
-
-bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
-{
- switch (d3dformat)
- {
- case D3DFMT_L8:
- return (format == GL_LUMINANCE);
- case D3DFMT_A8L8:
- return (format == GL_LUMINANCE_ALPHA);
- case D3DFMT_DXT1:
- return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
- case D3DFMT_DXT3:
- return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
- case D3DFMT_DXT5:
- return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
- case D3DFMT_A8R8G8B8:
- case D3DFMT_A16B16G16R16F:
- case D3DFMT_A32B32G32R32F:
- return (format == GL_RGBA || format == GL_BGRA_EXT);
- case D3DFMT_X8R8G8B8:
- return (format == GL_RGB);
- default:
- if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format))
- return true;
- return false;
- }
-}
-
-GLenum ConvertBackBufferFormat(D3DFORMAT format)
-{
- switch (format)
- {
- case D3DFMT_A4R4G4B4: return GL_RGBA4;
- case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
- case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
- case D3DFMT_R5G6B5: return GL_RGB565;
- case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
- default:
- UNREACHABLE();
- }
-
- return GL_RGBA4;
-}
-
-GLenum ConvertDepthStencilFormat(D3DFORMAT format)
-{
- if (format == D3DFMT_INTZ)
- {
- return GL_DEPTH24_STENCIL8_OES;
- }
- switch (format)
- {
- case D3DFMT_D16:
- case D3DFMT_D24X8:
- return GL_DEPTH_COMPONENT16;
- case D3DFMT_D24S8:
- return GL_DEPTH24_STENCIL8_OES;
- case D3DFMT_UNKNOWN:
- return GL_NONE;
- default:
- UNREACHABLE();
- }
-
- return GL_DEPTH24_STENCIL8_OES;
-}
-
-GLenum ConvertRenderTargetFormat(D3DFORMAT format)
-{
- if (format == D3DFMT_INTZ)
- {
- return GL_DEPTH24_STENCIL8_OES;
- }
-
- switch (format)
- {
- case D3DFMT_A4R4G4B4: return GL_RGBA4;
- case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
- case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
- case D3DFMT_R5G6B5: return GL_RGB565;
- case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
- case D3DFMT_D16:
- case D3DFMT_D24X8:
- return GL_DEPTH_COMPONENT16;
- case D3DFMT_D24S8:
- return GL_DEPTH24_STENCIL8_OES;
- case D3DFMT_UNKNOWN:
- return GL_NONE;
- default:
- UNREACHABLE();
- }
-
- return GL_RGBA4;
-}
-
-GLenum GetEquivalentFormat(D3DFORMAT format)
-{
- if (format == D3DFMT_INTZ)
- return GL_DEPTH24_STENCIL8_OES;
- if (format == D3DFMT_NULL)
- return GL_NONE;
-
- switch (format)
- {
- case D3DFMT_A4R4G4B4: return GL_RGBA4;
- case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
- case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
- case D3DFMT_R5G6B5: return GL_RGB565;
- case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
- case D3DFMT_D16: return GL_DEPTH_COMPONENT16;
- case D3DFMT_D24S8: return GL_DEPTH24_STENCIL8_OES;
- case D3DFMT_UNKNOWN: return GL_NONE;
- case D3DFMT_DXT1: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
- case D3DFMT_DXT3: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
- case D3DFMT_DXT5: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
- case D3DFMT_A32B32G32R32F: return GL_RGBA32F_EXT;
- case D3DFMT_A16B16G16R16F: return GL_RGBA16F_EXT;
- case D3DFMT_L8: return GL_LUMINANCE8_EXT;
- case D3DFMT_A8L8: return GL_LUMINANCE8_ALPHA8_EXT;
- default: UNREACHABLE();
- return GL_NONE;
- }
-}
-
-}
-
-namespace d3d9
-{
-
-bool IsCompressedFormat(D3DFORMAT surfaceFormat)
-{
- switch(surfaceFormat)
- {
- case D3DFMT_DXT1:
- case D3DFMT_DXT2:
- case D3DFMT_DXT3:
- case D3DFMT_DXT4:
- case D3DFMT_DXT5:
- return true;
- default:
- return false;
- }
-}
-
-size_t ComputeRowSize(D3DFORMAT format, unsigned int width)
-{
- if (format == D3DFMT_INTZ)
- {
- return 4 * width;
- }
- switch (format)
- {
- case D3DFMT_L8:
- return 1 * width;
- case D3DFMT_A8L8:
- return 2 * width;
- case D3DFMT_X8R8G8B8:
- case D3DFMT_A8R8G8B8:
- return 4 * width;
- case D3DFMT_A16B16G16R16F:
- return 8 * width;
- case D3DFMT_A32B32G32R32F:
- return 16 * width;
- case D3DFMT_DXT1:
- return 8 * ((width + 3) / 4);
- case D3DFMT_DXT3:
- case D3DFMT_DXT5:
- return 16 * ((width + 3) / 4);
- default:
- UNREACHABLE();
- return 0;
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps
deleted file mode 100644
index dcb3bd0e76..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// 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 mode : c0;
-
-// 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
-// Outputs sample(tex0, tc0).rrra.
-// For LA output (pass A) set C0.X = 1, C0.Y = 0.
-// For L output (A = 1) set C0.X = 0, C0.Y = 1.
-float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR
-{
- float4 tmp = tex2D(tex, texcoord.xy);
- tmp.w = tmp.w * mode.x + mode.y;
- return tmp.xxxw;
-};
-
-// RGB/A Component Mask Pixel Shader
-// Outputs sample(tex0, tc0) with options to force RGB = 0 and/or A = 1.
-// To force RGB = 0, set C0.X = 0, otherwise C0.X = 1.
-// To force A = 1, set C0.Z = 0, C0.W = 1, otherwise C0.Z = 1, C0.W = 0.
-float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR
-{
- float4 tmp = tex2D(tex, texcoord.xy);
- tmp.xyz = tmp.xyz * mode.x;
- tmp.w = tmp.w * mode.z + mode.w;
- return tmp;
-};
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h
index 8e1973605b..a57b00d444 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// 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.
//
@@ -10,194 +10,19 @@
#ifndef LIBGLESV2_RENDERER_GENERATEMIP_H_
#define LIBGLESV2_RENDERER_GENERATEMIP_H_
-#include "libGLESv2/mathutil.h"
+#include "libGLESv2/renderer/imageformats.h"
+#include "libGLESv2/angletypes.h"
namespace rx
{
-struct L8
-{
- unsigned char L;
-
- static void average(L8 *dst, const L8 *src1, const L8 *src2)
- {
- dst->L = ((src1->L ^ src2->L) >> 1) + (src1->L & src2->L);
- }
-};
-
-typedef L8 R8; // R8 type is functionally equivalent for mip purposes
-typedef L8 A8; // A8 type is functionally equivalent for mip purposes
-
-struct A8L8
-{
- unsigned char L;
- unsigned char A;
-
- static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2)
- {
- *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2);
- }
-};
-
-typedef A8L8 R8G8; // R8G8 type is functionally equivalent for mip purposes
-
-struct A8R8G8B8
-{
- unsigned char B;
- unsigned char G;
- unsigned char R;
- unsigned char A;
-
- static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2)
- {
- *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2);
- }
-};
-
-typedef A8R8G8B8 R8G8B8A8; // R8G8B8A8 type is functionally equivalent for mip purposes
-
-struct A16B16G16R16F
-{
- unsigned short R;
- unsigned short G;
- unsigned short B;
- unsigned short A;
-
- static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2)
- {
- dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f);
- dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f);
- dst->B = gl::float32ToFloat16((gl::float16ToFloat32(src1->B) + gl::float16ToFloat32(src2->B)) * 0.5f);
- dst->A = gl::float32ToFloat16((gl::float16ToFloat32(src1->A) + gl::float16ToFloat32(src2->A)) * 0.5f);
- }
-};
-
-struct R16F
-{
- unsigned short R;
-
- static void average(R16F *dst, const R16F *src1, const R16F *src2)
- {
- dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f);
- }
-};
-
-struct R16G16F
-{
- unsigned short R;
- unsigned short G;
-
- static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2)
- {
- dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f);
- dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f);
- }
-};
-
-struct A32B32G32R32F
-{
- float R;
- float G;
- float B;
- float A;
-
- static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2)
- {
- dst->R = (src1->R + src2->R) * 0.5f;
- dst->G = (src1->G + src2->G) * 0.5f;
- dst->B = (src1->B + src2->B) * 0.5f;
- dst->A = (src1->A + src2->A) * 0.5f;
- }
-};
-
-struct R32F
-{
- float R;
-
- static void average(R32F *dst, const R32F *src1, const R32F *src2)
- {
- dst->R = (src1->R + src2->R) * 0.5f;
- }
-};
-
-struct R32G32F
-{
- float R;
- float G;
-
- static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2)
- {
- dst->R = (src1->R + src2->R) * 0.5f;
- dst->G = (src1->G + src2->G) * 0.5f;
- }
-};
-
-struct R32G32B32F
-{
- float R;
- float G;
- float B;
-
- static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2)
- {
- dst->R = (src1->R + src2->R) * 0.5f;
- dst->G = (src1->G + src2->G) * 0.5f;
- dst->B = (src1->B + src2->B) * 0.5f;
- }
-};
template <typename T>
-static void GenerateMip(unsigned int sourceWidth, unsigned int sourceHeight,
- const unsigned char *sourceData, int sourcePitch,
- unsigned char *destData, int destPitch)
-{
- unsigned int mipWidth = std::max(1U, sourceWidth >> 1);
- unsigned int mipHeight = std::max(1U, sourceHeight >> 1);
-
- if (sourceHeight == 1)
- {
- ASSERT(sourceWidth != 1);
-
- const T *src = (const T*)sourceData;
- T *dst = (T*)destData;
-
- for (unsigned int x = 0; x < mipWidth; x++)
- {
- T::average(&dst[x], &src[x * 2], &src[x * 2 + 1]);
- }
- }
- else if (sourceWidth == 1)
- {
- ASSERT(sourceHeight != 1);
+inline void GenerateMip(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);
- for (unsigned int y = 0; y < mipHeight; y++)
- {
- const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch);
- const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch);
- T *dst = (T*)(destData + y * destPitch);
-
- T::average(dst, src0, src1);
- }
- }
- else
- {
- for (unsigned int y = 0; y < mipHeight; y++)
- {
- const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch);
- const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch);
- T *dst = (T*)(destData + y * destPitch);
-
- for (unsigned int x = 0; x < mipWidth; x++)
- {
- T tmp0;
- T tmp1;
-
- T::average(&tmp0, &src0[x * 2], &src0[x * 2 + 1]);
- T::average(&tmp1, &src1[x * 2], &src1[x * 2 + 1]);
- T::average(&dst[x], &tmp0, &tmp1);
- }
- }
- }
-}
}
+#include "generatemip.inl"
+
#endif // LIBGLESV2_RENDERER_GENERATEMIP_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl
new file mode 100644
index 0000000000..6788a42f03
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl
@@ -0,0 +1,266 @@
+//
+// 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.
+//
+
+// generatemip.inl: Defines the GenerateMip function, templated on the format
+// type of the image for which mip levels are being generated.
+
+#include "common/mathutil.h"
+
+namespace rx
+{
+
+namespace priv
+{
+
+template <typename T>
+static inline T *GetPixel(uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
+{
+ return reinterpret_cast<T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch));
+}
+
+template <typename T>
+static inline const T *GetPixel(const uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
+{
+ return reinterpret_cast<const T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch));
+}
+
+template <typename T>
+static void GenerateMip_Y(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth == 1);
+ ASSERT(sourceHeight > 1);
+ ASSERT(sourceDepth == 1);
+
+ for (size_t y = 0; y < destHeight; y++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, 0, y * 2, 0, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, 0, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, 0, y, 0, destRowPitch, destDepthPitch);
+
+ T::average(dst, src0, src1);
+ }
+}
+
+template <typename T>
+static void GenerateMip_X(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth > 1);
+ ASSERT(sourceHeight == 1);
+ ASSERT(sourceDepth == 1);
+
+ for (size_t x = 0; x < destWidth; x++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, x * 2, 0, 0, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, x * 2 + 1, 0, 0, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, x, 0, 0, destRowPitch, destDepthPitch);
+
+ T::average(dst, src0, src1);
+ }
+}
+
+template <typename T>
+static void GenerateMip_Z(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth == 1);
+ ASSERT(sourceHeight == 1);
+ ASSERT(sourceDepth > 1);
+
+ for (size_t z = 0; z < destDepth; z++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, 0, 0, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, 0, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, 0, 0, z, destRowPitch, destDepthPitch);
+
+ T::average(dst, src0, src1);
+ }
+}
+
+template <typename T>
+static void GenerateMip_XY(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth > 1);
+ ASSERT(sourceHeight > 1);
+ ASSERT(sourceDepth == 1);
+
+ for (size_t y = 0; y < destHeight; y++)
+ {
+ for (size_t x = 0; x < destWidth; x++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, 0, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
+ const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, 0, sourceRowPitch, sourceDepthPitch);
+ const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, x, y, 0, destRowPitch, destDepthPitch);
+
+ T tmp0, tmp1;
+
+ T::average(&tmp0, src0, src1);
+ T::average(&tmp1, src2, src3);
+ T::average(dst, &tmp0, &tmp1);
+ }
+ }
+}
+
+template <typename T>
+static void GenerateMip_YZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth == 1);
+ ASSERT(sourceHeight > 1);
+ ASSERT(sourceDepth > 1);
+
+ for (size_t z = 0; z < destDepth; z++)
+ {
+ for (size_t y = 0; y < destHeight; y++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, 0, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, 0, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ const T *src2 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src3 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, 0, y, z, destRowPitch, destDepthPitch);
+
+ T tmp0, tmp1;
+
+ T::average(&tmp0, src0, src1);
+ T::average(&tmp1, src2, src3);
+ T::average(dst, &tmp0, &tmp1);
+ }
+ }
+}
+
+template <typename T>
+static void GenerateMip_XZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth > 1);
+ ASSERT(sourceHeight == 1);
+ ASSERT(sourceDepth > 1);
+
+ for (size_t z = 0; z < destDepth; z++)
+ {
+ for (size_t x = 0; x < destWidth; x++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, x * 2, 0, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, x * 2, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, x, 0, z, destRowPitch, destDepthPitch);
+
+ T tmp0, tmp1;
+
+ T::average(&tmp0, src0, src1);
+ T::average(&tmp1, src2, src3);
+ T::average(dst, &tmp0, &tmp1);
+ }
+ }
+}
+
+template <typename T>
+static void GenerateMip_XYZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth > 1);
+ ASSERT(sourceHeight > 1);
+ ASSERT(sourceDepth > 1);
+
+ for (size_t z = 0; z < destDepth; z++)
+ {
+ for (size_t y = 0; y < destHeight; y++)
+ {
+ for (size_t x = 0; x < destWidth; x++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ const T *src2 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src3 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ const T *src4 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src5 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ const T *src6 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src7 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, x, y, z, destRowPitch, destDepthPitch);
+
+ T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+
+ T::average(&tmp0, src0, src1);
+ T::average(&tmp1, src2, src3);
+ T::average(&tmp2, src4, src5);
+ T::average(&tmp3, src6, src7);
+
+ T::average(&tmp4, &tmp0, &tmp1);
+ T::average(&tmp5, &tmp2, &tmp3);
+
+ T::average(dst, &tmp4, &tmp5);
+ }
+ }
+ }
+}
+
+
+typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch);
+
+template <typename T>
+static MipGenerationFunction GetMipGenerationFunction(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth)
+{
+ uint8_t index = ((sourceWidth > 1) ? 1 : 0) |
+ ((sourceHeight > 1) ? 2 : 0) |
+ ((sourceDepth > 1) ? 4 : 0);
+
+ switch (index)
+ {
+ case 0: return NULL;
+ case 1: return GenerateMip_X<T>; // W x 1 x 1
+ case 2: return GenerateMip_Y<T>; // 1 x H x 1
+ case 3: return GenerateMip_XY<T>; // W x H x 1
+ case 4: return GenerateMip_Z<T>; // 1 x 1 x D
+ case 5: return GenerateMip_XZ<T>; // W x 1 x D
+ case 6: return GenerateMip_YZ<T>; // 1 x H x D
+ case 7: return GenerateMip_XYZ<T>; // W x H x D
+ }
+
+ UNREACHABLE();
+ return NULL;
+}
+
+}
+
+template <typename T>
+inline void GenerateMip(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)
+{
+ size_t mipWidth = std::max<size_t>(1, sourceWidth >> 1);
+ size_t mipHeight = std::max<size_t>(1, sourceHeight >> 1);
+ size_t mipDepth = std::max<size_t>(1, sourceDepth >> 1);
+
+ priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction<T>(sourceWidth, sourceHeight, sourceDepth);
+ ASSERT(generationFunction != NULL);
+
+ generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch,
+ mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h b/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h
new file mode 100644
index 0000000000..2140a9ee72
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h
@@ -0,0 +1,2029 @@
+//
+// 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.
+//
+
+// imageformats.h: Defines image format types with functions for mip generation
+// and copying.
+
+#ifndef LIBGLESV2_RENDERER_IMAGEFORMATS_H_
+#define LIBGLESV2_RENDERER_IMAGEFORMATS_H_
+
+#include "common/mathutil.h"
+
+namespace rx
+{
+
+// Several structures share functionality for reading, writing or mipmapping but the layout
+// must match the texture format which the structure represents. If collapsing or typedefing
+// structs in this header, make sure the functionality and memory layout is exactly the same.
+
+struct L8
+{
+ unsigned char L;
+
+ static void readColor(gl::ColorF *dst, const L8 *src)
+ {
+ const float lum = gl::normalizedToFloat(src->L);
+ dst->red = lum;
+ dst->green = lum;
+ dst->blue = lum;
+ dst->alpha = 1.0f;
+ }
+
+ static void writeColor(L8 *dst, const gl::ColorF *src)
+ {
+ dst->L = gl::floatToNormalized<unsigned char>((src->red + src->green + src->blue) / 3.0f);
+ }
+
+ static void average(L8 *dst, const L8 *src1, const L8 *src2)
+ {
+ dst->L = gl::average(src1->L, src2->L);
+ }
+};
+
+struct R8
+{
+ unsigned char R;
+
+ static void readColor(gl::ColorF *dst, const R8 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorUI *dst, const R8 *src)
+ {
+ dst->red = src->R;
+ dst->green = 0;
+ dst->blue = 0;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R8 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned char>(src->red);
+ }
+
+ static void writeColor(R8 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned char>(src->red);
+ }
+
+ static void average(R8 *dst, const R8 *src1, const R8 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ }
+};
+
+struct A8
+{
+ unsigned char A;
+
+ static void readColor(gl::ColorF *dst, const A8 *src)
+ {
+ dst->red = 0.0f;
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = gl::normalizedToFloat(src->A);
+ }
+
+ static void writeColor(A8 *dst, const gl::ColorF *src)
+ {
+ dst->A = gl::floatToNormalized<unsigned char>(src->alpha);
+ }
+
+ static void average(A8 *dst, const A8 *src1, const A8 *src2)
+ {
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct L8A8
+{
+ unsigned char L;
+ unsigned char A;
+
+ static void readColor(gl::ColorF *dst, const L8A8 *src)
+ {
+ const float lum = gl::normalizedToFloat(src->L);
+ dst->red = lum;
+ dst->green = lum;
+ dst->blue = lum;
+ dst->alpha = gl::normalizedToFloat(src->A);
+ }
+
+ static void writeColor(L8A8 *dst, const gl::ColorF *src)
+ {
+ dst->L = gl::floatToNormalized<unsigned char>((src->red + src->green + src->blue) / 3.0f);
+ dst->A = gl::floatToNormalized<unsigned char>(src->alpha);
+ }
+
+ static void average(L8A8 *dst, const L8A8 *src1, const L8A8 *src2)
+ {
+ *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2);
+ }
+};
+
+struct A8L8
+{
+ unsigned char A;
+ unsigned char L;
+
+ static void readColor(gl::ColorF *dst, const A8L8 *src)
+ {
+ const float lum = gl::normalizedToFloat(src->L);
+ dst->red = lum;
+ dst->green = lum;
+ dst->blue = lum;
+ dst->alpha = gl::normalizedToFloat(src->A);
+ }
+
+ static void writeColor(A8L8 *dst, const gl::ColorF *src)
+ {
+ dst->L = gl::floatToNormalized<unsigned char>((src->red + src->green + src->blue) / 3.0f);
+ dst->A = gl::floatToNormalized<unsigned char>(src->alpha);
+ }
+
+ static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2)
+ {
+ *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2);
+ }
+};
+
+struct R8G8
+{
+ unsigned char R;
+ unsigned char G;
+
+ static void readColor(gl::ColorF *dst, const R8G8 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorUI *dst, const R8G8 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R8G8 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned char>(src->red);
+ dst->G = gl::floatToNormalized<unsigned char>(src->green);
+ }
+
+ static void writeColor(R8G8 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned char>(src->red);
+ dst->G = static_cast<unsigned char>(src->green);
+ }
+
+ static void average(R8G8 *dst, const R8G8 *src1, const R8G8 *src2)
+ {
+ *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2);
+ }
+};
+
+struct R8G8B8
+{
+ unsigned char R;
+ unsigned char G;
+ unsigned char B;
+
+ static void readColor(gl::ColorF *dst, const R8G8B8 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorUI *dst, const R8G8B8 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->G;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R8G8B8 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned char>(src->red);
+ dst->G = gl::floatToNormalized<unsigned char>(src->green);
+ dst->B = gl::floatToNormalized<unsigned char>(src->blue);
+ }
+
+ static void writeColor(R8G8B8 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned char>(src->red);
+ dst->G = static_cast<unsigned char>(src->green);
+ dst->B = static_cast<unsigned char>(src->blue);
+ }
+
+ static void average(R8G8B8 *dst, const R8G8B8 *src1, const R8G8B8 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ }
+};
+
+struct B8G8R8
+{
+ unsigned char B;
+ unsigned char G;
+ unsigned char R;
+
+ static void readColor(gl::ColorF *dst, const B8G8R8 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorUI *dst, const B8G8R8 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->G;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(B8G8R8 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned char>(src->red);
+ dst->G = gl::floatToNormalized<unsigned char>(src->green);
+ dst->B = gl::floatToNormalized<unsigned char>(src->blue);
+ }
+
+ static void writeColor(B8G8R8 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned char>(src->red);
+ dst->G = static_cast<unsigned char>(src->green);
+ dst->B = static_cast<unsigned char>(src->blue);
+ }
+
+ static void average(B8G8R8 *dst, const B8G8R8 *src1, const B8G8R8 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ }
+};
+
+struct R5G6B5
+{
+ unsigned short RGB;
+
+ static void readColor(gl::ColorF *dst, const R5G6B5 *src)
+ {
+ dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGB));
+ dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->RGB));
+ dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGB));
+ dst->alpha = 1.0f;
+ }
+
+ static void writeColor(R5G6B5 *dst, const gl::ColorF *src)
+ {
+ dst->RGB = gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red)) |
+ gl::shiftData<6, 5>(gl::floatToNormalized<6, unsigned short>(src->green)) |
+ gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue));
+ }
+
+ static void average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2)
+ {
+ dst->RGB = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGB), gl::getShiftedData<5, 11>(src2->RGB))) |
+ gl::shiftData<6, 5>(gl::average(gl::getShiftedData<6, 5>(src1->RGB), gl::getShiftedData<6, 5>(src2->RGB))) |
+ gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGB), gl::getShiftedData<5, 0>(src2->RGB)));
+ }
+};
+
+struct A8R8G8B8
+{
+ unsigned char A;
+ unsigned char R;
+ unsigned char G;
+ unsigned char B;
+
+ static void readColor(gl::ColorF *dst, const A8R8G8B8 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+ }
+
+ static void readColor(gl::ColorUI *dst, const A8R8G8B8 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(A8R8G8B8 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned char>(src->red);
+ dst->G = gl::floatToNormalized<unsigned char>(src->green);
+ dst->B = gl::floatToNormalized<unsigned char>(src->blue);
+ dst->A = gl::floatToNormalized<unsigned char>(src->alpha);
+ }
+
+ static void writeColor(A8R8G8B8 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned char>(src->red);
+ dst->G = static_cast<unsigned char>(src->green);
+ dst->B = static_cast<unsigned char>(src->blue);
+ dst->A = static_cast<unsigned char>(src->alpha);
+ }
+
+ static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2)
+ {
+ *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2);
+ }
+};
+
+struct R8G8B8A8
+{
+ unsigned char R;
+ unsigned char G;
+ unsigned char B;
+ unsigned char A;
+
+ static void readColor(gl::ColorF *dst, const R8G8B8A8 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+ }
+
+ static void readColor(gl::ColorUI *dst, const R8G8B8A8 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(R8G8B8A8 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned char>(src->red);
+ dst->G = gl::floatToNormalized<unsigned char>(src->green);
+ dst->B = gl::floatToNormalized<unsigned char>(src->blue);
+ dst->A = gl::floatToNormalized<unsigned char>(src->alpha);
+ }
+
+ static void writeColor(R8G8B8A8 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned char>(src->red);
+ dst->G = static_cast<unsigned char>(src->green);
+ dst->B = static_cast<unsigned char>(src->blue);
+ dst->A = static_cast<unsigned char>(src->alpha);
+ }
+
+ static void average(R8G8B8A8 *dst, const R8G8B8A8 *src1, const R8G8B8A8 *src2)
+ {
+ *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2);
+ }
+};
+
+struct B8G8R8A8
+{
+ unsigned char B;
+ unsigned char G;
+ unsigned char R;
+ unsigned char A;
+
+ static void readColor(gl::ColorF *dst, const B8G8R8A8 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+ }
+
+ static void readColor(gl::ColorUI *dst, const B8G8R8A8 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(B8G8R8A8 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned char>(src->red);
+ dst->G = gl::floatToNormalized<unsigned char>(src->green);
+ dst->B = gl::floatToNormalized<unsigned char>(src->blue);
+ dst->A = gl::floatToNormalized<unsigned char>(src->alpha);
+ }
+
+ static void writeColor(B8G8R8A8 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned char>(src->red);
+ dst->G = static_cast<unsigned char>(src->green);
+ dst->B = static_cast<unsigned char>(src->blue);
+ dst->A = static_cast<unsigned char>(src->alpha);
+ }
+
+ static void average(B8G8R8A8 *dst, const B8G8R8A8 *src1, const B8G8R8A8 *src2)
+ {
+ *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2);
+ }
+};
+
+struct B8G8R8X8
+{
+ unsigned char B;
+ unsigned char G;
+ unsigned char R;
+ unsigned char X;
+
+ static void readColor(gl::ColorF *dst, const B8G8R8X8 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorUI *dst, const B8G8R8X8 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(B8G8R8X8 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned char>(src->red);
+ dst->G = gl::floatToNormalized<unsigned char>(src->green);
+ dst->B = gl::floatToNormalized<unsigned char>(src->blue);
+ dst->X = 255;
+ }
+
+ static void writeColor(B8G8R8X8 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned char>(src->red);
+ dst->G = static_cast<unsigned char>(src->green);
+ dst->B = static_cast<unsigned char>(src->blue);
+ dst->X = 255;
+ }
+
+ static void average(B8G8R8X8 *dst, const B8G8R8X8 *src1, const B8G8R8X8 *src2)
+ {
+ *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2);
+ dst->X = 255;
+ }
+};
+
+struct B5G5R5A1
+{
+ unsigned short BGRA;
+
+ static void readColor(gl::ColorF *dst, const B5G5R5A1 *src)
+ {
+ dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->BGRA));
+ dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->BGRA));
+ dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->BGRA));
+ dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->BGRA));
+ }
+
+ static void writeColor(B5G5R5A1 *dst, const gl::ColorF *src)
+ {
+ dst->BGRA = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) |
+ gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->red)) |
+ gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) |
+ gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue));
+ }
+
+ static void average(B5G5R5A1 *dst, const B5G5R5A1 *src1, const B5G5R5A1 *src2)
+ {
+ dst->BGRA = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->BGRA), gl::getShiftedData<1, 15>(src2->BGRA))) |
+ gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->BGRA), gl::getShiftedData<5, 10>(src2->BGRA))) |
+ gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->BGRA), gl::getShiftedData<5, 5>(src2->BGRA))) |
+ gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->BGRA), gl::getShiftedData<5, 0>(src2->BGRA)));
+ }
+};
+
+struct R5G5B5A1
+{
+ unsigned short RGBA;
+
+ static void readColor(gl::ColorF *dst, const R5G5B5A1 *src)
+ {
+ dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->RGBA));
+ dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->RGBA));
+ dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->RGBA));
+ dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGBA));
+ }
+
+ static void writeColor(R5G5B5A1 *dst, const gl::ColorF *src)
+ {
+ dst->RGBA = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) |
+ gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->blue)) |
+ gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) |
+ gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->red));
+ }
+
+ static void average(R5G5B5A1 *dst, const R5G5B5A1 *src1, const R5G5B5A1 *src2)
+ {
+ dst->RGBA = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->RGBA), gl::getShiftedData<1, 15>(src2->RGBA))) |
+ gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->RGBA), gl::getShiftedData<5, 10>(src2->RGBA))) |
+ gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->RGBA), gl::getShiftedData<5, 5>(src2->RGBA))) |
+ gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGBA), gl::getShiftedData<5, 0>(src2->RGBA)));
+ }
+};
+
+struct R4G4B4A4
+{
+ unsigned char R : 4;
+ unsigned char G : 4;
+ unsigned char B : 4;
+ unsigned char A : 4;
+
+ static void readColor(gl::ColorF *dst, const R4G4B4A4 *src)
+ {
+ dst->red = gl::normalizedToFloat<4>(src->R);
+ dst->green = gl::normalizedToFloat<4>(src->G);
+ dst->blue = gl::normalizedToFloat<4>(src->B);
+ dst->alpha = gl::normalizedToFloat<4>(src->A);
+ }
+
+ static void writeColor(R4G4B4A4 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<4, unsigned char>(src->red);
+ dst->G = gl::floatToNormalized<4, unsigned char>(src->green);
+ dst->B = gl::floatToNormalized<4, unsigned char>(src->blue);
+ dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha);
+ }
+
+ static void average(R4G4B4A4 *dst, const R4G4B4A4 *src1, const R4G4B4A4 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct A4R4G4B4
+{
+ unsigned char A : 4;
+ unsigned char R : 4;
+ unsigned char G : 4;
+ unsigned char B : 4;
+
+ static void readColor(gl::ColorF *dst, const A4R4G4B4 *src)
+ {
+ dst->red = gl::normalizedToFloat<4>(src->R);
+ dst->green = gl::normalizedToFloat<4>(src->G);
+ dst->blue = gl::normalizedToFloat<4>(src->B);
+ dst->alpha = gl::normalizedToFloat<4>(src->A);
+ }
+
+ static void writeColor(A4R4G4B4 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<4, unsigned char>(src->red);
+ dst->G = gl::floatToNormalized<4, unsigned char>(src->green);
+ dst->B = gl::floatToNormalized<4, unsigned char>(src->blue);
+ dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha);
+ }
+
+ static void average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct B4G4R4A4
+{
+ unsigned char B : 4;
+ unsigned char G : 4;
+ unsigned char R : 4;
+ unsigned char A : 4;
+
+ static void readColor(gl::ColorF *dst, const B4G4R4A4 *src)
+ {
+ dst->red = gl::normalizedToFloat<4>(src->R);
+ dst->green = gl::normalizedToFloat<4>(src->G);
+ dst->blue = gl::normalizedToFloat<4>(src->B);
+ dst->alpha = gl::normalizedToFloat<4>(src->A);
+ }
+
+ static void writeColor(B4G4R4A4 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<4, unsigned char>(src->red);
+ dst->G = gl::floatToNormalized<4, unsigned char>(src->green);
+ dst->B = gl::floatToNormalized<4, unsigned char>(src->blue);
+ dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha);
+ }
+
+ static void average(B4G4R4A4 *dst, const B4G4R4A4 *src1, const B4G4R4A4 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct R16
+{
+ unsigned short R;
+
+ static void readColor(gl::ColorF *dst, const R16 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorUI *dst, const R16 *src)
+ {
+ dst->red = src->R;
+ dst->green = 0;
+ dst->blue = 0;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R16 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned short>(src->red);
+ }
+
+ static void writeColor(R16 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned short>(src->red);
+ }
+
+ static void average(R16 *dst, const R16 *src1, const R16 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ }
+};
+
+struct R16G16
+{
+ unsigned short R;
+ unsigned short G;
+
+ static void readColor(gl::ColorF *dst, const R16G16 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorUI *dst, const R16G16 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R16G16 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned short>(src->red);
+ dst->G = gl::floatToNormalized<unsigned short>(src->green);
+ }
+
+ static void writeColor(R16G16 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned short>(src->red);
+ dst->G = static_cast<unsigned short>(src->green);
+ }
+
+ static void average(R16G16 *dst, const R16G16 *src1, const R16G16 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ }
+};
+
+struct R16G16B16
+{
+ unsigned short R;
+ unsigned short G;
+ unsigned short B;
+
+ static void readColor(gl::ColorF *dst, const R16G16B16 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorUI *dst, const R16G16B16 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R16G16B16 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned short>(src->red);
+ dst->G = gl::floatToNormalized<unsigned short>(src->green);
+ dst->B = gl::floatToNormalized<unsigned short>(src->blue);
+ }
+
+ static void writeColor(R16G16B16 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned short>(src->red);
+ dst->G = static_cast<unsigned short>(src->green);
+ dst->B = static_cast<unsigned short>(src->blue);
+ }
+
+ static void average(R16G16B16 *dst, const R16G16B16 *src1, const R16G16B16 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ }
+};
+
+struct R16G16B16A16
+{
+ unsigned short R;
+ unsigned short G;
+ unsigned short B;
+ unsigned short A;
+
+ static void readColor(gl::ColorF *dst, const R16G16B16A16 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+ }
+
+ static void readColor(gl::ColorUI *dst, const R16G16B16A16 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(R16G16B16A16 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned short>(src->red);
+ dst->G = gl::floatToNormalized<unsigned short>(src->green);
+ dst->B = gl::floatToNormalized<unsigned short>(src->blue);
+ dst->A = gl::floatToNormalized<unsigned short>(src->alpha);
+ }
+
+ static void writeColor(R16G16B16A16 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned short>(src->red);
+ dst->G = static_cast<unsigned short>(src->green);
+ dst->B = static_cast<unsigned short>(src->blue);
+ dst->A = static_cast<unsigned short>(src->alpha);
+ }
+
+ static void average(R16G16B16A16 *dst, const R16G16B16A16 *src1, const R16G16B16A16 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct R32
+{
+ unsigned int R;
+
+ static void readColor(gl::ColorF *dst, const R32 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorUI *dst, const R32 *src)
+ {
+ dst->red = src->R;
+ dst->green = 0;
+ dst->blue = 0;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R32 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned int>(src->red);
+ }
+
+ static void writeColor(R32 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned int>(src->red);
+ }
+
+ static void average(R32 *dst, const R32 *src1, const R32 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ }
+};
+
+struct R32G32
+{
+ unsigned int R;
+ unsigned int G;
+
+ static void readColor(gl::ColorF *dst, const R32G32 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorUI *dst, const R32G32 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R32G32 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned int>(src->red);
+ dst->G = gl::floatToNormalized<unsigned int>(src->green);
+ }
+
+ static void writeColor(R32G32 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned int>(src->red);
+ dst->G = static_cast<unsigned int>(src->green);
+ }
+
+ static void average(R32G32 *dst, const R32G32 *src1, const R32G32 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ }
+};
+
+struct R32G32B32
+{
+ unsigned int R;
+ unsigned int G;
+ unsigned int B;
+
+ static void readColor(gl::ColorF *dst, const R32G32B32 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorUI *dst, const R32G32B32 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R32G32B32 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned int>(src->red);
+ dst->G = gl::floatToNormalized<unsigned int>(src->green);
+ dst->B = gl::floatToNormalized<unsigned int>(src->blue);
+ }
+
+ static void writeColor(R32G32B32 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned int>(src->red);
+ dst->G = static_cast<unsigned int>(src->green);
+ dst->B = static_cast<unsigned int>(src->blue);
+ }
+
+ static void average(R32G32B32 *dst, const R32G32B32 *src1, const R32G32B32 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ }
+};
+
+struct R32G32B32A32
+{
+ unsigned int R;
+ unsigned int G;
+ unsigned int B;
+ unsigned int A;
+
+ static void readColor(gl::ColorF *dst, const R32G32B32A32 *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+ }
+
+ static void readColor(gl::ColorUI *dst, const R32G32B32A32 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(R32G32B32A32 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<unsigned int>(src->red);
+ dst->G = gl::floatToNormalized<unsigned int>(src->green);
+ dst->B = gl::floatToNormalized<unsigned int>(src->blue);
+ dst->A = gl::floatToNormalized<unsigned int>(src->alpha);
+ }
+
+ static void writeColor(R32G32B32A32 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned int>(src->red);
+ dst->G = static_cast<unsigned int>(src->green);
+ dst->B = static_cast<unsigned int>(src->blue);
+ dst->A = static_cast<unsigned int>(src->alpha);
+ }
+
+ static void average(R32G32B32A32 *dst, const R32G32B32A32 *src1, const R32G32B32A32 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct R8S
+{
+ char R;
+
+ static void readColor(gl::ColorF *dst, const R8S *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorI *dst, const R8S *src)
+ {
+ dst->red = src->R;
+ dst->green = 0;
+ dst->blue = 0;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R8S *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<char>(src->red);
+ }
+
+ static void writeColor(R8S *dst, const gl::ColorI *src)
+ {
+ dst->R = static_cast<char>(src->red);
+ }
+
+ static void average(R8S *dst, const R8S *src1, const R8S *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ }
+};
+
+struct R8G8S
+{
+ char R;
+ char G;
+
+ static void readColor(gl::ColorF *dst, const R8G8S *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorI *dst, const R8G8S *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R8G8S *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<char>(src->red);
+ dst->G = gl::floatToNormalized<char>(src->green);
+ }
+
+ static void writeColor(R8G8S *dst, const gl::ColorI *src)
+ {
+ dst->R = static_cast<char>(src->red);
+ dst->G = static_cast<char>(src->green);
+ }
+
+ static void average(R8G8S *dst, const R8G8S *src1, const R8G8S *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ }
+};
+
+struct R8G8B8S
+{
+ char R;
+ char G;
+ char B;
+
+ static void readColor(gl::ColorF *dst, const R8G8B8S *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorI *dst, const R8G8B8S *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R8G8B8S *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<char>(src->red);
+ dst->G = gl::floatToNormalized<char>(src->green);
+ dst->B = gl::floatToNormalized<char>(src->blue);
+ }
+
+ static void writeColor(R8G8B8S *dst, const gl::ColorI *src)
+ {
+ dst->R = static_cast<char>(src->red);
+ dst->G = static_cast<char>(src->green);
+ dst->B = static_cast<char>(src->blue);
+ }
+
+ static void average(R8G8B8S *dst, const R8G8B8S *src1, const R8G8B8S *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ }
+};
+
+struct R8G8B8A8S
+{
+ char R;
+ char G;
+ char B;
+ char A;
+
+ static void readColor(gl::ColorF *dst, const R8G8B8A8S *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+ }
+
+ static void readColor(gl::ColorI *dst, const R8G8B8A8S *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(R8G8B8A8S *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<char>(src->red);
+ dst->G = gl::floatToNormalized<char>(src->green);
+ dst->B = gl::floatToNormalized<char>(src->blue);
+ dst->A = gl::floatToNormalized<char>(src->alpha);
+ }
+
+ static void writeColor(R8G8B8A8S *dst, const gl::ColorI *src)
+ {
+ dst->R = static_cast<char>(src->red);
+ dst->G = static_cast<char>(src->green);
+ dst->B = static_cast<char>(src->blue);
+ dst->A = static_cast<char>(src->alpha);
+ }
+
+ static void average(R8G8B8A8S *dst, const R8G8B8A8S *src1, const R8G8B8A8S *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct R16S
+{
+ short R;
+
+ static void readColor(gl::ColorF *dst, const R16S *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorI *dst, const R16S *src)
+ {
+ dst->red = src->R;
+ dst->green = 0;
+ dst->blue = 0;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R16S *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<short>(src->red);
+ }
+
+ static void writeColor(R16S *dst, const gl::ColorI *src)
+ {
+ dst->R = static_cast<short>(src->red);
+ }
+
+ static void average(R16S *dst, const R16S *src1, const R16S *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ }
+};
+
+struct R16G16S
+{
+ short R;
+ short G;
+
+ static void readColor(gl::ColorF *dst, const R16G16S *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorI *dst, const R16G16S *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R16G16S *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<short>(src->red);
+ dst->G = gl::floatToNormalized<short>(src->green);
+ }
+
+ static void writeColor(R16G16S *dst, const gl::ColorI *src)
+ {
+ dst->R = static_cast<short>(src->red);
+ dst->G = static_cast<short>(src->green);
+ }
+
+ static void average(R16G16S *dst, const R16G16S *src1, const R16G16S *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ }
+};
+
+struct R16G16B16S
+{
+ short R;
+ short G;
+ short B;
+
+ static void readColor(gl::ColorF *dst, const R16G16B16S *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorI *dst, const R16G16B16S *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R16G16B16S *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<short>(src->red);
+ dst->G = gl::floatToNormalized<short>(src->green);
+ dst->B = gl::floatToNormalized<short>(src->blue);
+ }
+
+ static void writeColor(R16G16B16S *dst, const gl::ColorI *src)
+ {
+ dst->R = static_cast<short>(src->red);
+ dst->G = static_cast<short>(src->green);
+ dst->B = static_cast<short>(src->blue);
+ }
+
+ static void average(R16G16B16S *dst, const R16G16B16S *src1, const R16G16B16S *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ }
+};
+
+struct R16G16B16A16S
+{
+ short R;
+ short G;
+ short B;
+ short A;
+
+ static void readColor(gl::ColorF *dst, const R16G16B16A16S *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+ }
+
+ static void readColor(gl::ColorI *dst, const R16G16B16A16S *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(R16G16B16A16S *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<short>(src->red);
+ dst->G = gl::floatToNormalized<short>(src->green);
+ dst->B = gl::floatToNormalized<short>(src->blue);
+ dst->A = gl::floatToNormalized<short>(src->alpha);
+ }
+
+ static void writeColor(R16G16B16A16S *dst, const gl::ColorI *src)
+ {
+ dst->R = static_cast<short>(src->red);
+ dst->G = static_cast<short>(src->green);
+ dst->B = static_cast<short>(src->blue);
+ dst->A = static_cast<short>(src->alpha);
+ }
+
+ static void average(R16G16B16A16S *dst, const R16G16B16A16S *src1, const R16G16B16A16S *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct R32S
+{
+ int R;
+
+ static void readColor(gl::ColorF *dst, const R32S *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorI *dst, const R32S *src)
+ {
+ dst->red = src->R;
+ dst->green = 0;
+ dst->blue = 0;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R32S *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<int>(src->red);
+ }
+
+ static void writeColor(R32S *dst, const gl::ColorI *src)
+ {
+ dst->R = static_cast<int>(src->red);
+ }
+
+ static void average(R32S *dst, const R32S *src1, const R32S *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ }
+};
+
+struct R32G32S
+{
+ int R;
+ int G;
+
+ static void readColor(gl::ColorF *dst, const R32G32S *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorI *dst, const R32G32S *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R32G32S *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<int>(src->red);
+ dst->G = gl::floatToNormalized<int>(src->green);
+ }
+
+ static void writeColor(R32G32S *dst, const gl::ColorI *src)
+ {
+ dst->R = static_cast<int>(src->red);
+ dst->G = static_cast<int>(src->green);
+ }
+
+ static void average(R32G32S *dst, const R32G32S *src1, const R32G32S *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ }
+};
+
+struct R32G32B32S
+{
+ int R;
+ int G;
+ int B;
+
+ static void readColor(gl::ColorF *dst, const R32G32B32S *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+ }
+
+ static void readColor(gl::ColorI *dst, const R32G32B32S *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1;
+ }
+
+ static void writeColor(R32G32B32S *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<int>(src->red);
+ dst->G = gl::floatToNormalized<int>(src->green);
+ dst->B = gl::floatToNormalized<int>(src->blue);
+ }
+
+ static void writeColor(R32G32B32S *dst, const gl::ColorI *src)
+ {
+ dst->R = static_cast<int>(src->red);
+ dst->G = static_cast<int>(src->green);
+ dst->B = static_cast<int>(src->blue);
+ }
+
+ static void average(R32G32B32S *dst, const R32G32B32S *src1, const R32G32B32S *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ }
+};
+
+struct R32G32B32A32S
+{
+ int R;
+ int G;
+ int B;
+ int A;
+
+ static void readColor(gl::ColorF *dst, const R32G32B32A32S *src)
+ {
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+ }
+
+ static void readColor(gl::ColorI *dst, const R32G32B32A32S *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(R32G32B32A32S *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<int>(src->red);
+ dst->G = gl::floatToNormalized<int>(src->green);
+ dst->B = gl::floatToNormalized<int>(src->blue);
+ dst->A = gl::floatToNormalized<int>(src->alpha);
+ }
+
+ static void writeColor(R32G32B32A32S *dst, const gl::ColorI *src)
+ {
+ dst->R = static_cast<int>(src->red);
+ dst->G = static_cast<int>(src->green);
+ dst->B = static_cast<int>(src->blue);
+ dst->A = static_cast<int>(src->alpha);
+ }
+
+ static void average(R32G32B32A32S *dst, const R32G32B32A32S *src1, const R32G32B32A32S *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct A16B16G16R16F
+{
+ unsigned short A;
+ unsigned short R;
+ unsigned short G;
+ unsigned short B;
+
+ static void readColor(gl::ColorF *dst, const A16B16G16R16F *src)
+ {
+ dst->red = gl::float16ToFloat32(src->R);
+ dst->green = gl::float16ToFloat32(src->G);
+ dst->blue = gl::float16ToFloat32(src->B);
+ dst->alpha = gl::float16ToFloat32(src->A);
+ }
+
+ static void writeColor(A16B16G16R16F *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::float32ToFloat16(src->red);
+ dst->G = gl::float32ToFloat16(src->green);
+ dst->B = gl::float32ToFloat16(src->blue);
+ dst->A = gl::float32ToFloat16(src->alpha);
+ }
+
+ static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2)
+ {
+ dst->R = gl::averageHalfFloat(src1->R, src2->R);
+ dst->G = gl::averageHalfFloat(src1->G, src2->G);
+ dst->B = gl::averageHalfFloat(src1->B, src2->B);
+ dst->A = gl::averageHalfFloat(src1->A, src2->A);
+ }
+};
+
+struct R16G16B16A16F
+{
+ unsigned short R;
+ unsigned short G;
+ unsigned short B;
+ unsigned short A;
+
+ static void readColor(gl::ColorF *dst, const R16G16B16A16F *src)
+ {
+ dst->red = gl::float16ToFloat32(src->R);
+ dst->green = gl::float16ToFloat32(src->G);
+ dst->blue = gl::float16ToFloat32(src->B);
+ dst->alpha = gl::float16ToFloat32(src->A);
+ }
+
+ static void writeColor(R16G16B16A16F *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::float32ToFloat16(src->red);
+ dst->G = gl::float32ToFloat16(src->green);
+ dst->B = gl::float32ToFloat16(src->blue);
+ dst->A = gl::float32ToFloat16(src->alpha);
+ }
+
+ static void average(R16G16B16A16F *dst, const R16G16B16A16F *src1, const R16G16B16A16F *src2)
+ {
+ dst->R = gl::averageHalfFloat(src1->R, src2->R);
+ dst->G = gl::averageHalfFloat(src1->G, src2->G);
+ dst->B = gl::averageHalfFloat(src1->B, src2->B);
+ dst->A = gl::averageHalfFloat(src1->A, src2->A);
+ }
+};
+
+struct R16F
+{
+ unsigned short R;
+
+ static void readColor(gl::ColorF *dst, const R16F *src)
+ {
+ dst->red = gl::float16ToFloat32(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void writeColor(R16F *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::float32ToFloat16(src->red);
+ }
+
+ static void average(R16F *dst, const R16F *src1, const R16F *src2)
+ {
+ dst->R = gl::averageHalfFloat(src1->R, src2->R);
+ }
+};
+
+struct A16F
+{
+ unsigned short A;
+
+ static void readColor(gl::ColorF *dst, const A16F *src)
+ {
+ dst->red = 0.0f;
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = gl::float16ToFloat32(src->A);
+ }
+
+ static void writeColor(A16F *dst, const gl::ColorF *src)
+ {
+ dst->A = gl::float32ToFloat16(src->alpha);
+ }
+
+ static void average(A16F *dst, const A16F *src1, const A16F *src2)
+ {
+ dst->A = gl::averageHalfFloat(src1->A, src2->A);
+ }
+};
+
+struct L16F
+{
+ unsigned short L;
+
+ static void readColor(gl::ColorF *dst, const L16F *src)
+ {
+ float lum = gl::float16ToFloat32(src->L);
+ dst->red = lum;
+ dst->green = lum;
+ dst->blue = lum;
+ dst->alpha = 1.0f;
+ }
+
+ static void writeColor(L16F *dst, const gl::ColorF *src)
+ {
+ dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f);
+ }
+
+ static void average(L16F *dst, const L16F *src1, const L16F *src2)
+ {
+ dst->L = gl::averageHalfFloat(src1->L, src2->L);
+ }
+};
+
+struct L16A16F
+{
+ unsigned short L;
+ unsigned short A;
+
+ static void readColor(gl::ColorF *dst, const L16A16F *src)
+ {
+ float lum = gl::float16ToFloat32(src->L);
+ dst->red = lum;
+ dst->green = lum;
+ dst->blue = lum;
+ dst->alpha = gl::float16ToFloat32(src->A);
+ }
+
+ static void writeColor(L16A16F *dst, const gl::ColorF *src)
+ {
+ dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f);
+ dst->A = gl::float32ToFloat16(src->alpha);
+ }
+
+ static void average(L16A16F *dst, const L16A16F *src1, const L16A16F *src2)
+ {
+ dst->L = gl::averageHalfFloat(src1->L, src2->L);
+ dst->A = gl::averageHalfFloat(src1->A, src2->A);
+ }
+};
+
+struct R16G16F
+{
+ unsigned short R;
+ unsigned short G;
+
+ static void readColor(gl::ColorF *dst, const R16G16F *src)
+ {
+ dst->red = gl::float16ToFloat32(src->R);
+ dst->green = gl::float16ToFloat32(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void writeColor(R16G16F *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::float32ToFloat16(src->red);
+ dst->G = gl::float32ToFloat16(src->green);
+ }
+
+ static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2)
+ {
+ dst->R = gl::averageHalfFloat(src1->R, src2->R);
+ dst->G = gl::averageHalfFloat(src1->G, src2->G);
+ }
+};
+
+struct R16G16B16F
+{
+ unsigned short R;
+ unsigned short G;
+ unsigned short B;
+
+ static void readColor(gl::ColorF *dst, const R16G16B16F *src)
+ {
+ dst->red = gl::float16ToFloat32(src->R);
+ dst->green = gl::float16ToFloat32(src->G);
+ dst->blue = gl::float16ToFloat32(src->B);
+ dst->alpha = 1.0f;
+ }
+
+ static void writeColor(R16G16B16F *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::float32ToFloat16(src->red);
+ dst->G = gl::float32ToFloat16(src->green);
+ dst->B = gl::float32ToFloat16(src->blue);
+ }
+
+ static void average(R16G16B16F *dst, const R16G16B16F *src1, const R16G16B16F *src2)
+ {
+ dst->R = gl::averageHalfFloat(src1->R, src2->R);
+ dst->G = gl::averageHalfFloat(src1->G, src2->G);
+ dst->B = gl::averageHalfFloat(src1->B, src2->B);
+ }
+};
+
+struct A32B32G32R32F
+{
+ float A;
+ float R;
+ float G;
+ float B;
+
+ static void readColor(gl::ColorF *dst, const A32B32G32R32F *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(A32B32G32R32F *dst, const gl::ColorF *src)
+ {
+ dst->R = src->red;
+ dst->G = src->green;
+ dst->B = src->blue;
+ dst->A = src->alpha;
+ }
+
+ static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct R32G32B32A32F
+{
+ float R;
+ float G;
+ float B;
+ float A;
+
+ static void readColor(gl::ColorF *dst, const R32G32B32A32F *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(R32G32B32A32F *dst, const gl::ColorF *src)
+ {
+ dst->R = src->red;
+ dst->G = src->green;
+ dst->B = src->blue;
+ dst->A = src->alpha;
+ }
+
+ static void average(R32G32B32A32F *dst, const R32G32B32A32F *src1, const R32G32B32A32F *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct R32F
+{
+ float R;
+
+ static void readColor(gl::ColorF *dst, const R32F *src)
+ {
+ dst->red = src->R;
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void writeColor(R32F *dst, const gl::ColorF *src)
+ {
+ dst->R = src->red;
+ }
+
+ static void average(R32F *dst, const R32F *src1, const R32F *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ }
+};
+
+struct A32F
+{
+ float A;
+
+ static void readColor(gl::ColorF *dst, const A32F *src)
+ {
+ dst->red = 0.0f;
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(A32F *dst, const gl::ColorF *src)
+ {
+ dst->A = src->alpha;
+ }
+
+ static void average(A32F *dst, const A32F *src1, const A32F *src2)
+ {
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct L32F
+{
+ float L;
+
+ static void readColor(gl::ColorF *dst, const L32F *src)
+ {
+ dst->red = src->L;
+ dst->green = src->L;
+ dst->blue = src->L;
+ dst->alpha = 1.0f;
+ }
+
+ static void writeColor(L32F *dst, const gl::ColorF *src)
+ {
+ dst->L = (src->red + src->green + src->blue) / 3.0f;
+ }
+
+ static void average(L32F *dst, const L32F *src1, const L32F *src2)
+ {
+ dst->L = gl::average(src1->L, src2->L);
+ }
+};
+
+struct L32A32F
+{
+ float L;
+ float A;
+
+ static void readColor(gl::ColorF *dst, const L32A32F *src)
+ {
+ dst->red = src->L;
+ dst->green = src->L;
+ dst->blue = src->L;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(L32A32F *dst, const gl::ColorF *src)
+ {
+ dst->L = (src->red + src->green + src->blue) / 3.0f;
+ dst->A = src->alpha;
+ }
+
+ static void average(L32A32F *dst, const L32A32F *src1, const L32A32F *src2)
+ {
+ dst->L = gl::average(src1->L, src2->L);
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct R32G32F
+{
+ float R;
+ float G;
+
+ static void readColor(gl::ColorF *dst, const R32G32F *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+ }
+
+ static void writeColor(R32G32F *dst, const gl::ColorF *src)
+ {
+ dst->R = src->red;
+ dst->G = src->green;
+ }
+
+ static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ }
+};
+
+struct R32G32B32F
+{
+ float R;
+ float G;
+ float B;
+
+ static void readColor(gl::ColorF *dst, const R32G32B32F *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1.0f;
+ }
+
+ static void writeColor(R32G32B32F *dst, const gl::ColorF *src)
+ {
+ dst->R = src->red;
+ dst->G = src->green;
+ dst->B = src->blue;
+ }
+
+ static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ }
+};
+
+struct R10G10B10A2
+{
+ unsigned int R : 10;
+ unsigned int G : 10;
+ unsigned int B : 10;
+ unsigned int A : 2;
+
+ static void readColor(gl::ColorF *dst, const R10G10B10A2 *src)
+ {
+ dst->red = gl::normalizedToFloat<10>(src->R);
+ dst->green = gl::normalizedToFloat<10>(src->G);
+ dst->blue = gl::normalizedToFloat<10>(src->B);
+ dst->alpha = gl::normalizedToFloat< 2>(src->A);
+ }
+
+ static void readColor(gl::ColorUI *dst, const R10G10B10A2 *src)
+ {
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+ }
+
+ static void writeColor(R10G10B10A2 *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::floatToNormalized<10, unsigned int>(src->red);
+ dst->G = gl::floatToNormalized<10, unsigned int>(src->green);
+ dst->B = gl::floatToNormalized<10, unsigned int>(src->blue);
+ dst->A = gl::floatToNormalized< 2, unsigned int>(src->alpha);
+ }
+
+ static void writeColor(R10G10B10A2 *dst, const gl::ColorUI *src)
+ {
+ dst->R = static_cast<unsigned int>(src->red);
+ dst->G = static_cast<unsigned int>(src->green);
+ dst->B = static_cast<unsigned int>(src->blue);
+ dst->A = static_cast<unsigned int>(src->alpha);
+ }
+
+ static void average(R10G10B10A2 *dst, const R10G10B10A2 *src1, const R10G10B10A2 *src2)
+ {
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+ }
+};
+
+struct R9G9B9E5
+{
+ unsigned int R : 9;
+ unsigned int G : 9;
+ unsigned int B : 9;
+ unsigned int E : 5;
+
+ static void readColor(gl::ColorF *dst, const R9G9B9E5 *src)
+ {
+ gl::convert999E5toRGBFloats(gl::bitCast<unsigned int>(*src), &dst->red, &dst->green, &dst->blue);
+ dst->alpha = 1.0f;
+ }
+
+ static void writeColor(R9G9B9E5 *dst, const gl::ColorF *src)
+ {
+ *reinterpret_cast<unsigned int*>(dst) = gl::convertRGBFloatsTo999E5(src->red,
+ src->green,
+ src->blue);
+ }
+
+ static void average(R9G9B9E5 *dst, const R9G9B9E5 *src1, const R9G9B9E5 *src2)
+ {
+ float r1, g1, b1;
+ gl::convert999E5toRGBFloats(*reinterpret_cast<const unsigned int*>(src1), &r1, &g1, &b1);
+
+ float r2, g2, b2;
+ gl::convert999E5toRGBFloats(*reinterpret_cast<const unsigned int*>(src2), &r2, &g2, &b2);
+
+ *reinterpret_cast<unsigned int*>(dst) = gl::convertRGBFloatsTo999E5(gl::average(r1, r2),
+ gl::average(g1, g2),
+ gl::average(b1, b2));
+ }
+};
+
+struct R11G11B10F
+{
+ unsigned int R : 11;
+ unsigned int G : 11;
+ unsigned int B : 10;
+
+ static void readColor(gl::ColorF *dst, const R11G11B10F *src)
+ {
+ dst->red = gl::float11ToFloat32(src->R);
+ dst->green = gl::float11ToFloat32(src->G);
+ dst->blue = gl::float10ToFloat32(src->B);
+ dst->alpha = 1.0f;
+ }
+
+ static void writeColor(R11G11B10F *dst, const gl::ColorF *src)
+ {
+ dst->R = gl::float32ToFloat11(src->red);
+ dst->G = gl::float32ToFloat11(src->green);
+ dst->B = gl::float32ToFloat10(src->blue);
+ }
+
+ static void average(R11G11B10F *dst, const R11G11B10F *src1, const R11G11B10F *src2)
+ {
+ dst->R = gl::averageFloat11(src1->R, src2->R);
+ dst->G = gl::averageFloat11(src1->G, src2->G);
+ dst->B = gl::averageFloat10(src1->B, src2->B);
+ }
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_IMAGEFORMATS_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp
new file mode 100644
index 0000000000..1986191a75
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp
@@ -0,0 +1,661 @@
+//
+// 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.
+//
+
+// loadimage.cpp: Defines image loading functions.
+
+#include "libGLESv2/renderer/loadimage.h"
+
+namespace rx
+{
+
+void LoadA8ToRGBA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = static_cast<uint32_t>(source[x]) << 24;
+ }
+ }
+ }
+}
+
+void LoadA8ToBGRA8(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)
+{
+ // Same as loading to RGBA
+ LoadA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch);
+}
+
+void LoadA32FToRGBA32F(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ float *dest = OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = 0.0f;
+ dest[4 * x + 1] = 0.0f;
+ dest[4 * x + 2] = 0.0f;
+ dest[4 * x + 3] = source[x];
+ }
+ }
+ }
+}
+
+void LoadA16FToRGBA16F(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = 0;
+ dest[4 * x + 1] = 0;
+ dest[4 * x + 2] = 0;
+ dest[4 * x + 3] = source[x];
+ }
+ }
+ }
+}
+
+void LoadL8ToRGBA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[x];
+ dest[4 * x + 1] = source[x];
+ dest[4 * x + 2] = source[x];
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+ }
+}
+
+void LoadL8ToBGRA8(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)
+{
+ // Same as loading to RGBA
+ LoadL8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch);
+}
+
+void LoadL32FToRGBA32F(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ float *dest = OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[x];
+ dest[4 * x + 1] = source[x];
+ dest[4 * x + 2] = source[x];
+ dest[4 * x + 3] = 1.0f;
+ }
+ }
+ }
+}
+
+void LoadL16FToRGBA16F(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[x];
+ dest[4 * x + 1] = source[x];
+ dest[4 * x + 2] = source[x];
+ dest[4 * x + 3] = gl::Float16One;
+ }
+ }
+ }
+}
+
+void LoadLA8ToRGBA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[2 * x + 0];
+ dest[4 * x + 1] = source[2 * x + 0];
+ dest[4 * x + 2] = source[2 * x + 0];
+ dest[4 * x + 3] = source[2 * x + 1];
+ }
+ }
+ }
+}
+
+void LoadLA8ToBGRA8(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)
+{
+ // Same as loading to RGBA
+ LoadLA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch);
+}
+
+void LoadLA32FToRGBA32F(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ float *dest = OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[2 * x + 0];
+ dest[4 * x + 1] = source[2 * x + 0];
+ dest[4 * x + 2] = source[2 * x + 0];
+ dest[4 * x + 3] = source[2 * x + 1];
+ }
+ }
+ }
+}
+
+void LoadLA16FToRGBA16F(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[2 * x + 0];
+ dest[4 * x + 1] = source[2 * x + 0];
+ dest[4 * x + 2] = source[2 * x + 0];
+ dest[4 * x + 3] = source[2 * x + 1];
+ }
+ }
+ }
+}
+
+void LoadRGB8ToBGRX8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[x * 3 + 2];
+ dest[4 * x + 1] = source[x * 3 + 1];
+ dest[4 * x + 2] = source[x * 3 + 0];
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+ }
+}
+
+void LoadRG8ToBGRX8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = 0x00;
+ dest[4 * x + 1] = source[x * 2 + 1];
+ dest[4 * x + 2] = source[x * 2 + 0];
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+ }
+}
+
+void LoadR8ToBGRX8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = 0x00;
+ dest[4 * x + 1] = 0x00;
+ dest[4 * x + 2] = source[x];
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+ }
+}
+
+void LoadR5G6B5ToBGRA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t rgb = source[x];
+ dest[4 * x + 0] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2);
+ dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9);
+ dest[4 * x + 2] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13);
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+ }
+}
+
+void LoadR5G6B5ToRGBA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t rgb = source[x];
+ dest[4 * x + 0] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13);
+ dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9);
+ dest[4 * x + 2] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2);
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+ }
+}
+
+void LoadRGBA8ToBGRA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint32_t rgba = source[x];
+ dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+ }
+ }
+ }
+}
+
+void LoadRGBA4ToBGRA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t rgba = source[x];
+ dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
+ dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
+ dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
+ dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
+ }
+ }
+ }
+}
+
+void LoadRGBA4ToRGBA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t rgba = source[x];
+ dest[4 * x + 0] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
+ dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
+ dest[4 * x + 2] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
+ dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
+ }
+ }
+ }
+}
+
+void LoadBGRA4ToBGRA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t bgra = source[x];
+ dest[4 * x + 0] = ((bgra & 0xF000) >> 8) | ((bgra & 0xF000) >> 12);
+ dest[4 * x + 1] = ((bgra & 0x0F00) >> 4) | ((bgra & 0x0F00) >> 8);
+ dest[4 * x + 2] = ((bgra & 0x00F0) << 0) | ((bgra & 0x00F0) >> 4);
+ dest[4 * x + 3] = ((bgra & 0x000F) << 4) | ((bgra & 0x000F) >> 0);
+ }
+ }
+ }
+}
+
+void LoadRGB5A1ToBGRA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t rgba = source[x];
+ dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
+ dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
+ dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+ dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
+ }
+ }
+ }
+}
+
+void LoadRGB5A1ToRGBA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t rgba = source[x];
+ dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+ dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
+ dest[4 * x + 2] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
+ dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
+ }
+ }
+ }
+}
+
+
+void LoadBGR5A1ToBGRA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t bgra = source[x];
+ dest[4 * x + 0] = ((bgra & 0xF800) >> 8) | ((bgra & 0xF800) >> 13);
+ dest[4 * x + 1] = ((bgra & 0x07C0) >> 3) | ((bgra & 0x07C0) >> 8);
+ dest[4 * x + 2] = ((bgra & 0x003E) << 2) | ((bgra & 0x003E) >> 3);
+ dest[4 * x + 3] = (bgra & 0x0001) ? 0xFF : 0;
+ }
+ }
+ }
+}
+
+void LoadRGB10A2ToRGBA8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint32_t rgba = source[x];
+ dest[4 * x + 0] = (rgba & 0x000003FF) >> 2;
+ dest[4 * x + 1] = (rgba & 0x000FFC00) >> 12;
+ dest[4 * x + 2] = (rgba & 0x3FF00000) >> 22;
+ dest[4 * x + 3] = ((rgba & 0xC0000000) >> 30) * 0x55;
+ }
+ }
+ }
+}
+
+void LoadRGB16FToRGB9E5(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = gl::convertRGBFloatsTo999E5(gl::float16ToFloat32(source[x * 3 + 0]),
+ gl::float16ToFloat32(source[x * 3 + 1]),
+ gl::float16ToFloat32(source[x * 3 + 2]));
+ }
+ }
+ }
+}
+
+void LoadRGB32FToRGB9E5(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = gl::convertRGBFloatsTo999E5(source[x * 3 + 0], source[x * 3 + 1], source[x * 3 + 2]);
+ }
+ }
+ }
+}
+
+void LoadRGB16FToRG11B10F(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 0])) << 0) |
+ (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 1])) << 11) |
+ (gl::float32ToFloat10(gl::float16ToFloat32(source[x * 3 + 2])) << 22);
+ }
+ }
+ }
+}
+
+void LoadRGB32FToRG11B10F(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = (gl::float32ToFloat11(source[x * 3 + 0]) << 0) |
+ (gl::float32ToFloat11(source[x * 3 + 1]) << 11) |
+ (gl::float32ToFloat10(source[x * 3 + 2]) << 22);
+ }
+ }
+ }
+}
+
+void LoadG8R24ToR24G8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint32_t d = source[x] >> 8;
+ uint8_t s = source[x] & 0xFF;
+ dest[x] = d | (s << 24);
+ }
+ }
+ }
+}
+
+void LoadRGB32FToRGBA16F(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x * 4 + 0] = gl::float32ToFloat16(source[x * 3 + 0]);
+ dest[x * 4 + 1] = gl::float32ToFloat16(source[x * 3 + 1]);
+ dest[x * 4 + 2] = gl::float32ToFloat16(source[x * 3 + 2]);
+ dest[x * 4 + 3] = gl::Float16One;
+ }
+ }
+ }
+}
+
+void LoadR32ToR16(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = source[x] >> 16;
+ }
+ }
+ }
+}
+
+void LoadR32ToR24G8(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)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = source[x] >> 8;
+ }
+ }
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h
new file mode 100644
index 0000000000..bcdff24a66
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h
@@ -0,0 +1,193 @@
+//
+// 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.
+//
+
+// loadimage.h: Defines image loading functions
+
+#ifndef LIBGLESV2_RENDERER_LOADIMAGE_H_
+#define LIBGLESV2_RENDERER_LOADIMAGE_H_
+
+#include "libGLESv2/angletypes.h"
+
+#include <cstdint>
+
+namespace rx
+{
+
+void LoadA8ToRGBA8(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);
+
+void LoadA8ToBGRA8(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);
+
+void LoadA8ToBGRA8_SSE2(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);
+
+void LoadA32FToRGBA32F(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);
+
+void LoadA16FToRGBA16F(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);
+
+void LoadL8ToRGBA8(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);
+
+void LoadL8ToBGRA8(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);
+
+void LoadL32FToRGBA32F(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);
+
+void LoadL16FToRGBA16F(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);
+
+void LoadLA8ToRGBA8(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);
+
+void LoadLA8ToBGRA8(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);
+
+void LoadLA32FToRGBA32F(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);
+
+void LoadLA16FToRGBA16F(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);
+
+void LoadRGB8ToBGRX8(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);
+
+void LoadRG8ToBGRX8(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);
+
+void LoadR8ToBGRX8(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);
+
+void LoadR5G6B5ToBGRA8(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);
+
+void LoadR5G6B5ToRGBA8(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);
+
+void LoadRGBA8ToBGRA8_SSE2(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);
+
+void LoadRGBA8ToBGRA8(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);
+
+void LoadRGBA4ToBGRA8(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);
+
+void LoadRGBA4ToRGBA8(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);
+
+void LoadBGRA4ToBGRA8(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);
+
+void LoadRGB5A1ToBGRA8(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);
+
+void LoadRGB5A1ToRGBA8(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);
+
+void LoadBGR5A1ToBGRA8(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);
+
+void LoadRGB10A2ToRGBA8(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);
+
+void LoadRGB16FToRGB9E5(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);
+
+void LoadRGB32FToRGB9E5(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);
+
+void LoadRGB16FToRG11B10F(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);
+
+void LoadRGB32FToRG11B10F(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);
+
+void LoadG8R24ToR24G8(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);
+
+template <typename type, size_t componentCount>
+inline void LoadToNative(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);
+
+template <typename type, uint32_t fourthComponentBits>
+inline void LoadToNative3To4(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);
+
+template <size_t componentCount>
+inline void Load32FTo16F(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);
+
+void LoadRGB32FToRGBA16F(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);
+
+template <size_t blockWidth, size_t blockHeight, size_t blockSize>
+inline void LoadCompressedToNative(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);
+
+void LoadR32ToR16(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);
+
+template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits>
+inline void Initialize4ComponentData(size_t width, size_t height, size_t depth,
+ uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
+
+void LoadR32ToR24G8(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);
+
+template <typename T>
+inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch);
+
+template <typename T>
+inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch);
+
+}
+
+#include "loadimage.inl"
+
+#endif // LIBGLESV2_RENDERER_LOADIMAGE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl
new file mode 100644
index 0000000000..abd0a3673c
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl
@@ -0,0 +1,156 @@
+//
+// 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 "common/mathutil.h"
+
+namespace rx
+{
+
+template <typename T>
+inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
+{
+ return reinterpret_cast<T*>(data + (y * rowPitch) + (z * depthPitch));
+}
+
+template <typename T>
+inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
+{
+ return reinterpret_cast<const T*>(data + (y * rowPitch) + (z * depthPitch));
+}
+
+template <typename type, size_t componentCount>
+inline void LoadToNative(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)
+{
+ const size_t rowSize = width * sizeof(type) * componentCount;
+ const size_t layerSize = rowSize * height;
+ const size_t imageSize = layerSize * depth;
+
+ if (layerSize == inputDepthPitch && layerSize == outputDepthPitch)
+ {
+ ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch);
+ memcpy(output, input, imageSize);
+ }
+ else if (rowSize == inputRowPitch && rowSize == outputRowPitch)
+ {
+ for (size_t z = 0; z < depth; z++)
+ {
+ const type *source = OffsetDataPointer<type>(input, 0, z, inputRowPitch, inputDepthPitch);
+ type *dest = OffsetDataPointer<type>(output, 0, z, outputRowPitch, outputDepthPitch);
+
+ memcpy(dest, source, layerSize);
+ }
+ }
+ else
+ {
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const type *source = OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch);
+ type *dest = OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
+ memcpy(dest, source, width * sizeof(type) * componentCount);
+ }
+ }
+ }
+}
+
+template <typename type, uint32_t fourthComponentBits>
+inline void LoadToNative3To4(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)
+{
+ const type fourthValue = gl::bitCast<type>(fourthComponentBits);
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const type *source = OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch);
+ type *dest = OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x * 4 + 0] = source[x * 3 + 0];
+ dest[x * 4 + 1] = source[x * 3 + 1];
+ dest[x * 4 + 2] = source[x * 3 + 2];
+ dest[x * 4 + 3] = fourthValue;
+ }
+ }
+ }
+}
+
+template <size_t componentCount>
+inline void Load32FTo16F(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)
+{
+ const size_t elementWidth = componentCount * width;
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < elementWidth; x++)
+ {
+ dest[x] = gl::float32ToFloat16(source[x]);
+ }
+ }
+ }
+}
+
+template <size_t blockWidth, size_t blockHeight, size_t blockSize>
+inline void LoadCompressedToNative(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)
+{
+ const size_t columns = (width + (blockWidth - 1)) / blockWidth;
+ const size_t rows = (height + (blockHeight - 1)) / blockHeight;
+
+ for (size_t z = 0; z < depth; ++z)
+ {
+ for (size_t y = 0; y < rows; ++y)
+ {
+ const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ memcpy(dest, source, columns * blockSize);
+ }
+ }
+}
+
+template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits>
+inline void Initialize4ComponentData(size_t width, size_t height, size_t depth,
+ uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
+{
+ type writeValues[4] =
+ {
+ gl::bitCast<type>(firstBits),
+ gl::bitCast<type>(secondBits),
+ gl::bitCast<type>(thirdBits),
+ gl::bitCast<type>(fourthBits),
+ };
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ type *destRow = OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ type* destPixel = destRow + x * 4;
+
+ // This could potentially be optimized by generating an entire row of initialization
+ // data and copying row by row instead of pixel by pixel.
+ memcpy(destPixel, writeValues, sizeof(type) * 4);
+ }
+ }
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp
new file mode 100644
index 0000000000..f777b30be6
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp
@@ -0,0 +1,112 @@
+//
+// 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.
+//
+
+// loadimageSSE2.cpp: Defines image loading functions. It's
+// in a separated file for GCC, which can enable SSE usage only per-file,
+// not for code blocks that use SSE2 explicitly.
+
+#include "libGLESv2/renderer/loadimage.h"
+
+#if !defined(__SSE2__) && (defined(_M_X64) || _M_IX86_FP == 2)
+#define __SSE2__
+#endif
+
+namespace rx
+{
+
+void LoadA8ToBGRA8_SSE2(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)
+{
+#ifdef __SSE2__
+ __m128i zeroWide = _mm_setzero_si128();
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ size_t x = 0;
+
+ // Make output writes aligned
+ for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++)
+ {
+ dest[x] = static_cast<uint32_t>(source[x]) << 24;
+ }
+
+ for (; x + 7 < width; x += 8)
+ {
+ __m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x]));
+ // Interleave each byte to 16bit, make the lower byte to zero
+ sourceData = _mm_unpacklo_epi8(zeroWide, sourceData);
+ // Interleave each 16bit to 32bit, make the lower 16bit to zero
+ __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData);
+ __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData);
+
+ _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo);
+ _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi);
+ }
+
+ // Handle the remainder
+ for (; x < width; x++)
+ {
+ dest[x] = static_cast<uint32_t>(source[x]) << 24;
+ }
+ }
+ }
+#endif
+}
+
+void LoadRGBA8ToBGRA8_SSE2(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)
+{
+#ifdef __SSE2__
+ __m128i brMask = _mm_set1_epi32(0x00ff00ff);
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ size_t x = 0;
+
+ // Make output writes aligned
+ for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
+ {
+ uint32_t rgba = source[x];
+ dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+ }
+
+ for (; x + 3 < width; x += 4)
+ {
+ __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
+ // Mask out g and a, which don't change
+ __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
+ // Mask out b and r
+ __m128i brComponents = _mm_and_si128(sourceData, brMask);
+ // Swap b and r
+ __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
+ __m128i result = _mm_or_si128(gaComponents, brSwapped);
+ _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
+ }
+
+ // Perform leftover writes
+ for (; x < width; x++)
+ {
+ uint32_t rgba = source[x];
+ dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+ }
+ }
+ }
+#endif
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h b/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h
index 590b9d48a3..81ba8a0767 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h
@@ -10,6 +10,10 @@
#ifndef LIBGLESV2_VERTEXCONVERSION_H_
#define LIBGLESV2_VERTEXCONVERSION_H_
+#include <limits>
+#include <cstdint>
+#include <cstddef>
+
namespace rx
{
@@ -154,11 +158,13 @@ struct VertexDataConverter
static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);
- static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out)
+ 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 = pointerAddBytes(in, i * stride);
+ 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()));
@@ -169,19 +175,7 @@ struct VertexDataConverter
}
}
- static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out)
- {
- return convertArray(static_cast<const InputType*>(in), stride, n, static_cast<OutputType*>(out));
- }
-
private:
- // Advance the given pointer by a number of bytes (not pointed-to elements).
- template <class T>
- static T *pointerAddBytes(T *basePtr, std::size_t numBytes)
- {
- return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(basePtr) + numBytes);
- }
-
static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue)
{
if (WidenRule::finalWidth > elementindex)
diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.cpp b/src/3rdparty/angle/src/libGLESv2/utilities.cpp
deleted file mode 100644
index 30765ffba0..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/utilities.cpp
+++ /dev/null
@@ -1,817 +0,0 @@
-#include "precompiled.h"
-//
-// 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.
-//
-
-// utilities.cpp: Conversion functions and other utility routines.
-
-#include "libGLESv2/utilities.h"
-#include "libGLESv2/mathutil.h"
-#if defined(ANGLE_OS_WINRT)
-# include <locale>
-# include <codecvt>
-# include <wrl.h>
-# include <windows.storage.h>
- using namespace Microsoft::WRL;
- using namespace ABI::Windows::Storage;
-#endif
-
-namespace gl
-{
-
-int UniformComponentCount(GLenum type)
-{
- switch (type)
- {
- case GL_BOOL:
- case GL_FLOAT:
- case GL_INT:
- case GL_SAMPLER_2D:
- case GL_SAMPLER_CUBE:
- return 1;
- case GL_BOOL_VEC2:
- case GL_FLOAT_VEC2:
- case GL_INT_VEC2:
- return 2;
- case GL_INT_VEC3:
- case GL_FLOAT_VEC3:
- case GL_BOOL_VEC3:
- return 3;
- case GL_BOOL_VEC4:
- case GL_FLOAT_VEC4:
- case GL_INT_VEC4:
- case GL_FLOAT_MAT2:
- return 4;
- case GL_FLOAT_MAT3:
- return 9;
- case GL_FLOAT_MAT4:
- return 16;
- default:
- UNREACHABLE();
- }
-
- return 0;
-}
-
-GLenum UniformComponentType(GLenum type)
-{
- switch(type)
- {
- case GL_BOOL:
- case GL_BOOL_VEC2:
- case GL_BOOL_VEC3:
- case GL_BOOL_VEC4:
- return GL_BOOL;
- 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:
- return GL_FLOAT;
- case GL_INT:
- case GL_SAMPLER_2D:
- case GL_SAMPLER_CUBE:
- case GL_INT_VEC2:
- case GL_INT_VEC3:
- case GL_INT_VEC4:
- return GL_INT;
- default:
- UNREACHABLE();
- }
-
- return GL_NONE;
-}
-
-size_t UniformComponentSize(GLenum type)
-{
- switch(type)
- {
- case GL_BOOL: return sizeof(GLint);
- case GL_FLOAT: return sizeof(GLfloat);
- case GL_INT: return sizeof(GLint);
- default: UNREACHABLE();
- }
-
- return 0;
-}
-
-size_t UniformInternalSize(GLenum type)
-{
- // Expanded to 4-element vectors
- return UniformComponentSize(UniformComponentType(type)) * VariableRowCount(type) * 4;
-}
-
-size_t UniformExternalSize(GLenum type)
-{
- return UniformComponentSize(UniformComponentType(type)) * UniformComponentCount(type);
-}
-
-int VariableRowCount(GLenum type)
-{
- switch (type)
- {
- case GL_NONE:
- return 0;
- case GL_BOOL:
- case GL_FLOAT:
- case GL_INT:
- case GL_BOOL_VEC2:
- case GL_FLOAT_VEC2:
- case GL_INT_VEC2:
- case GL_INT_VEC3:
- case GL_FLOAT_VEC3:
- case GL_BOOL_VEC3:
- case GL_BOOL_VEC4:
- case GL_FLOAT_VEC4:
- case GL_INT_VEC4:
- case GL_SAMPLER_2D:
- case GL_SAMPLER_CUBE:
- return 1;
- case GL_FLOAT_MAT2:
- return 2;
- case GL_FLOAT_MAT3:
- return 3;
- case GL_FLOAT_MAT4:
- return 4;
- default:
- UNREACHABLE();
- }
-
- return 0;
-}
-
-int VariableColumnCount(GLenum type)
-{
- switch (type)
- {
- case GL_NONE:
- return 0;
- case GL_BOOL:
- case GL_FLOAT:
- case GL_INT:
- case GL_SAMPLER_2D:
- case GL_SAMPLER_CUBE:
- return 1;
- case GL_BOOL_VEC2:
- case GL_FLOAT_VEC2:
- case GL_INT_VEC2:
- case GL_FLOAT_MAT2:
- return 2;
- case GL_INT_VEC3:
- case GL_FLOAT_VEC3:
- case GL_BOOL_VEC3:
- case GL_FLOAT_MAT3:
- return 3;
- case GL_BOOL_VEC4:
- case GL_FLOAT_VEC4:
- case GL_INT_VEC4:
- case GL_FLOAT_MAT4:
- return 4;
- default:
- UNREACHABLE();
- }
-
- return 0;
-}
-
-int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
-{
- ASSERT(allocationSize <= bitsSize);
-
- unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
-
- for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
- {
- if ((*bits & mask) == 0)
- {
- *bits |= mask;
- return i;
- }
-
- mask <<= 1;
- }
-
- return -1;
-}
-
-GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment)
-{
- ASSERT(alignment > 0 && isPow2(alignment));
-
- GLsizei rawPitch = ComputePixelSize(internalformat) * width;
- return (rawPitch + alignment - 1) & ~(alignment - 1);
-}
-
-GLsizei ComputeCompressedPitch(GLsizei width, GLenum internalformat)
-{
- return ComputeCompressedSize(width, 1, internalformat);
-}
-
-GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum internalformat)
-{
- switch (internalformat)
- {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- return 8 * ((width + 3) / 4) * ((height + 3) / 4);
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- return 16 * ((width + 3) / 4) * ((height + 3) / 4);
- default:
- return 0;
- }
-}
-
-GLsizei ComputeTypeSize(GLenum type)
-{
- switch (type)
- {
- case GL_BYTE: return 1;
- case GL_UNSIGNED_BYTE: return 1;
- case GL_SHORT: return 2;
- case GL_UNSIGNED_SHORT: return 2;
- case GL_INT: return 4;
- case GL_UNSIGNED_INT: return 4;
- case GL_FLOAT: return 4;
- case GL_HALF_FLOAT_OES: return 2;
- case GL_UNSIGNED_SHORT_5_6_5: return 2;
- case GL_UNSIGNED_SHORT_4_4_4_4: return 2;
- case GL_UNSIGNED_SHORT_5_5_5_1: return 2;
- case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: return 2;
- case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: return 2;
- case GL_UNSIGNED_INT_2_10_10_10_REV_EXT: return 4;
- case GL_UNSIGNED_INT_24_8_OES: return 4;
- default: UNREACHABLE(); return 0;
- }
-}
-
-bool IsCompressed(GLenum format)
-{
- if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
- format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
- format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
- format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
- {
- return true;
- }
- else
- {
- return false;
- }
-}
-
-bool IsDepthTexture(GLenum format)
-{
- if (format == GL_DEPTH_COMPONENT ||
- format == GL_DEPTH_STENCIL_OES ||
- format == GL_DEPTH_COMPONENT16 ||
- format == GL_DEPTH_COMPONENT32_OES ||
- format == GL_DEPTH24_STENCIL8_OES)
- {
- return true;
- }
-
- return false;
-}
-
-bool IsStencilTexture(GLenum format)
-{
- if (format == GL_DEPTH_STENCIL_OES ||
- format == GL_DEPTH24_STENCIL8_OES)
- {
- return true;
- }
-
- return false;
-}
-
-void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
-{
- int upsampleCount = 0;
-
- if (isCompressed)
- {
- // Don't expand the size of full textures that are at least 4x4
- // already.
- if (isImage || *requestWidth < 4 || *requestHeight < 4)
- {
- while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0)
- {
- *requestWidth <<= 1;
- *requestHeight <<= 1;
- upsampleCount++;
- }
- }
- }
- *levelOffset = upsampleCount;
-}
-
-// Returns the size, in bytes, of a single texel in an Image
-int ComputePixelSize(GLint internalformat)
-{
- switch (internalformat)
- {
- case GL_ALPHA8_EXT: return sizeof(unsigned char);
- case GL_LUMINANCE8_EXT: return sizeof(unsigned char);
- case GL_ALPHA32F_EXT: return sizeof(float);
- case GL_LUMINANCE32F_EXT: return sizeof(float);
- case GL_ALPHA16F_EXT: return sizeof(unsigned short);
- case GL_LUMINANCE16F_EXT: return sizeof(unsigned short);
- case GL_LUMINANCE8_ALPHA8_EXT: return sizeof(unsigned char) * 2;
- case GL_LUMINANCE_ALPHA32F_EXT: return sizeof(float) * 2;
- case GL_LUMINANCE_ALPHA16F_EXT: return sizeof(unsigned short) * 2;
- case GL_RGB8_OES: return sizeof(unsigned char) * 3;
- case GL_RGB565: return sizeof(unsigned short);
- case GL_RGB32F_EXT: return sizeof(float) * 3;
- case GL_RGB16F_EXT: return sizeof(unsigned short) * 3;
- case GL_RGBA8_OES: return sizeof(unsigned char) * 4;
- case GL_RGBA4: return sizeof(unsigned short);
- case GL_RGB5_A1: return sizeof(unsigned short);
- case GL_RGBA32F_EXT: return sizeof(float) * 4;
- case GL_RGBA16F_EXT: return sizeof(unsigned short) * 4;
- case GL_BGRA8_EXT: return sizeof(unsigned char) * 4;
- case GL_BGRA4_ANGLEX: return sizeof(unsigned short);
- case GL_BGR5_A1_ANGLEX: return sizeof(unsigned short);
- default: UNREACHABLE();
- }
-
- return 0;
-}
-
-bool IsCubemapTextureTarget(GLenum target)
-{
- return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
-}
-
-bool IsInternalTextureTarget(GLenum target)
-{
- return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
-}
-
-GLint ConvertSizedInternalFormat(GLenum format, GLenum type)
-{
- switch (format)
- {
- case GL_ALPHA:
- switch (type)
- {
- case GL_UNSIGNED_BYTE: return GL_ALPHA8_EXT;
- case GL_FLOAT: return GL_ALPHA32F_EXT;
- case GL_HALF_FLOAT_OES: return GL_ALPHA16F_EXT;
- default: UNIMPLEMENTED();
- }
- break;
- case GL_LUMINANCE:
- switch (type)
- {
- case GL_UNSIGNED_BYTE: return GL_LUMINANCE8_EXT;
- case GL_FLOAT: return GL_LUMINANCE32F_EXT;
- case GL_HALF_FLOAT_OES: return GL_LUMINANCE16F_EXT;
- default: UNIMPLEMENTED();
- }
- break;
- case GL_LUMINANCE_ALPHA:
- switch (type)
- {
- case GL_UNSIGNED_BYTE: return GL_LUMINANCE8_ALPHA8_EXT;
- case GL_FLOAT: return GL_LUMINANCE_ALPHA32F_EXT;
- case GL_HALF_FLOAT_OES: return GL_LUMINANCE_ALPHA16F_EXT;
- default: UNIMPLEMENTED();
- }
- break;
- case GL_RGB:
- switch (type)
- {
- case GL_UNSIGNED_BYTE: return GL_RGB8_OES;
- case GL_UNSIGNED_SHORT_5_6_5: return GL_RGB565;
- case GL_FLOAT: return GL_RGB32F_EXT;
- case GL_HALF_FLOAT_OES: return GL_RGB16F_EXT;
- default: UNIMPLEMENTED();
- }
- break;
- case GL_RGBA:
- switch (type)
- {
- case GL_UNSIGNED_BYTE: return GL_RGBA8_OES;
- case GL_UNSIGNED_SHORT_4_4_4_4: return GL_RGBA4;
- case GL_UNSIGNED_SHORT_5_5_5_1: return GL_RGB5_A1;
- case GL_FLOAT: return GL_RGBA32F_EXT;
- case GL_HALF_FLOAT_OES: return GL_RGBA16F_EXT;
- break;
- default: UNIMPLEMENTED();
- }
- break;
- case GL_BGRA_EXT:
- switch (type)
- {
- case GL_UNSIGNED_BYTE: return GL_BGRA8_EXT;
- case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: return GL_BGRA4_ANGLEX;
- case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: return GL_BGR5_A1_ANGLEX;
- default: UNIMPLEMENTED();
- }
- 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:
- return format;
- case GL_DEPTH_COMPONENT:
- switch (type)
- {
- case GL_UNSIGNED_SHORT: return GL_DEPTH_COMPONENT16;
- case GL_UNSIGNED_INT: return GL_DEPTH_COMPONENT32_OES;
- default: UNIMPLEMENTED();
- }
- break;
- case GL_DEPTH_STENCIL_OES:
- switch (type)
- {
- case GL_UNSIGNED_INT_24_8_OES: return GL_DEPTH24_STENCIL8_OES;
- default: UNIMPLEMENTED();
- }
- break;
- default:
- UNIMPLEMENTED();
- }
-
- return GL_NONE;
-}
-
-GLenum ExtractFormat(GLenum internalformat)
-{
- switch (internalformat)
- {
- case GL_RGB565: return GL_RGB;
- case GL_RGBA4: return GL_RGBA;
- case GL_RGB5_A1: return GL_RGBA;
- case GL_RGB8_OES: return GL_RGB;
- case GL_RGBA8_OES: return GL_RGBA;
- case GL_LUMINANCE8_ALPHA8_EXT: return GL_LUMINANCE_ALPHA;
- case GL_LUMINANCE8_EXT: return GL_LUMINANCE;
- case GL_ALPHA8_EXT: return GL_ALPHA;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
- case GL_RGBA32F_EXT: return GL_RGBA;
- case GL_RGB32F_EXT: return GL_RGB;
- case GL_ALPHA32F_EXT: return GL_ALPHA;
- case GL_LUMINANCE32F_EXT: return GL_LUMINANCE;
- case GL_LUMINANCE_ALPHA32F_EXT: return GL_LUMINANCE_ALPHA;
- case GL_RGBA16F_EXT: return GL_RGBA;
- case GL_RGB16F_EXT: return GL_RGB;
- case GL_ALPHA16F_EXT: return GL_ALPHA;
- case GL_LUMINANCE16F_EXT: return GL_LUMINANCE;
- case GL_LUMINANCE_ALPHA16F_EXT: return GL_LUMINANCE_ALPHA;
- case GL_BGRA8_EXT: return GL_BGRA_EXT;
- case GL_DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT;
- case GL_DEPTH_COMPONENT32_OES: return GL_DEPTH_COMPONENT;
- case GL_DEPTH24_STENCIL8_OES: return GL_DEPTH_STENCIL_OES;
- default: return GL_NONE; // Unsupported
- }
-}
-
-GLenum ExtractType(GLenum internalformat)
-{
- switch (internalformat)
- {
- case GL_RGB565: return GL_UNSIGNED_SHORT_5_6_5;
- case GL_RGBA4: return GL_UNSIGNED_SHORT_4_4_4_4;
- case GL_RGB5_A1: return GL_UNSIGNED_SHORT_5_5_5_1;
- case GL_RGB8_OES: return GL_UNSIGNED_BYTE;
- case GL_RGBA8_OES: return GL_UNSIGNED_BYTE;
- case GL_LUMINANCE8_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
- case GL_LUMINANCE8_EXT: return GL_UNSIGNED_BYTE;
- case GL_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE;
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_UNSIGNED_BYTE;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_UNSIGNED_BYTE;
- case GL_RGBA32F_EXT: return GL_FLOAT;
- case GL_RGB32F_EXT: return GL_FLOAT;
- case GL_ALPHA32F_EXT: return GL_FLOAT;
- case GL_LUMINANCE32F_EXT: return GL_FLOAT;
- case GL_LUMINANCE_ALPHA32F_EXT: return GL_FLOAT;
- case GL_RGBA16F_EXT: return GL_HALF_FLOAT_OES;
- case GL_RGB16F_EXT: return GL_HALF_FLOAT_OES;
- case GL_ALPHA16F_EXT: return GL_HALF_FLOAT_OES;
- case GL_LUMINANCE16F_EXT: return GL_HALF_FLOAT_OES;
- case GL_LUMINANCE_ALPHA16F_EXT: return GL_HALF_FLOAT_OES;
- case GL_BGRA8_EXT: return GL_UNSIGNED_BYTE;
- case GL_DEPTH_COMPONENT16: return GL_UNSIGNED_SHORT;
- case GL_DEPTH_COMPONENT32_OES: return GL_UNSIGNED_INT;
- case GL_DEPTH24_STENCIL8_OES: return GL_UNSIGNED_INT_24_8_OES;
- default: return GL_NONE; // Unsupported
- }
-}
-
-bool IsColorRenderable(GLenum internalformat)
-{
- switch (internalformat)
- {
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGB565:
- case GL_RGB8_OES:
- case GL_RGBA8_OES:
- return true;
- case GL_DEPTH_COMPONENT16:
- case GL_STENCIL_INDEX8:
- case GL_DEPTH24_STENCIL8_OES:
- return false;
- case GL_BGRA8_EXT:
- return true;
- default:
- UNIMPLEMENTED();
- }
-
- return false;
-}
-
-bool IsDepthRenderable(GLenum internalformat)
-{
- switch (internalformat)
- {
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH24_STENCIL8_OES:
- return true;
- case GL_STENCIL_INDEX8:
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGB565:
- case GL_RGB8_OES:
- case GL_RGBA8_OES:
- return false;
- default:
- UNIMPLEMENTED();
- }
-
- return false;
-}
-
-bool IsStencilRenderable(GLenum internalformat)
-{
- switch (internalformat)
- {
- case GL_STENCIL_INDEX8:
- case GL_DEPTH24_STENCIL8_OES:
- return true;
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGB565:
- case GL_RGB8_OES:
- case GL_RGBA8_OES:
- case GL_DEPTH_COMPONENT16:
- return false;
- default:
- UNIMPLEMENTED();
- }
-
- return false;
-}
-
-bool IsFloat32Format(GLint internalformat)
-{
- switch (internalformat)
- {
- case GL_RGBA32F_EXT:
- case GL_RGB32F_EXT:
- case GL_ALPHA32F_EXT:
- case GL_LUMINANCE32F_EXT:
- case GL_LUMINANCE_ALPHA32F_EXT:
- return true;
- default:
- return false;
- }
-}
-
-bool IsFloat16Format(GLint internalformat)
-{
- switch (internalformat)
- {
- case GL_RGBA16F_EXT:
- case GL_RGB16F_EXT:
- case GL_ALPHA16F_EXT:
- case GL_LUMINANCE16F_EXT:
- case GL_LUMINANCE_ALPHA16F_EXT:
- return true;
- default:
- return false;
- }
-}
-
-unsigned int GetAlphaSize(GLenum colorFormat)
-{
- switch (colorFormat)
- {
- case GL_RGBA16F_EXT:
- return 16;
- case GL_RGBA32F_EXT:
- return 32;
- case GL_RGBA4:
- return 4;
- case GL_RGBA8_OES:
- case GL_BGRA8_EXT:
- return 8;
- case GL_RGB5_A1:
- return 1;
- case GL_RGB8_OES:
- case GL_RGB565:
- case GL_RGB32F_EXT:
- case GL_RGB16F_EXT:
- return 0;
- default:
- return 0;
- }
-}
-
-unsigned int GetRedSize(GLenum colorFormat)
-{
- switch (colorFormat)
- {
- case GL_RGBA16F_EXT:
- case GL_RGB16F_EXT:
- return 16;
- case GL_RGBA32F_EXT:
- case GL_RGB32F_EXT:
- return 32;
- case GL_RGBA4:
- return 4;
- case GL_RGBA8_OES:
- case GL_BGRA8_EXT:
- case GL_RGB8_OES:
- return 8;
- case GL_RGB5_A1:
- case GL_RGB565:
- return 5;
- default:
- return 0;
- }
-}
-
-unsigned int GetGreenSize(GLenum colorFormat)
-{
- switch (colorFormat)
- {
- case GL_RGBA16F_EXT:
- case GL_RGB16F_EXT:
- return 16;
- case GL_RGBA32F_EXT:
- case GL_RGB32F_EXT:
- return 32;
- case GL_RGBA4:
- return 4;
- case GL_RGBA8_OES:
- case GL_BGRA8_EXT:
- case GL_RGB8_OES:
- return 8;
- case GL_RGB5_A1:
- return 5;
- case GL_RGB565:
- return 6;
- default:
- return 0;
- }
-}
-
-unsigned int GetBlueSize(GLenum colorFormat)
-{
- switch (colorFormat)
- {
- case GL_RGBA16F_EXT:
- case GL_RGB16F_EXT:
- return 16;
- case GL_RGBA32F_EXT:
- case GL_RGB32F_EXT:
- return 32;
- case GL_RGBA4:
- return 4;
- case GL_RGBA8_OES:
- case GL_BGRA8_EXT:
- case GL_RGB8_OES:
- return 8;
- case GL_RGB5_A1:
- case GL_RGB565:
- return 5;
- default:
- return 0;
- }
-}
-
-unsigned int GetDepthSize(GLenum depthFormat)
-{
- switch (depthFormat)
- {
- case GL_DEPTH_COMPONENT16: return 16;
- case GL_DEPTH_COMPONENT32_OES: return 32;
- case GL_DEPTH24_STENCIL8_OES: return 24;
- default: return 0;
- }
-}
-
-unsigned int GetStencilSize(GLenum stencilFormat)
-{
- switch (stencilFormat)
- {
- case GL_DEPTH24_STENCIL8_OES: return 8;
- default: return 0;
- }
-}
-
-bool IsTriangleMode(GLenum drawMode)
-{
- switch (drawMode)
- {
- case GL_TRIANGLES:
- case GL_TRIANGLE_FAN:
- case GL_TRIANGLE_STRIP:
- return true;
- case GL_POINTS:
- case GL_LINES:
- case GL_LINE_LOOP:
- case GL_LINE_STRIP:
- return false;
- default: UNREACHABLE();
- }
-
- return false;
-}
-
-}
-
-std::string getTempPath()
-{
-#if !defined(ANGLE_OS_WINRT)
- char path[MAX_PATH];
- DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
- if (pathLen == 0)
- {
- UNREACHABLE();
- return std::string();
- }
-
- UINT unique = GetTempFileNameA(path, "sh", 0, path);
- if (unique == 0)
- {
- UNREACHABLE();
- return std::string();
- }
-#else
- static std::string path;
-
- while (path.empty()) {
- ComPtr<IApplicationDataStatics> factory;
- Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData);
- HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory));
- if (FAILED(result))
- break;
-
- ComPtr<IApplicationData> applicationData;
- result = factory->get_Current(&applicationData);
- if (FAILED(result))
- break;
-
- ComPtr<IStorageFolder> storageFolder;
- result = applicationData->get_LocalFolder(&storageFolder);
- if (FAILED(result))
- break;
-
- ComPtr<IStorageItem> localFolder;
- result = storageFolder.As(&localFolder);
- if (FAILED(result))
- break;
-
- HSTRING localFolderPath;
- result = localFolder->get_Path(&localFolderPath);
- if (FAILED(result))
- break;
-
- std::wstring_convert< std::codecvt_utf8<wchar_t> > converter;
- path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL));
- if (path.empty())
- {
- UNREACHABLE();
- break;
- }
- }
-#endif
-
- return path;
-}
-
-void writeFile(const char* path, const void* content, size_t size)
-{
- FILE* file = fopen(path, "w");
- if (!file)
- {
- UNREACHABLE();
- return;
- }
-
- fwrite(content, sizeof(char), size, file);
- fclose(file);
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.h b/src/3rdparty/angle/src/libGLESv2/utilities.h
deleted file mode 100644
index ed663ebca2..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/utilities.h
+++ /dev/null
@@ -1,67 +0,0 @@
-//
-// 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.
-//
-
-// utilities.h: Conversion functions and other utility routines.
-
-#ifndef LIBGLESV2_UTILITIES_H
-#define LIBGLESV2_UTILITIES_H
-
-#define GL_APICALL
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <string>
-
-namespace gl
-{
-
-struct Color;
-
-int UniformComponentCount(GLenum type);
-GLenum UniformComponentType(GLenum type);
-size_t UniformInternalSize(GLenum type);
-size_t UniformExternalSize(GLenum type);
-int VariableRowCount(GLenum type);
-int VariableColumnCount(GLenum type);
-
-int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
-
-void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset);
-int ComputePixelSize(GLint internalformat);
-GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment);
-GLsizei ComputeCompressedPitch(GLsizei width, GLenum format);
-GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format);
-GLsizei ComputeTypeSize(GLenum type);
-bool IsCompressed(GLenum format);
-bool IsDepthTexture(GLenum format);
-bool IsStencilTexture(GLenum format);
-bool IsCubemapTextureTarget(GLenum target);
-bool IsInternalTextureTarget(GLenum target);
-GLint ConvertSizedInternalFormat(GLenum format, GLenum type);
-GLenum ExtractFormat(GLenum internalformat);
-GLenum ExtractType(GLenum internalformat);
-
-bool IsColorRenderable(GLenum internalformat);
-bool IsDepthRenderable(GLenum internalformat);
-bool IsStencilRenderable(GLenum internalformat);
-
-bool IsFloat32Format(GLint internalformat);
-bool IsFloat16Format(GLint internalformat);
-
-GLuint GetAlphaSize(GLenum colorFormat);
-GLuint GetRedSize(GLenum colorFormat);
-GLuint GetGreenSize(GLenum colorFormat);
-GLuint GetBlueSize(GLenum colorFormat);
-GLuint GetDepthSize(GLenum depthFormat);
-GLuint GetStencilSize(GLenum stencilFormat);
-bool IsTriangleMode(GLenum drawMode);
-
-}
-
-std::string getTempPath();
-void writeFile(const char* path, const void* data, size_t size);
-
-#endif // LIBGLESV2_UTILITIES_H
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.cpp b/src/3rdparty/angle/src/libGLESv2/validationES.cpp
new file mode 100644
index 0000000000..f79bc97e4f
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/validationES.cpp
@@ -0,0 +1,1920 @@
+//
+// 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 "libGLESv2/validationES.h"
+#include "libGLESv2/validationES2.h"
+#include "libGLESv2/validationES3.h"
+#include "libGLESv2/Context.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
+#include "libGLESv2/formatutils.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/Query.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/TransformFeedback.h"
+#include "libGLESv2/VertexArray.h"
+#include "libGLESv2/renderer/BufferImpl.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+namespace gl
+{
+
+bool ValidCap(const Context *context, GLenum cap)
+{
+ switch (cap)
+ {
+ 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->getClientVersion() >= 3);
+ default:
+ return false;
+ }
+}
+
+bool ValidTextureTarget(const Context *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->getClientVersion() >= 3);
+
+ default:
+ return false;
+ }
+}
+
+// This function differs from ValidTextureTarget in that the target must be
+// usable as the destination of a 2D operation-- so a cube face is valid, but
+// GL_TEXTURE_CUBE_MAP is not.
+// Note: duplicate of IsInternalTextureTarget
+bool ValidTexture2DDestinationTarget(const Context *context, 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;
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_3D:
+ return (context->getClientVersion() >= 3);
+ default:
+ return false;
+ }
+}
+
+bool ValidFramebufferTarget(GLenum target)
+{
+ META_ASSERT(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER);
+
+ 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 Context *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;
+
+ case GL_COPY_READ_BUFFER:
+ case GL_COPY_WRITE_BUFFER:
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ case GL_UNIFORM_BUFFER:
+ return (context->getClientVersion() >= 3);
+
+ default:
+ return false;
+ }
+}
+
+bool ValidBufferParameter(const Context *context, GLenum pname)
+{
+ switch (pname)
+ {
+ case GL_BUFFER_USAGE:
+ case GL_BUFFER_SIZE:
+ return true;
+
+ // GL_BUFFER_MAP_POINTER is a special case, and may only be
+ // queried with GetBufferPointerv
+ case GL_BUFFER_ACCESS_FLAGS:
+ case GL_BUFFER_MAPPED:
+ case GL_BUFFER_MAP_OFFSET:
+ case GL_BUFFER_MAP_LENGTH:
+ return (context->getClientVersion() >= 3);
+
+ default:
+ return false;
+ }
+}
+
+bool ValidMipLevel(const Context *context, GLenum target, GLint level)
+{
+ size_t maxDimension = 0;
+ switch (target)
+ {
+ case GL_TEXTURE_2D: maxDimension = context->getCaps().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 = context->getCaps().maxCubeMapTextureSize; break;
+ case GL_TEXTURE_3D: maxDimension = context->getCaps().max3DTextureSize; break;
+ case GL_TEXTURE_2D_ARRAY: maxDimension = context->getCaps().max2DTextureSize; break;
+ default: UNREACHABLE();
+ }
+
+ return level <= gl::log2(maxDimension);
+}
+
+bool ValidImageSize(const Context *context, GLenum target, GLint level,
+ GLsizei width, GLsizei height, GLsizei depth)
+{
+ if (level < 0 || width < 0 || height < 0 || depth < 0)
+ {
+ return false;
+ }
+
+ if (!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 ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height)
+{
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ if (!formatInfo.compressed)
+ {
+ return false;
+ }
+
+ if (width < 0 || (static_cast<GLuint>(width) > formatInfo.compressedBlockWidth && width % formatInfo.compressedBlockWidth != 0) ||
+ height < 0 || (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight && height % formatInfo.compressedBlockHeight != 0))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidQueryType(const Context *context, GLenum queryType)
+{
+ META_ASSERT(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT);
+ META_ASSERT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT);
+
+ switch (queryType)
+ {
+ case GL_ANY_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ return true;
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ return (context->getClientVersion() >= 3);
+ default:
+ return false;
+ }
+}
+
+bool ValidProgram(Context *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."
+
+ if (context->getProgram(id) != NULL)
+ {
+ return true;
+ }
+ else if (context->getShader(id) != NULL)
+ {
+ // ID is the wrong type
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ // No shader/program object has this ID
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+}
+
+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->recordError(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->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateRenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height,
+ bool angleExtension)
+{
+ switch (target)
+ {
+ case GL_RENDERBUFFER:
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (width < 0 || height < 0 || samples < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (!formatCaps.renderable)
+ {
+ context->recordError(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. The ES3 spec (section 4.4.2) does, however, state 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.pixelBytes == 0)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
+ // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2)
+ // states that samples must be less than or equal to the maximum samples for the specified
+ // internal format.
+ if (angleExtension)
+ {
+ ASSERT(context->getExtensions().framebufferMultisample);
+ if (static_cast<GLuint>(samples) > context->getExtensions().maxSamples)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ // Check if this specific format supports enough samples
+ if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+ {
+ context->recordError(Error(GL_OUT_OF_MEMORY));
+ return false;
+ }
+ }
+ else
+ {
+ if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+
+ GLuint handle = context->getState().getRenderbufferId();
+ if (handle == 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
+ GLenum renderbuffertarget, GLuint renderbuffer)
+{
+ if (!ValidFramebufferTarget(target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id();
+
+ if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ 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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool IsPartialBlit(gl::Context *context, gl::FramebufferAttachment *readBuffer, gl::FramebufferAttachment *writeBuffer,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
+{
+ if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 ||
+ dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() ||
+ srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight())
+ {
+ return true;
+ }
+ else if (context->getState().isScissorTestEnabled())
+ {
+ const Rectangle &scissor = context->getState().getScissor();
+
+ return scissor.x > 0 || scissor.y > 0 ||
+ scissor.width < writeBuffer->getWidth() ||
+ scissor.height < writeBuffer->getHeight();
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
+ GLenum filter, bool fromAngleExtension)
+{
+ switch (filter)
+ {
+ case GL_NEAREST:
+ break;
+ case GL_LINEAR:
+ if (fromAngleExtension)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
+ {
+ context->recordError(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;
+ }
+
+ if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0))
+ {
+ ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.");
+ context->recordError(Error(GL_INVALID_OPERATION));
+ 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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (context->getState().getReadFramebuffer()->id() == context->getState().getDrawFramebuffer()->id())
+ {
+ if (fromAngleExtension)
+ {
+ ERR("Blits with the same source and destination framebuffer are not supported by this "
+ "implementation.");
+ }
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
+ gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
+ if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
+ !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if (drawFramebuffer->getSamples() != 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
+
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
+ gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
+
+ if (readColorBuffer && drawColorBuffer)
+ {
+ GLenum readInternalFormat = readColorBuffer->getActualFormat();
+ const InternalFormat &readFormatInfo = GetInternalFormatInfo(readInternalFormat);
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
+ {
+ if (drawFramebuffer->isEnabledColorAttachment(i))
+ {
+ GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat();
+ const InternalFormat &drawFormatInfo = GetInternalFormatInfo(drawInternalFormat);
+
+ // 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
+ if ( (readFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || readFormatInfo.componentType == GL_SIGNED_NORMALIZED) &&
+ !(drawFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || drawFormatInfo.componentType == GL_SIGNED_NORMALIZED))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (readFormatInfo.componentType == GL_UNSIGNED_INT && drawFormatInfo.componentType != GL_UNSIGNED_INT)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (readFormatInfo.componentType == GL_INT && drawFormatInfo.componentType != GL_INT)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+
+ if ((readFormatInfo.componentType == GL_INT || readFormatInfo.componentType == GL_UNSIGNED_INT) && filter == GL_LINEAR)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (fromAngleExtension)
+ {
+ const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
+ if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ {
+ if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
+ {
+ FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(colorAttachment);
+ ASSERT(attachment);
+
+ if (attachment->type() != GL_TEXTURE_2D && attachment->type() != GL_RENDERBUFFER)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (attachment->getActualFormat() != readColorBuffer->getActualFormat())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+ if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT)
+ {
+ gl::FramebufferAttachment *readDepthBuffer = readFramebuffer->getDepthbuffer();
+ gl::FramebufferAttachment *drawDepthBuffer = drawFramebuffer->getDepthbuffer();
+
+ if (readDepthBuffer && drawDepthBuffer)
+ {
+ if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (readDepthBuffer->getSamples() > 0 && !sameBounds)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (fromAngleExtension)
+ {
+ if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer,
+ srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
+ {
+ ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
+ context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted
+ return false;
+ }
+
+ if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT)
+ {
+ gl::FramebufferAttachment *readStencilBuffer = readFramebuffer->getStencilbuffer();
+ gl::FramebufferAttachment *drawStencilBuffer = drawFramebuffer->getStencilbuffer();
+
+ if (readStencilBuffer && drawStencilBuffer)
+ {
+ if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (readStencilBuffer->getSamples() > 0 && !sameBounds)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (fromAngleExtension)
+ {
+ if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer,
+ srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
+ {
+ ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
+ context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted
+ return false;
+ }
+
+ if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetVertexAttribParameters(Context *context, GLenum pname)
+{
+ 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:
+ return true;
+
+ case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
+ // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
+ // the same constant.
+ META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
+ return true;
+
+ case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ return true;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+}
+
+bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param)
+{
+ 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->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ default: break;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ switch (param)
+ {
+ case GL_REPEAT:
+ case GL_CLAMP_TO_EDGE:
+ case GL_MIRRORED_REPEAT:
+ return true;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ case GL_TEXTURE_MIN_FILTER:
+ switch (param)
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ return true;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAG_FILTER:
+ switch (param)
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ return true;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_USAGE_ANGLE:
+ switch (param)
+ {
+ case GL_NONE:
+ case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
+ return true;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->getExtensions().textureFilterAnisotropic)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ // we assume the parameter passed to this validation method is truncated, not rounded
+ if (param < 1)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ return true;
+
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ // any value is permissible
+ return true;
+
+ case GL_TEXTURE_COMPARE_MODE:
+ // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
+ switch (param)
+ {
+ case GL_NONE:
+ case GL_COMPARE_REF_TO_TEXTURE:
+ return true;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_COMPARE_FUNC:
+ // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
+ switch (param)
+ {
+ case GL_LEQUAL:
+ case GL_GEQUAL:
+ case GL_LESS:
+ case GL_GREATER:
+ case GL_EQUAL:
+ case GL_NOTEQUAL:
+ case GL_ALWAYS:
+ case GL_NEVER:
+ return true;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SWIZZLE_R:
+ case GL_TEXTURE_SWIZZLE_G:
+ case GL_TEXTURE_SWIZZLE_B:
+ case GL_TEXTURE_SWIZZLE_A:
+ switch (param)
+ {
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_ZERO:
+ case GL_ONE:
+ return true;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ if (param < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ return true;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+}
+
+bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname)
+{
+ switch (pname)
+ {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_COMPARE_MODE:
+ case GL_TEXTURE_COMPARE_FUNC:
+ return true;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+}
+
+bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels)
+{
+ gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
+ ASSERT(framebuffer);
+
+ if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!framebuffer->getReadColorbuffer())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ GLenum currentInternalFormat, currentFormat, currentType;
+ GLuint clientVersion = context->getClientVersion();
+
+ context->getCurrentReadFormatType(&currentInternalFormat, &currentFormat, &currentType);
+
+ bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(context, format, type) :
+ ValidES3ReadFormatType(context, currentInternalFormat, format, type);
+
+ if (!(currentFormat == format && currentType == type) && !validReadFormat)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
+ const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat);
+
+ GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment());
+ // sized query sanity check
+ if (bufSize)
+ {
+ int requiredSize = outputPitch * height;
+ if (requiredSize > *bufSize)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
+{
+ if (!ValidQueryType(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (id == 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
+ // of zero, if the active query object name for <target> is non-zero (for the
+ // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
+ // the active query for either target is non-zero), if <id> is the name of an
+ // existing query object whose type does not match <target>, or if <id> is the
+ // active query object name for any query type, the error INVALID_OPERATION is
+ // generated.
+
+ // Ensure no other queries are active
+ // NOTE: If other queries than occlusion are supported, we will need to check
+ // separately that:
+ // a) The query ID passed is not the current active query for any target/type
+ // b) There are no active queries for the requested target (and in the case
+ // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
+ // no query may be active for either if glBeginQuery targets either.
+ if (context->getState().isQueryActive())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ Query *queryObject = context->getQuery(id, true, target);
+
+ // check that name was obtained with glGenQueries
+ if (!queryObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // check for type mismatch
+ if (queryObject->getType() != target)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateEndQuery(gl::Context *context, GLenum target)
+{
+ if (!ValidQueryType(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ const Query *queryObject = context->getState().getActiveQuery(target);
+
+ if (queryObject == NULL)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniformType,
+ GLint location, GLsizei count, LinkedUniform **uniformOut)
+{
+ if (count < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
+ if (!programBinary)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (location == -1)
+ {
+ // Silently ignore the uniform command
+ return false;
+ }
+
+ if (!programBinary->isValidUniformLocation(location))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ LinkedUniform *uniform = programBinary->getUniformByLocation(location);
+
+ // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+ if (uniform->elementCount() == 1 && count > 1)
+ {
+ context->recordError(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->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ LinkedUniform *uniform = NULL;
+ if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
+ {
+ return false;
+ }
+
+ GLenum targetBoolType = VariableBoolVectorType(uniformType);
+ bool samplerUniformCheck = (IsSampler(uniform->type) && uniformType == GL_INT);
+ if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
+ {
+ context->recordError(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->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (transpose != GL_FALSE && context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ LinkedUniform *uniform = NULL;
+ if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
+ {
+ return false;
+ }
+
+ if (uniform->type != matrixType)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
+{
+ if (!context->getQueryParameterInfo(pname, nativeType, numParams))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
+ {
+ unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
+
+ if (colorAttachment >= context->getCaps().maxDrawBuffers)
+ {
+ context->recordError(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:
+ if (context->getState().getActiveSampler() >= context->getCaps().maxCombinedTextureImageUnits)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ {
+ Framebuffer *framebuffer = context->getState().getReadFramebuffer();
+ ASSERT(framebuffer);
+ if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
+ if (!attachment)
+ {
+ context->recordError(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 ValidateCopyTexImageParametersBase(gl::Context* 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, GLenum *textureFormatOut)
+{
+
+ if (!ValidTexture2DDestinationTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (border != 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (!ValidMipLevel(context, target, level))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
+ if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+
+ gl::Texture *texture = NULL;
+ GLenum textureInternalFormat = GL_NONE;
+ GLint textureLevelWidth = 0;
+ GLint textureLevelHeight = 0;
+ GLint textureLevelDepth = 0;
+ GLuint maxDimension = 0;
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ {
+ gl::Texture2D *texture2d = context->getTexture2D();
+ if (texture2d)
+ {
+ textureInternalFormat = texture2d->getInternalFormat(level);
+ textureLevelWidth = texture2d->getWidth(level);
+ textureLevelHeight = texture2d->getHeight(level);
+ textureLevelDepth = 1;
+ texture = texture2d;
+ 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:
+ {
+ gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
+ if (textureCube)
+ {
+ textureInternalFormat = textureCube->getInternalFormat(target, level);
+ textureLevelWidth = textureCube->getWidth(target, level);
+ textureLevelHeight = textureCube->getHeight(target, level);
+ textureLevelDepth = 1;
+ texture = textureCube;
+ maxDimension = caps.maxCubeMapTextureSize;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ gl::Texture2DArray *texture2dArray = context->getTexture2DArray();
+ if (texture2dArray)
+ {
+ textureInternalFormat = texture2dArray->getInternalFormat(level);
+ textureLevelWidth = texture2dArray->getWidth(level);
+ textureLevelHeight = texture2dArray->getHeight(level);
+ textureLevelDepth = texture2dArray->getLayers(level);
+ texture = texture2dArray;
+ maxDimension = caps.max2DTextureSize;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_3D:
+ {
+ gl::Texture3D *texture3d = context->getTexture3D();
+ if (texture3d)
+ {
+ textureInternalFormat = texture3d->getInternalFormat(level);
+ textureLevelWidth = texture3d->getWidth(level);
+ textureLevelHeight = texture3d->getHeight(level);
+ textureLevelDepth = texture3d->getDepth(level);
+ texture = texture3d;
+ maxDimension = caps.max3DTextureSize;
+ }
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (!texture)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (texture->isImmutable() && !isSubImage)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+
+ if (formatInfo.depthBits > 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (formatInfo.compressed)
+ {
+ if (((width % formatInfo.compressedBlockWidth) != 0 && width != textureLevelWidth) ||
+ ((height % formatInfo.compressedBlockHeight) != 0 && height != textureLevelHeight))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ if (isSubImage)
+ {
+ if (xoffset + width > textureLevelWidth ||
+ yoffset + height > textureLevelHeight ||
+ zoffset >= textureLevelDepth)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ else
+ {
+ if (IsCubemapTextureTarget(target) && width != height)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ int maxLevelDimension = (maxDimension >> level);
+ if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+
+ *textureFormatOut = textureInternalFormat;
+ return true;
+}
+
+static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsizei maxVertex, 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->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (count < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ const State &state = context->getState();
+
+ // Check for mapped buffers
+ if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+ if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
+ state.getStencilRef() != state.getStencilBackRef() ||
+ depthStencilState.stencilMask != depthStencilState.stencilBackMask)
+ {
+ // 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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::Framebuffer *fbo = state.getDrawFramebuffer();
+ if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if (state.getCurrentProgramId() == 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ gl::ProgramBinary *programBinary = state.getCurrentProgramBinary();
+ if (!programBinary->validateSamplers(NULL, context->getCaps()))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Buffer validations
+ const VertexArray *vao = state.getVertexArray();
+ for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
+ bool attribActive = (programBinary->getSemanticIndex(attributeIndex) != -1);
+ if (attribActive && 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);
+ }
+
+ GLint64 attribDataSize = maxVertexElement * attribStride;
+
+ // [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 > buffer->getSize())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ 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->recordError(Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
+ return false;
+ }
+ }
+ }
+
+ // No-op if zero count
+ return (count > 0);
+}
+
+bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+{
+ if (first < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ const State &state = context->getState();
+ gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused() &&
+ curTransformFeedback->getDrawMode() != 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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!ValidateDrawBase(context, mode, count, count, primcount))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+{
+ if (primcount < 0)
+ {
+ context->recordError(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->getState();
+
+ gl::ProgramBinary *programBinary = state.getCurrentProgramBinary();
+
+ const VertexArray *vao = state.getVertexArray();
+ for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
+ bool active = (programBinary->getSemanticIndex(attributeIndex) != -1);
+ if (active && attrib.divisor == 0)
+ {
+ return true;
+ }
+ }
+
+ context->recordError(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(Context *context, GLenum mode, GLsizei count, GLenum type,
+ const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT:
+ break;
+ case GL_UNSIGNED_INT:
+ if (!context->getExtensions().elementIndexUint)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ const State &state = context->getState();
+
+ gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isStarted() && !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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Check for mapped buffers
+ if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::VertexArray *vao = state.getVertexArray();
+ const gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
+ if (!indices && !elementArrayBuffer)
+ {
+ context->recordError(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->recordError(Error(GL_OUT_OF_MEMORY));
+ return false;
+ }
+
+ // Check for reading past the end of the bound buffer object
+ if (byteCount > elementArrayBuffer->getSize())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ else if (!indices)
+ {
+ // Catch this programming error here
+ context->recordError(Error(GL_INVALID_OPERATION));
+ 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)
+ {
+ GLint64 offset = reinterpret_cast<GLint64>(indices);
+ if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL))
+ {
+ const void *dataPointer = elementArrayBuffer->getImplementation()->getData();
+ const uint8_t *offsetPointer = static_cast<const uint8_t *>(dataPointer) + offset;
+ *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count);
+ }
+ }
+ else
+ {
+ *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, indices, count);
+ }
+
+ if (!ValidateDrawBase(context, mode, count, static_cast<GLsizei>(indexRangeOut->end), primcount))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawElementsInstanced(Context *context,
+ GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLsizei primcount,
+ rx::RangeUI *indexRangeOut)
+{
+ if (primcount < 0)
+ {
+ context->recordError(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, rx::RangeUI *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->recordError(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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (level < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+
+ const gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id();
+
+ if (framebufferHandle == 0 || !framebuffer)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ 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 in ES2
+ if (context->getClientVersion() < 3 && level != 0)
+ {
+ context->recordError(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->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ if (tex->getTarget() != GL_TEXTURE_2D)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
+ if (tex2d->isCompressed(level))
+ {
+ context->recordError(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->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
+ if (texcube->isCompressed(textarget, level))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
+{
+ if (program == 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject || !programObject->isLinked())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+ if (!programBinary)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!programBinary->isValidUniformLocation(location))
+ {
+ context->recordError(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)
+{
+ if (!ValidateGetUniformBase(context, program, location))
+ {
+ return false;
+ }
+
+ gl::Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+ gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+
+ // sized queries -- ensure the provided buffer is large enough
+ LinkedUniform *uniform = programBinary->getUniformByLocation(location);
+ size_t requiredBytes = VariableExternalSize(uniform->type);
+ if (static_cast<size_t>(bufSize) < requiredBytes)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+{
+ return ValidateSizedGetUniform(context, program, location, bufSize);
+}
+
+bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
+{
+ return ValidateSizedGetUniform(context, program, location, bufSize);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.h b/src/3rdparty/angle/src/libGLESv2/validationES.h
new file mode 100644
index 0000000000..1fdb633cb6
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/validationES.h
@@ -0,0 +1,92 @@
+//
+// 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 LIBGLESV2_VALIDATION_ES_H
+#define LIBGLESV2_VALIDATION_ES_H
+
+#include "common/mathutil.h"
+
+#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
+
+namespace gl
+{
+
+class Context;
+
+bool ValidCap(const Context *context, GLenum cap);
+bool ValidTextureTarget(const Context *context, GLenum target);
+bool ValidTexture2DDestinationTarget(const Context *context, GLenum target);
+bool ValidFramebufferTarget(GLenum target);
+bool ValidBufferTarget(const Context *context, GLenum target);
+bool ValidBufferParameter(const Context *context, GLenum pname);
+bool ValidMipLevel(const Context *context, GLenum target, GLint level);
+bool ValidImageSize(const Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth);
+bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height);
+bool ValidQueryType(const Context *context, GLenum queryType);
+bool ValidProgram(Context *context, GLuint id);
+
+bool ValidateAttachmentTarget(Context *context, GLenum attachment);
+bool ValidateRenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height,
+ bool angleExtension);
+bool ValidateFramebufferRenderbufferParameters(Context *context, GLenum target, GLenum attachment,
+ GLenum renderbuffertarget, GLuint renderbuffer);
+
+bool ValidateBlitFramebufferParameters(Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
+ GLenum filter, bool fromAngleExtension);
+
+bool ValidateGetVertexAttribParameters(Context *context, GLenum pname);
+
+bool ValidateTexParamParameters(Context *context, GLenum pname, GLint param);
+
+bool ValidateSamplerObjectParameter(Context *context, GLenum pname);
+
+bool ValidateReadPixelsParameters(Context *context, GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels);
+
+bool ValidateBeginQuery(Context *context, GLenum target, GLuint id);
+bool ValidateEndQuery(Context *context, GLenum target);
+
+bool ValidateUniform(Context *context, GLenum uniformType, GLint location, GLsizei count);
+bool ValidateUniformMatrix(Context *context, GLenum matrixType, GLint location, GLsizei count,
+ GLboolean transpose);
+
+bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams);
+
+bool ValidateCopyTexImageParametersBase(Context* 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, GLenum *textureInternalFormatOut);
+
+bool ValidateDrawArrays(Context *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(Context *context, GLenum mode, GLsizei count, GLenum type,
+ const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut);
+
+bool ValidateDrawElementsInstanced(Context *context, GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut);
+bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLsizei primcount, rx::RangeUI *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 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);
+
+}
+
+#endif // LIBGLESV2_VALIDATION_ES_H
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES2.cpp b/src/3rdparty/angle/src/libGLESv2/validationES2.cpp
new file mode 100644
index 0000000000..f950454df0
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/validationES2.cpp
@@ -0,0 +1,980 @@
+//
+// 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 "libGLESv2/validationES2.h"
+#include "libGLESv2/validationES.h"
+#include "libGLESv2/Context.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/formatutils.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/FramebufferAttachment.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+namespace gl
+{
+
+static bool ValidateSubImageParams2D(Context *context, bool compressed, GLsizei width, GLsizei height,
+ GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type,
+ gl::Texture2D *texture)
+{
+ if (!texture)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (compressed != texture->isCompressed(level))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (format != GL_NONE)
+ {
+ if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ if (compressed)
+ {
+ if ((width % 4 != 0 && width != texture->getWidth(level)) ||
+ (height % 4 != 0 && height != texture->getHeight(level)))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ if (xoffset + width > texture->getWidth(level) ||
+ yoffset + height > texture->getHeight(level))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidateSubImageParamsCube(Context *context, bool compressed, GLsizei width, GLsizei height,
+ GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type,
+ gl::TextureCubeMap *texture)
+{
+ if (!texture)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (compressed != texture->isCompressed(target, level))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (format != GL_NONE)
+ {
+ if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ if (compressed)
+ {
+ if ((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
+ (height % 4 != 0 && height != texture->getHeight(target, 0)))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ if (xoffset + width > texture->getWidth(target, level) ||
+ yoffset + height > texture->getHeight(target, level))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ return true;
+}
+
+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, const GLvoid *pixels)
+{
+ if (!ValidTexture2DDestinationTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (!ValidImageSize(context, target, level, width, height, 1))
+ {
+ context->recordError(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->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (!isSubImage && !isCompressed && internalformat != format)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+
+ gl::Texture *texture = NULL;
+ bool textureCompressed = false;
+ GLenum textureInternalFormat = GL_NONE;
+ GLint textureLevelWidth = 0;
+ GLint textureLevelHeight = 0;
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ {
+ if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::Texture2D *tex2d = context->getTexture2D();
+ if (tex2d)
+ {
+ textureCompressed = tex2d->isCompressed(level);
+ textureInternalFormat = tex2d->getInternalFormat(level);
+ textureLevelWidth = tex2d->getWidth(level);
+ textureLevelHeight = tex2d->getHeight(level);
+ texture = tex2d;
+ }
+
+ if (isSubImage && !ValidateSubImageParams2D(context, isCompressed, width, height, xoffset, yoffset,
+ level, format, type, tex2d))
+ {
+ return false;
+ }
+
+ texture = tex2d;
+ }
+ 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->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::TextureCubeMap *texCube = context->getTextureCubeMap();
+ if (texCube)
+ {
+ textureCompressed = texCube->isCompressed(target, level);
+ textureInternalFormat = texCube->getInternalFormat(target, level);
+ textureLevelWidth = texCube->getWidth(target, level);
+ textureLevelHeight = texCube->getHeight(target, level);
+ texture = texCube;
+ }
+
+ if (isSubImage && !ValidateSubImageParamsCube(context, isCompressed, width, height, xoffset, yoffset,
+ target, level, format, type, texCube))
+ {
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (!texture)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!isSubImage && texture->isImmutable())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Verify zero border
+ if (border != 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
+ if (isCompressed)
+ {
+ if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ switch (actualInternalFormat)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (!context->getExtensions().textureCompressionDXT1)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (!context->getExtensions().textureCompressionDXT1)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (!context->getExtensions().textureCompressionDXT5)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ 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->recordError(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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ case GL_RED:
+ case GL_RG:
+ if (!context->getExtensions().textureRG)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ break;
+ default:
+ context->recordError(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->recordError(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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ case GL_SRGB_EXT:
+ case GL_SRGB_ALPHA_EXT:
+ if (!context->getExtensions().sRGB)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ context->recordError(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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ case GL_DEPTH_STENCIL_OES:
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_24_8_OES:
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ default:
+ context->recordError(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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (context->getExtensions().textureCompressionDXT3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (context->getExtensions().textureCompressionDXT5)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL_OES:
+ if (!context->getExtensions().depthTextures)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ if (target != GL_TEXTURE_2D)
+ {
+ context->recordError(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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (type == GL_FLOAT)
+ {
+ if (!context->getExtensions().textureFloat)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ }
+ else if (type == GL_HALF_FLOAT_OES)
+ {
+ if (!context->getExtensions().textureHalfFloat)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+
+bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage,
+ GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border)
+{
+ GLenum textureInternalFormat = GL_NONE;
+
+ if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
+ xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
+ {
+ return false;
+ }
+
+ gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
+ GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
+ GLenum textureFormat = gl::GetInternalFormatInfo(textureInternalFormat).format;
+
+ // [OpenGL ES 2.0.24] table 3.9
+ if (isSubImage)
+ {
+ switch (textureFormat)
+ {
+ case GL_ALPHA:
+ if (colorbufferFormat != GL_ALPHA8_EXT &&
+ colorbufferFormat != GL_RGBA4 &&
+ colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_RGBA8_OES)
+ {
+ context->recordError(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)
+ {
+ context->recordError(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)
+ {
+ context->recordError(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)
+ {
+ context->recordError(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)
+ {
+ context->recordError(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)
+ {
+ context->recordError(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:
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL_OES:
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ default:
+ context->recordError(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)
+ {
+ context->recordError(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)
+ {
+ context->recordError(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)
+ {
+ context->recordError(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)
+ {
+ context->recordError(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)
+ {
+ context->recordError(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)
+ {
+ context->recordError(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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (context->getExtensions().textureCompressionDXT3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (context->getExtensions().textureCompressionDXT5)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ 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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ default:
+ context->recordError(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->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (width < 1 || height < 1 || levels < 1)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (target == GL_TEXTURE_CUBE_MAP && width != height)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+ if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
+ {
+ context->recordError(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->recordError(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->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (levels != 1 && !context->getExtensions().textureNPOT)
+ {
+ if (!gl::isPow2(width) || !gl::isPow2(height))
+ {
+ context->recordError(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->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (!context->getExtensions().textureCompressionDXT3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (!context->getExtensions().textureCompressionDXT5)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ 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->recordError(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->recordError(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->recordError(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->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ if (target != GL_TEXTURE_2D)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ // ANGLE_depth_texture only supports 1-level textures
+ if (levels != 1)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ gl::Texture *texture = NULL;
+ switch(target)
+ {
+ case GL_TEXTURE_2D:
+ texture = context->getTexture2D();
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ texture = context->getTextureCubeMap();
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ if (!texture || texture->id() == 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (texture->isImmutable())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+// check for combinations of format and type that are valid for ReadPixels
+bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
+{
+ switch (format)
+ {
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ return false;
+ }
+ break;
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ break;
+ default:
+ return false;
+ }
+ break;
+ case GL_RG_EXT:
+ case GL_RED_EXT:
+ if (!context->getExtensions().textureRG)
+ {
+ return false;
+ }
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ return false;
+ }
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES2.h b/src/3rdparty/angle/src/libGLESv2/validationES2.h
new file mode 100644
index 0000000000..53a0b630ea
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/validationES2.h
@@ -0,0 +1,34 @@
+//
+// 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 LIBGLESV2_VALIDATION_ES2_H
+#define LIBGLESV2_VALIDATION_ES2_H
+
+#include <GLES2/gl2.h>
+
+namespace gl
+{
+
+class Context;
+
+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, const GLvoid *pixels);
+
+bool ValidateES2CopyTexImageParameters(Context* 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 ValidES2ReadFormatType(Context *context, GLenum format, GLenum type);
+
+}
+
+#endif // LIBGLESV2_VALIDATION_ES2_H
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp b/src/3rdparty/angle/src/libGLESv2/validationES3.cpp
new file mode 100644
index 0000000000..251c6ad2c4
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/validationES3.cpp
@@ -0,0 +1,1281 @@
+//
+// 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 "libGLESv2/validationES3.h"
+#include "libGLESv2/validationES.h"
+#include "libGLESv2/Context.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/formatutils.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/FramebufferAttachment.h"
+
+#include "common/mathutil.h"
+
+namespace gl
+{
+
+struct ES3FormatCombination
+{
+ GLenum internalFormat;
+ GLenum format;
+ GLenum type;
+};
+
+bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
+{
+ return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
+}
+
+typedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
+
+static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type)
+{
+ ES3FormatCombination info;
+ info.internalFormat = internalFormat;
+ info.format = format;
+ info.type = type;
+ set->insert(info);
+}
+
+ES3FormatCombinationSet BuildES3FormatSet()
+{
+ ES3FormatCombinationSet set;
+
+ // Format combinations from ES 3.0.1 spec, table 3.2
+
+ // | Internal format | Format | Type |
+ // | | | |
+ InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE );
+ InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
+ InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
+ InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
+ InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
+ InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT );
+ InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES );
+ InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE );
+ InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT );
+ InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT );
+ InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT );
+ InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT );
+ InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV );
+ InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE );
+ InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
+ InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV );
+ InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV );
+ InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT );
+ InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES );
+ InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT );
+ InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES );
+ InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT );
+ InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES );
+ InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE );
+ InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT );
+ InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT );
+ InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT );
+ InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT );
+ InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE );
+ InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT );
+ InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES );
+ InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE );
+ InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT );
+ InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT );
+ InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT );
+ InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT );
+ InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE );
+ InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT );
+ InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES );
+ InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE );
+ InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT );
+ InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT );
+ InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT );
+ InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT );
+
+ // Unsized formats
+ InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
+ InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
+ InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
+ InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
+
+ // Depth stencil formats
+ InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
+ InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
+ InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
+ InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
+ InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
+
+ // From GL_EXT_sRGB
+ InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
+
+ // From GL_OES_texture_float
+ InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT );
+
+ // From GL_OES_texture_half_float
+ InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
+ InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
+ InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT );
+ InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES );
+ InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT );
+ InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES );
+
+ // From GL_EXT_texture_format_BGRA8888
+ InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
+
+ // From GL_EXT_texture_storage
+ // | Internal format | Format | Type |
+ // | | | |
+ InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT );
+ InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT );
+ InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES );
+ InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT );
+ InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES );
+ InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
+ InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
+
+ // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
+ InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
+ InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
+ InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
+ InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
+
+ // From GL_ANGLE_depth_texture
+ InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES );
+
+ // Compressed formats
+ // From ES 3.0.1 spec, table 3.16
+ // | Internal format | Format | Type |
+ // | | | |
+ InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE);
+ InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE);
+ InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE);
+ InsertES3FormatCombo(&set, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE);
+ InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE);
+ InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE);
+ InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE);
+ InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE);
+ InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE);
+ InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE);
+ InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE);
+
+
+ // From GL_EXT_texture_compression_dxt1
+ InsertES3FormatCombo(&set, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE);
+ InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE);
+
+ // From GL_ANGLE_texture_compression_dxt3
+ InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE);
+
+ // From GL_ANGLE_texture_compression_dxt5
+ InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE);
+
+ return set;
+}
+
+static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
+{
+ // Note: dEQP 2013.4 expects an INVALID_VALUE error for TexImage3D with an invalid
+ // internal format. (dEQP-GLES3.functional.negative_api.texture.teximage3d)
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ // The type and format are valid if any supported internal format has that type and format
+ bool formatSupported = false;
+ bool typeSupported = false;
+
+ static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
+ for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
+ {
+ if (i->format == format || i->type == type)
+ {
+ const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
+ bool supported = info.textureSupport(context->getClientVersion(), context->getExtensions());
+ if (supported && i->type == type)
+ {
+ typeSupported = true;
+ }
+ if (supported && i->format == format)
+ {
+ formatSupported = true;
+ }
+
+ // Early-out if both type and format are supported now
+ if (typeSupported && formatSupported)
+ {
+ break;
+ }
+ }
+ }
+
+ if (!typeSupported || !formatSupported)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ // Check if this is a valid format combination to load texture data
+ ES3FormatCombination searchFormat;
+ searchFormat.internalFormat = internalFormat;
+ searchFormat.format = format;
+ searchFormat.type = type;
+
+ if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateES3TexImageParameters(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, const GLvoid *pixels)
+{
+ if (!ValidTexture2DDestinationTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ // Validate image size
+ if (!ValidImageSize(context, target, level, width, height, depth))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ // Verify zero border
+ if (border != 0)
+ {
+ context->recordError(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->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+
+ gl::Texture *texture = NULL;
+ bool textureCompressed = false;
+ GLenum textureInternalFormat = GL_NONE;
+ GLint textureLevelWidth = 0;
+ GLint textureLevelHeight = 0;
+ GLint textureLevelDepth = 0;
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ {
+ if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::Texture2D *texture2d = context->getTexture2D();
+ if (texture2d)
+ {
+ textureCompressed = texture2d->isCompressed(level);
+ textureInternalFormat = texture2d->getInternalFormat(level);
+ textureLevelWidth = texture2d->getWidth(level);
+ textureLevelHeight = texture2d->getHeight(level);
+ textureLevelDepth = 1;
+ texture = texture2d;
+ }
+ }
+ 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->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
+ if (textureCube)
+ {
+ textureCompressed = textureCube->isCompressed(target, level);
+ textureInternalFormat = textureCube->getInternalFormat(target, level);
+ textureLevelWidth = textureCube->getWidth(target, level);
+ textureLevelHeight = textureCube->getHeight(target, level);
+ textureLevelDepth = 1;
+ texture = textureCube;
+ }
+ }
+ 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->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::Texture3D *texture3d = context->getTexture3D();
+ if (texture3d)
+ {
+ textureCompressed = texture3d->isCompressed(level);
+ textureInternalFormat = texture3d->getInternalFormat(level);
+ textureLevelWidth = texture3d->getWidth(level);
+ textureLevelHeight = texture3d->getHeight(level);
+ textureLevelDepth = texture3d->getDepth(level);
+ texture = texture3d;
+ }
+ }
+ 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 >> level))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::Texture2DArray *texture2darray = context->getTexture2DArray();
+ if (texture2darray)
+ {
+ textureCompressed = texture2darray->isCompressed(level);
+ textureInternalFormat = texture2darray->getInternalFormat(level);
+ textureLevelWidth = texture2darray->getWidth(level);
+ textureLevelHeight = texture2darray->getHeight(level);
+ textureLevelDepth = texture2darray->getLayers(level);
+ texture = texture2darray;
+ }
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (!texture)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (texture->isImmutable() && !isSubImage)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Validate texture formats
+ GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
+ const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
+ if (isCompressed)
+ {
+ if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (!actualFormatInfo.compressed)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (target == GL_TEXTURE_3D)
+ {
+ context->recordError(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->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ // Validate sub image parameters
+ if (isSubImage)
+ {
+ if (isCompressed != textureCompressed)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (isCompressed)
+ {
+ if ((width % 4 != 0 && width != textureLevelWidth) ||
+ (height % 4 != 0 && height != textureLevelHeight))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ if (width == 0 || height == 0 || depth == 0)
+ {
+ return false;
+ }
+
+ if (xoffset < 0 || yoffset < 0 || zoffset < 0)
+ {
+ context->recordError(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->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (xoffset + width > textureLevelWidth ||
+ yoffset + height > textureLevelHeight ||
+ zoffset + depth > textureLevelDepth)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+
+ // Check for pixel unpack buffer related API errors
+ gl::Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
+ if (pixelUnpackBuffer != NULL)
+ {
+ // ...the data would be unpacked from the buffer object such that the memory reads required
+ // would exceed the data store size.
+ size_t widthSize = static_cast<size_t>(width);
+ size_t heightSize = static_cast<size_t>(height);
+ size_t depthSize = static_cast<size_t>(depth);
+ GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
+
+ size_t pixelBytes = static_cast<size_t>(gl::GetInternalFormatInfo(sizedFormat).pixelBytes);
+
+ if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) ||
+ !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) ||
+ !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes))
+ {
+ // Overflow past the end of the buffer
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes;
+ size_t offset = reinterpret_cast<size_t>(pixels);
+
+ if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) ||
+ ((offset + copyBytes) > static_cast<size_t>(pixelUnpackBuffer->getSize())))
+ {
+ // Overflow past the end of the buffer
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
+ // indicated by type.
+ size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
+
+ if ((offset % dataBytesPerPixel) != 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // ...the buffer object's data store is currently mapped.
+ if (pixelUnpackBuffer->isMapped())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+struct EffectiveInternalFormatInfo
+{
+ GLenum mEffectiveFormat;
+ GLenum mDestFormat;
+ GLuint mMinRedBits;
+ GLuint mMaxRedBits;
+ GLuint mMinGreenBits;
+ GLuint mMaxGreenBits;
+ GLuint mMinBlueBits;
+ GLuint mMaxBlueBits;
+ GLuint mMinAlphaBits;
+ GLuint mMaxAlphaBits;
+
+ EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
+ GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
+ GLuint minAlphaBits, GLuint maxAlphaBits)
+ : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
+ mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
+ mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
+ mMaxAlphaBits(maxAlphaBits) {};
+};
+
+typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
+
+static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
+{
+ EffectiveInternalFormatList list;
+
+ // 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 |
+ list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
+ list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
+ list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
+ list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
+ list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
+ list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
+ list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
+ list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
+ list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
+
+ return list;
+}
+
+static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
+{
+ EffectiveInternalFormatList list;
+
+ // 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 | Dest Format | R | G | B | A |
+ list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
+ list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
+ list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
+ list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
+ list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
+ list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
+ list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
+ list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
+
+ return list;
+}
+
+static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
+ GLenum *outEffectiveFormat)
+{
+ const EffectiveInternalFormatList *list = NULL;
+ GLenum targetFormat = GL_NONE;
+
+ if (destFormat.pixelBytes > 0)
+ {
+ static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
+ list = &sizedList;
+ }
+ else
+ {
+ static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
+ list = &unsizedList;
+ targetFormat = destFormat.format;
+ }
+
+ for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
+ {
+ const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
+ if ((formatInfo.mDestFormat == targetFormat) &&
+ (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
+ (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
+ (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
+ (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
+ {
+ *outEffectiveFormat = formatInfo.mEffectiveFormat;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+struct CopyConversion
+{
+ GLenum mTextureFormat;
+ GLenum mFramebufferFormat;
+
+ CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
+ : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
+
+ bool operator<(const CopyConversion& other) const
+ {
+ return memcmp(this, &other, sizeof(CopyConversion)) < 0;
+ }
+};
+
+typedef std::set<CopyConversion> CopyConversionSet;
+
+static CopyConversionSet BuildValidES3CopyTexImageCombinations()
+{
+ CopyConversionSet set;
+
+ // From ES 3.0.1 spec, table 3.15
+ set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
+ set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
+ set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
+ set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
+ set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
+ set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
+ set.insert(CopyConversion(GL_RED, GL_RED));
+ set.insert(CopyConversion(GL_RED, GL_RG));
+ set.insert(CopyConversion(GL_RED, GL_RGB));
+ set.insert(CopyConversion(GL_RED, GL_RGBA));
+ set.insert(CopyConversion(GL_RG, GL_RG));
+ set.insert(CopyConversion(GL_RG, GL_RGB));
+ set.insert(CopyConversion(GL_RG, GL_RGBA));
+ set.insert(CopyConversion(GL_RGB, GL_RGB));
+ set.insert(CopyConversion(GL_RGB, GL_RGBA));
+ set.insert(CopyConversion(GL_RGBA, GL_RGBA));
+
+ // Necessary for ANGLE back-buffers
+ set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
+ set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
+ set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
+ set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
+ set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
+ set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
+ set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
+
+ set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
+ set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
+ set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
+ set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
+ set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
+ set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
+ set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
+ set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
+ set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
+ set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
+
+ return set;
+}
+
+static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
+{
+ const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
+ const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
+
+ static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
+ if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
+ {
+ // 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 ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
+ {
+ return false;
+ }
+
+ if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
+ ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
+ {
+ return false;
+ }
+
+ if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+ textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
+ textureInternalFormatInfo.componentType == GL_FLOAT) &&
+ !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+ framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
+ framebufferInternalFormatInfo.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 (framebufferInternalFormatInfo.pixelBytes > 0)
+ {
+ sourceEffectiveFormat = &framebufferInternalFormatInfo;
+ }
+ 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.
+ const FormatType &typeInfo = GetFormatTypeInfo(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
+ sourceEffectiveFormat = &GetInternalFormatInfo(typeInfo.internalFormat);
+ }
+ }
+ 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 (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
+ {
+ GLenum effectiveFormat;
+ if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
+ {
+ sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
+ {
+ // SRGB buffers can only be copied to sized format destinations according to table 3.18
+ if ((textureInternalFormatInfo.pixelBytes > 0) &&
+ (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
+ (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
+ (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
+ (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
+ {
+ sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ return false;
+ }
+ }
+
+ if (textureInternalFormatInfo.pixelBytes > 0)
+ {
+ // 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 (textureInternalFormatInfo.redBits != sourceEffectiveFormat->redBits ||
+ textureInternalFormatInfo.greenBits != sourceEffectiveFormat->greenBits ||
+ textureInternalFormatInfo.blueBits != sourceEffectiveFormat->blueBits ||
+ textureInternalFormatInfo.alphaBits != sourceEffectiveFormat->alphaBits)
+ {
+ return false;
+ }
+ }
+
+
+ return true; // A conversion function exists, and no rule in the specification has precluded conversion
+ // between these formats.
+ }
+
+ return false;
+}
+
+bool ValidateES3CopyTexImageParameters(Context *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)
+{
+ GLenum textureInternalFormat;
+ if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
+ xoffset, yoffset, zoffset, x, y, width, height,
+ border, &textureInternalFormat))
+ {
+ return false;
+ }
+
+ gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
+
+ if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
+ GLenum colorbufferInternalFormat = source->getInternalFormat();
+
+ if (isSubImage)
+ {
+ if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
+ context->getState().getReadFramebuffer()->id()))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ else
+ {
+ if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
+ context->getState().getReadFramebuffer()->id()))
+ {
+ context->recordError(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 ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
+ GLsizei width, GLsizei height, GLsizei depth)
+{
+ if (width < 1 || height < 1 || depth < 1 || levels < 1)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+
+ gl::Texture *texture = NULL;
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ {
+ texture = context->getTexture2D();
+
+ if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+ static_cast<GLuint>(height) > caps.max2DTextureSize)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_CUBE_MAP:
+ {
+ texture = context->getTextureCubeMap();
+
+ if (width != height)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_3D:
+ {
+ texture = context->getTexture3D();
+
+ if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
+ static_cast<GLuint>(height) > caps.max3DTextureSize ||
+ static_cast<GLuint>(depth) > caps.max3DTextureSize)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ texture = context->getTexture2DArray();
+
+ if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+ static_cast<GLuint>(height) > caps.max2DTextureSize ||
+ static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (!texture || texture->id() == 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (texture->isImmutable())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+ if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (formatInfo.pixelBytes == 0)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer)
+{
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (layer < 0)
+ {
+ context->recordError(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->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
+ if (texArray->isCompressed(level))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_3D:
+ {
+ if (level > gl::log2(caps.max3DTextureSize))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
+ if (tex3d->isCompressed(level))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type)
+{
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
+
+ switch (format)
+ {
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ if (internalFormat != GL_RGB10_A2)
+ {
+ return false;
+ }
+ break;
+ case GL_FLOAT:
+ if (internalFormatInfo.componentType != GL_FLOAT)
+ {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ break;
+ case GL_RGBA_INTEGER:
+ switch (type)
+ {
+ case GL_INT:
+ if (internalFormatInfo.componentType != GL_INT)
+ {
+ return false;
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
+ {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ break;
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ break;
+ default:
+ return false;
+ }
+ break;
+ case GL_RG_EXT:
+ case GL_RED_EXT:
+ if (!context->getExtensions().textureRG)
+ {
+ return false;
+ }
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments,
+ const GLenum* attachments)
+{
+ bool defaultFramebuffer = false;
+
+ switch (target)
+ {
+ case GL_DRAW_FRAMEBUFFER:
+ case GL_FRAMEBUFFER:
+ defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0;
+ break;
+ case GL_READ_FRAMEBUFFER:
+ defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0;
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ for (int i = 0; i < numAttachments; ++i)
+ {
+ if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
+ {
+ if (defaultFramebuffer)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ else
+ {
+ switch (attachments[i])
+ {
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (defaultFramebuffer)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_COLOR:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ if (!defaultFramebuffer)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool ValidateClearBuffer(Context *context)
+{
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
+ if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
+{
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateGetUniformBase(context, program, location);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.h b/src/3rdparty/angle/src/libGLESv2/validationES3.h
new file mode 100644
index 0000000000..cafacca601
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/validationES3.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.
+//
+
+// validationES3.h: Validation functions for OpenGL ES 3.0 entry point parameters
+
+#ifndef LIBGLESV2_VALIDATION_ES3_H
+#define LIBGLESV2_VALIDATION_ES3_H
+
+#include <GLES3/gl3.h>
+
+namespace gl
+{
+
+class Context;
+
+bool ValidateES3TexImageParameters(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, const GLvoid *pixels);
+
+bool ValidateES3CopyTexImageParameters(Context *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 ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
+ GLsizei width, GLsizei height, GLsizei depth);
+
+bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer);
+
+bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type);
+
+bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments,
+ const GLenum* attachments);
+
+bool ValidateClearBuffer(Context *context);
+
+bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params);
+
+}
+
+#endif // LIBGLESV2_VALIDATION_ES3_H